mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 12:39:28 +00:00
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.
148 lines
5.5 KiB
C
148 lines
5.5 KiB
C
/* 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;
|
|
}
|