1 /* 2 * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <openssl/asn1.h> 11 #include <openssl/x509.h> 12 #include <openssl/x509v3.h> 13 #include <openssl/err.h> 14 15 #include "pcy_local.h" 16 17 static int node_cmp(const X509_POLICY_NODE *const *a, 18 const X509_POLICY_NODE *const *b) 19 { 20 return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy); 21 } 22 23 STACK_OF(X509_POLICY_NODE) *ossl_policy_node_cmp_new(void) 24 { 25 return sk_X509_POLICY_NODE_new(node_cmp); 26 } 27 28 X509_POLICY_NODE *ossl_policy_tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes, 29 const ASN1_OBJECT *id) 30 { 31 X509_POLICY_DATA n; 32 X509_POLICY_NODE l; 33 int idx; 34 35 n.valid_policy = (ASN1_OBJECT *)id; 36 l.data = &n; 37 38 idx = sk_X509_POLICY_NODE_find(nodes, &l); 39 return sk_X509_POLICY_NODE_value(nodes, idx); 40 41 } 42 43 X509_POLICY_NODE *ossl_policy_level_find_node(const X509_POLICY_LEVEL *level, 44 const X509_POLICY_NODE *parent, 45 const ASN1_OBJECT *id) 46 { 47 X509_POLICY_NODE *node; 48 int i; 49 for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { 50 node = sk_X509_POLICY_NODE_value(level->nodes, i); 51 if (node->parent == parent) { 52 if (!OBJ_cmp(node->data->valid_policy, id)) 53 return node; 54 } 55 } 56 return NULL; 57 } 58 59 X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level, 60 X509_POLICY_DATA *data, 61 X509_POLICY_NODE *parent, 62 X509_POLICY_TREE *tree, 63 int extra_data) 64 { 65 X509_POLICY_NODE *node; 66 67 /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */ 68 if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum) 69 return NULL; 70 71 node = OPENSSL_zalloc(sizeof(*node)); 72 if (node == NULL) 73 return NULL; 74 node->data = data; 75 node->parent = parent; 76 if (level != NULL) { 77 if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { 78 if (level->anyPolicy) 79 goto node_error; 80 level->anyPolicy = node; 81 } else { 82 83 if (level->nodes == NULL) 84 level->nodes = ossl_policy_node_cmp_new(); 85 if (level->nodes == NULL) { 86 ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB); 87 goto node_error; 88 } 89 if (!sk_X509_POLICY_NODE_push(level->nodes, node)) { 90 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 91 goto node_error; 92 } 93 } 94 } 95 96 if (extra_data) { 97 if (tree->extra_data == NULL) 98 tree->extra_data = sk_X509_POLICY_DATA_new_null(); 99 if (tree->extra_data == NULL) { 100 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 101 goto extra_data_error; 102 } 103 if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) { 104 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 105 goto extra_data_error; 106 } 107 } 108 109 tree->node_count++; 110 if (parent) 111 parent->nchild++; 112 113 return node; 114 115 extra_data_error: 116 if (level != NULL) { 117 if (level->anyPolicy == node) 118 level->anyPolicy = NULL; 119 else 120 (void) sk_X509_POLICY_NODE_pop(level->nodes); 121 } 122 123 node_error: 124 ossl_policy_node_free(node); 125 return NULL; 126 } 127 128 void ossl_policy_node_free(X509_POLICY_NODE *node) 129 { 130 OPENSSL_free(node); 131 } 132 133 /* 134 * See if a policy node matches a policy OID. If mapping enabled look through 135 * expected policy set otherwise just valid policy. 136 */ 137 138 int ossl_policy_node_match(const X509_POLICY_LEVEL *lvl, 139 const X509_POLICY_NODE *node, const ASN1_OBJECT *oid) 140 { 141 int i; 142 ASN1_OBJECT *policy_oid; 143 const X509_POLICY_DATA *x = node->data; 144 145 if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP) 146 || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) { 147 if (!OBJ_cmp(x->valid_policy, oid)) 148 return 1; 149 return 0; 150 } 151 152 for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) { 153 policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i); 154 if (!OBJ_cmp(policy_oid, oid)) 155 return 1; 156 } 157 return 0; 158 159 } 160