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