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,166 @@
|
||||
/* Provenance: openssl/openssl tree_init (fixed).
|
||||
* repo: openssl/openssl
|
||||
* commit: 879f7080d7e141f415c79eaa3a8ac4a3dad0348b
|
||||
* parent: 969327390220aee7515a4054d5189186402d6687
|
||||
* commit_url: https://github.com/openssl/openssl/commit/879f7080d7e141f415c79eaa3a8ac4a3dad0348b
|
||||
* cve: CVE-2023-0464
|
||||
* license: Apache-2.0
|
||||
* function: tree_init
|
||||
* relpath: crypto/x509v3/pcy_tree.c
|
||||
*/
|
||||
|
||||
static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
|
||||
unsigned int flags)
|
||||
{
|
||||
X509_POLICY_TREE *tree;
|
||||
X509_POLICY_LEVEL *level;
|
||||
const X509_POLICY_CACHE *cache;
|
||||
X509_POLICY_DATA *data = NULL;
|
||||
int ret = X509_PCY_TREE_VALID;
|
||||
int n = sk_X509_num(certs) - 1; /* RFC5280 paths omit the TA */
|
||||
int explicit_policy = (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : n+1;
|
||||
int any_skip = (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : n+1;
|
||||
int map_skip = (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : n+1;
|
||||
int i;
|
||||
|
||||
*ptree = NULL;
|
||||
|
||||
/* Can't do anything with just a trust anchor */
|
||||
if (n == 0)
|
||||
return X509_PCY_TREE_EMPTY;
|
||||
|
||||
/*
|
||||
* First setup the policy cache in all n non-TA certificates, this will be
|
||||
* used in X509_verify_cert() which will invoke the verify callback for all
|
||||
* certificates with invalid policy extensions.
|
||||
*/
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
X509 *x = sk_X509_value(certs, i);
|
||||
|
||||
/* Call for side-effect of computing hash and caching extensions */
|
||||
X509_check_purpose(x, -1, 0);
|
||||
|
||||
/* If cache is NULL, likely ENOMEM: return immediately */
|
||||
if (policy_cache_set(x) == NULL)
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point check for invalid policies and required explicit policy.
|
||||
* Note that the explicit_policy counter is a count-down to zero, with the
|
||||
* requirement kicking in if and once it does that. The counter is
|
||||
* decremented for every non-self-issued certificate in the path, but may
|
||||
* be further reduced by policy constraints in a non-leaf certificate.
|
||||
*
|
||||
* The ultimate policy set is the intersection of all the policies along
|
||||
* the path, if we hit a certificate with an empty policy set, and explicit
|
||||
* policy is required we're done.
|
||||
*/
|
||||
for (i = n - 1;
|
||||
i >= 0 && (explicit_policy > 0 || (ret & X509_PCY_TREE_EMPTY) == 0);
|
||||
i--) {
|
||||
X509 *x = sk_X509_value(certs, i);
|
||||
uint32_t ex_flags = X509_get_extension_flags(x);
|
||||
|
||||
/* All the policies are already cached, we can return early */
|
||||
if (ex_flags & EXFLAG_INVALID_POLICY)
|
||||
return X509_PCY_TREE_INVALID;
|
||||
|
||||
/* Access the cache which we now know exists */
|
||||
cache = policy_cache_set(x);
|
||||
|
||||
if ((ret & X509_PCY_TREE_VALID) && cache->data == NULL)
|
||||
ret = X509_PCY_TREE_EMPTY;
|
||||
if (explicit_policy > 0) {
|
||||
if (!(ex_flags & EXFLAG_SI))
|
||||
explicit_policy--;
|
||||
if ((cache->explicit_skip >= 0)
|
||||
&& (cache->explicit_skip < explicit_policy))
|
||||
explicit_policy = cache->explicit_skip;
|
||||
}
|
||||
}
|
||||
|
||||
if (explicit_policy == 0)
|
||||
ret |= X509_PCY_TREE_EXPLICIT;
|
||||
if ((ret & X509_PCY_TREE_VALID) == 0)
|
||||
return ret;
|
||||
|
||||
/* If we get this far initialize the tree */
|
||||
if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) {
|
||||
X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
}
|
||||
|
||||
/* Limit the growth of the tree to mitigate CVE-2023-0464 */
|
||||
tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;
|
||||
|
||||
/*
|
||||
* http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
|
||||
*
|
||||
* The top level is implicitly for the trust anchor with valid expected
|
||||
* policies of anyPolicy. (RFC 5280 has the TA at depth 0 and the leaf at
|
||||
* depth n, we have the leaf at depth 0 and the TA at depth n).
|
||||
*/
|
||||
if ((tree->levels = OPENSSL_zalloc(sizeof(*tree->levels)*(n+1))) == NULL) {
|
||||
OPENSSL_free(tree);
|
||||
X509V3err(X509V3_F_TREE_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
}
|
||||
tree->nlevel = n+1;
|
||||
level = tree->levels;
|
||||
if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL)
|
||||
goto bad_tree;
|
||||
if (level_add_node(level, data, NULL, tree, 1) == NULL) {
|
||||
policy_data_free(data);
|
||||
goto bad_tree;
|
||||
}
|
||||
|
||||
/*
|
||||
* In this pass initialize all the tree levels and whether anyPolicy and
|
||||
* policy mapping are inhibited at each level.
|
||||
*/
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
X509 *x = sk_X509_value(certs, i);
|
||||
uint32_t ex_flags = X509_get_extension_flags(x);
|
||||
|
||||
/* Access the cache which we now know exists */
|
||||
cache = policy_cache_set(x);
|
||||
|
||||
X509_up_ref(x);
|
||||
(++level)->cert = x;
|
||||
|
||||
if (!cache->anyPolicy)
|
||||
level->flags |= X509_V_FLAG_INHIBIT_ANY;
|
||||
|
||||
/* Determine inhibit any and inhibit map flags */
|
||||
if (any_skip == 0) {
|
||||
/*
|
||||
* Any matching allowed only if certificate is self issued and not
|
||||
* the last in the chain.
|
||||
*/
|
||||
if (!(ex_flags & EXFLAG_SI) || (i == 0))
|
||||
level->flags |= X509_V_FLAG_INHIBIT_ANY;
|
||||
} else {
|
||||
if (!(ex_flags & EXFLAG_SI))
|
||||
any_skip--;
|
||||
if ((cache->any_skip >= 0) && (cache->any_skip < any_skip))
|
||||
any_skip = cache->any_skip;
|
||||
}
|
||||
|
||||
if (map_skip == 0)
|
||||
level->flags |= X509_V_FLAG_INHIBIT_MAP;
|
||||
else {
|
||||
if (!(ex_flags & EXFLAG_SI))
|
||||
map_skip--;
|
||||
if ((cache->map_skip >= 0) && (cache->map_skip < map_skip))
|
||||
map_skip = cache->map_skip;
|
||||
}
|
||||
}
|
||||
|
||||
*ptree = tree;
|
||||
return ret;
|
||||
|
||||
bad_tree:
|
||||
X509_policy_tree_free(tree);
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
}
|
||||
Reference in New Issue
Block a user