mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-20 21:49:28 +00:00
feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
/* Provenance: openssl/openssl check_chain_extensions (fixed).
|
||||
* repo: openssl/openssl
|
||||
* commit: 2a40b7bc7b94dd7de897a74571e7024f0cf0d63b
|
||||
* parent: cfd74383d9b06f85cb1e166180346115a3f9a452
|
||||
* commit_url: https://github.com/openssl/openssl/commit/2a40b7bc7b94dd7de897a74571e7024f0cf0d63b
|
||||
* cve: CVE-2021-3450
|
||||
* license: OpenSSL License
|
||||
* function: check_chain_extensions
|
||||
* relpath: crypto/x509/x509_vfy.c
|
||||
*/
|
||||
|
||||
static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
{
|
||||
int i, must_be_ca, plen = 0;
|
||||
X509 *x;
|
||||
int proxy_path_length = 0;
|
||||
int purpose;
|
||||
int allow_proxy_certs;
|
||||
int num = sk_X509_num(ctx->chain);
|
||||
|
||||
/*-
|
||||
* must_be_ca can have 1 of 3 values:
|
||||
* -1: we accept both CA and non-CA certificates, to allow direct
|
||||
* use of self-signed certificates (which are marked as CA).
|
||||
* 0: we only accept non-CA certificates. This is currently not
|
||||
* used, but the possibility is present for future extensions.
|
||||
* 1: we only accept CA certificates. This is currently used for
|
||||
* all certificates in the chain except the leaf certificate.
|
||||
*/
|
||||
must_be_ca = -1;
|
||||
|
||||
/* CRL path validation */
|
||||
if (ctx->parent) {
|
||||
allow_proxy_certs = 0;
|
||||
purpose = X509_PURPOSE_CRL_SIGN;
|
||||
} else {
|
||||
allow_proxy_certs =
|
||||
! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
|
||||
purpose = ctx->param->purpose;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
int ret;
|
||||
x = sk_X509_value(ctx->chain, i);
|
||||
if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
||||
&& (x->ex_flags & EXFLAG_CRITICAL)) {
|
||||
if (!verify_cb_cert(ctx, x, i,
|
||||
X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION))
|
||||
return 0;
|
||||
}
|
||||
if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
|
||||
if (!verify_cb_cert(ctx, x, i,
|
||||
X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED))
|
||||
return 0;
|
||||
}
|
||||
ret = X509_check_ca(x);
|
||||
switch (must_be_ca) {
|
||||
case -1:
|
||||
if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
|
||||
&& (ret != 1) && (ret != 0)) {
|
||||
ret = 0;
|
||||
ctx->error = X509_V_ERR_INVALID_CA;
|
||||
} else
|
||||
ret = 1;
|
||||
break;
|
||||
case 0:
|
||||
if (ret != 0) {
|
||||
ret = 0;
|
||||
ctx->error = X509_V_ERR_INVALID_NON_CA;
|
||||
} else
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
/* X509_V_FLAG_X509_STRICT is implicit for intermediate CAs */
|
||||
if ((ret == 0)
|
||||
|| ((i + 1 < num || ctx->param->flags & X509_V_FLAG_X509_STRICT)
|
||||
&& (ret != 1))) {
|
||||
ret = 0;
|
||||
ctx->error = X509_V_ERR_INVALID_CA;
|
||||
} else
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
if (ret > 0
|
||||
&& (ctx->param->flags & X509_V_FLAG_X509_STRICT) && num > 1) {
|
||||
/* Check for presence of explicit elliptic curve parameters */
|
||||
ret = check_curve(x);
|
||||
if (ret < 0) {
|
||||
ctx->error = X509_V_ERR_UNSPECIFIED;
|
||||
ret = 0;
|
||||
} else if (ret == 0) {
|
||||
ctx->error = X509_V_ERR_EC_KEY_EXPLICIT_PARAMS;
|
||||
}
|
||||
}
|
||||
if (ret > 0
|
||||
&& (x->ex_flags & EXFLAG_CA) == 0
|
||||
&& x->ex_pathlen != -1
|
||||
&& (ctx->param->flags & X509_V_FLAG_X509_STRICT)) {
|
||||
ctx->error = X509_V_ERR_INVALID_EXTENSION;
|
||||
ret = 0;
|
||||
}
|
||||
if (ret == 0 && !verify_cb_cert(ctx, x, i, X509_V_OK))
|
||||
return 0;
|
||||
/* check_purpose() makes the callback as needed */
|
||||
if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca))
|
||||
return 0;
|
||||
/* Check pathlen */
|
||||
if ((i > 1) && (x->ex_pathlen != -1)
|
||||
&& (plen > (x->ex_pathlen + proxy_path_length))) {
|
||||
if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED))
|
||||
return 0;
|
||||
}
|
||||
/* Increment path length if not a self issued intermediate CA */
|
||||
if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0)
|
||||
plen++;
|
||||
/*
|
||||
* If this certificate is a proxy certificate, the next certificate
|
||||
* must be another proxy certificate or a EE certificate. If not,
|
||||
* the next certificate must be a CA certificate.
|
||||
*/
|
||||
if (x->ex_flags & EXFLAG_PROXY) {
|
||||
/*
|
||||
* RFC3820, 4.1.3 (b)(1) stipulates that if pCPathLengthConstraint
|
||||
* is less than max_path_length, the former should be copied to
|
||||
* the latter, and 4.1.4 (a) stipulates that max_path_length
|
||||
* should be verified to be larger than zero and decrement it.
|
||||
*
|
||||
* Because we're checking the certs in the reverse order, we start
|
||||
* with verifying that proxy_path_length isn't larger than pcPLC,
|
||||
* and copy the latter to the former if it is, and finally,
|
||||
* increment proxy_path_length.
|
||||
*/
|
||||
if (x->ex_pcpathlen != -1) {
|
||||
if (proxy_path_length > x->ex_pcpathlen) {
|
||||
if (!verify_cb_cert(ctx, x, i,
|
||||
X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED))
|
||||
return 0;
|
||||
}
|
||||
proxy_path_length = x->ex_pcpathlen;
|
||||
}
|
||||
proxy_path_length++;
|
||||
must_be_ca = 0;
|
||||
} else
|
||||
must_be_ca = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user