diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2004-03-23 14:14:35 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2004-03-23 14:14:35 +0000 |
commit | 4acc3e907d29d8d61ae7e11ad7985a986332a1c1 (patch) | |
tree | 97b0e178ea69ae6786e979d62cc480180c7431af | |
parent | 9449e38504dea3e1500cd58f40c1b2b904ef843d (diff) |
Initial support for certificate policy checking and evaluation.
This is currently *very* experimental and needs to be more fully integrated
with the main verification code.
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | crypto/asn1/x_x509.c | 3 | ||||
-rw-r--r-- | crypto/ossl_typ.h | 5 | ||||
-rw-r--r-- | crypto/stack/safestack.h | 63 | ||||
-rw-r--r-- | crypto/x509/x509.h | 1 | ||||
-rw-r--r-- | crypto/x509/x509_vfy.h | 38 | ||||
-rw-r--r-- | crypto/x509v3/Makefile.ssl | 8 | ||||
-rw-r--r-- | crypto/x509v3/pcy_cache.c | 286 | ||||
-rw-r--r-- | crypto/x509v3/pcy_data.c | 123 | ||||
-rw-r--r-- | crypto/x509v3/pcy_int.h | 220 | ||||
-rw-r--r-- | crypto/x509v3/pcy_lib.c | 165 | ||||
-rw-r--r-- | crypto/x509v3/pcy_map.c | 186 | ||||
-rw-r--r-- | crypto/x509v3/pcy_node.c | 159 | ||||
-rw-r--r-- | crypto/x509v3/pcy_tree.c | 681 | ||||
-rw-r--r-- | crypto/x509v3/x509v3.h | 2 |
15 files changed, 1942 insertions, 3 deletions
@@ -4,6 +4,11 @@ Changes between 0.9.7c and 0.9.8 [xx XXX xxxx] + *) Preliminary support for certificate policy evaluation and checking. This + is initially intended to pass the tests outlined in "Conformance Testing + of Relying Party Client Certificate Path Processing Logic" v1.07. + [Steve Henson] + *) bn_dup_expand() has been deprecated, it was introduced in 0.9.7 and remained unused and not that useful. A variety of other little bignum tweaks and fixes have also been made continuing on from the audit (see diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c index f71ba267d9..eff2290c2b 100644 --- a/crypto/asn1/x_x509.c +++ b/crypto/asn1/x_x509.c @@ -79,6 +79,8 @@ ASN1_SEQUENCE(X509_CINF) = { IMPLEMENT_ASN1_FUNCTIONS(X509_CINF) /* X509 top level structure needs a bit of customisation */ +extern void policy_cache_free(X509_POLICY_CACHE *cache); + static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) { X509 *ret = (X509 *)*pval; @@ -106,6 +108,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it) X509_CERT_AUX_free(ret->aux); ASN1_OCTET_STRING_free(ret->skid); AUTHORITY_KEYID_free(ret->akid); + policy_cache_free(ret->policy_cache); if (ret->name != NULL) OPENSSL_free(ret->name); break; diff --git a/crypto/ossl_typ.h b/crypto/ossl_typ.h index 46200a80b1..2977b10827 100644 --- a/crypto/ossl_typ.h +++ b/crypto/ossl_typ.h @@ -119,6 +119,11 @@ typedef struct conf_st CONF; typedef struct engine_st ENGINE; +typedef struct X509_POLICY_NODE_st X509_POLICY_NODE; +typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL; +typedef struct X509_POLICY_TREE_st X509_POLICY_TREE; +typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE; + /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */ #define DECLARE_PKCS12_STACK_OF(type) /* Nothing */ #define IMPLEMENT_PKCS12_STACK_OF(type) /* Nothing */ diff --git a/crypto/stack/safestack.h b/crypto/stack/safestack.h index 3110e50a84..cd9e780e4d 100644 --- a/crypto/stack/safestack.h +++ b/crypto/stack/safestack.h @@ -1359,6 +1359,69 @@ STACK_OF(type) \ #define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st)) #define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st)) +#define sk_X509_POLICY_DATA_new(st) SKM_sk_new(X509_POLICY_DATA, (st)) +#define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA) +#define sk_X509_POLICY_DATA_free(st) SKM_sk_free(X509_POLICY_DATA, (st)) +#define sk_X509_POLICY_DATA_num(st) SKM_sk_num(X509_POLICY_DATA, (st)) +#define sk_X509_POLICY_DATA_value(st, i) SKM_sk_value(X509_POLICY_DATA, (st), (i)) +#define sk_X509_POLICY_DATA_set(st, i, val) SKM_sk_set(X509_POLICY_DATA, (st), (i), (val)) +#define sk_X509_POLICY_DATA_zero(st) SKM_sk_zero(X509_POLICY_DATA, (st)) +#define sk_X509_POLICY_DATA_push(st, val) SKM_sk_push(X509_POLICY_DATA, (st), (val)) +#define sk_X509_POLICY_DATA_unshift(st, val) SKM_sk_unshift(X509_POLICY_DATA, (st), (val)) +#define sk_X509_POLICY_DATA_find(st, val) SKM_sk_find(X509_POLICY_DATA, (st), (val)) +#define sk_X509_POLICY_DATA_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_DATA, (st), (val)) +#define sk_X509_POLICY_DATA_delete(st, i) SKM_sk_delete(X509_POLICY_DATA, (st), (i)) +#define sk_X509_POLICY_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_DATA, (st), (ptr)) +#define sk_X509_POLICY_DATA_insert(st, val, i) SKM_sk_insert(X509_POLICY_DATA, (st), (val), (i)) +#define sk_X509_POLICY_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_DATA, (st), (cmp)) +#define sk_X509_POLICY_DATA_dup(st) SKM_sk_dup(X509_POLICY_DATA, st) +#define sk_X509_POLICY_DATA_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_DATA, (st), (free_func)) +#define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st)) +#define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st)) +#define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st)) + +#define sk_X509_POLICY_NODE_new(st) SKM_sk_new(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE) +#define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i)) +#define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val)) +#define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i)) +#define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr)) +#define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i)) +#define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp)) +#define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st) +#define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func)) +#define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st)) + +#define sk_X509_POLICY_REF_new(st) SKM_sk_new(X509_POLICY_REF, (st)) +#define sk_X509_POLICY_REF_new_null() SKM_sk_new_null(X509_POLICY_REF) +#define sk_X509_POLICY_REF_free(st) SKM_sk_free(X509_POLICY_REF, (st)) +#define sk_X509_POLICY_REF_num(st) SKM_sk_num(X509_POLICY_REF, (st)) +#define sk_X509_POLICY_REF_value(st, i) SKM_sk_value(X509_POLICY_REF, (st), (i)) +#define sk_X509_POLICY_REF_set(st, i, val) SKM_sk_set(X509_POLICY_REF, (st), (i), (val)) +#define sk_X509_POLICY_REF_zero(st) SKM_sk_zero(X509_POLICY_REF, (st)) +#define sk_X509_POLICY_REF_push(st, val) SKM_sk_push(X509_POLICY_REF, (st), (val)) +#define sk_X509_POLICY_REF_unshift(st, val) SKM_sk_unshift(X509_POLICY_REF, (st), (val)) +#define sk_X509_POLICY_REF_find(st, val) SKM_sk_find(X509_POLICY_REF, (st), (val)) +#define sk_X509_POLICY_REF_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_REF, (st), (val)) +#define sk_X509_POLICY_REF_delete(st, i) SKM_sk_delete(X509_POLICY_REF, (st), (i)) +#define sk_X509_POLICY_REF_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_REF, (st), (ptr)) +#define sk_X509_POLICY_REF_insert(st, val, i) SKM_sk_insert(X509_POLICY_REF, (st), (val), (i)) +#define sk_X509_POLICY_REF_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_REF, (st), (cmp)) +#define sk_X509_POLICY_REF_dup(st) SKM_sk_dup(X509_POLICY_REF, st) +#define sk_X509_POLICY_REF_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_REF, (st), (free_func)) +#define sk_X509_POLICY_REF_shift(st) SKM_sk_shift(X509_POLICY_REF, (st)) +#define sk_X509_POLICY_REF_pop(st) SKM_sk_pop(X509_POLICY_REF, (st)) +#define sk_X509_POLICY_REF_sort(st) SKM_sk_sort(X509_POLICY_REF, (st)) + #define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st)) #define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE) #define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st)) diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index e7d2c5ba52..b73a699598 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -285,6 +285,7 @@ struct x509_st unsigned long ex_nscert; ASN1_OCTET_STRING *skid; struct AUTHORITY_KEYID_st *akid; + X509_POLICY_CACHE *policy_cache; #ifndef OPENSSL_NO_SHA unsigned char sha1_hash[SHA_DIGEST_LENGTH]; #endif diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index 7e24ded810..6cf3d70ff7 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -325,6 +325,14 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ #define X509_V_FLAG_IGNORE_CRITICAL 0x10 /* Disable workarounds for broken certificates */ #define X509_V_FLAG_X509_STRICT 0x20 +/* Enable policy checking */ +#define X509_V_FLAG_POLICY_CHECK 0x40 +/* Policy variable require-explicit-policy */ +#define X509_V_FLAG_EXPLICIT_POLICY 0x80 +/* Policy variable inhibit-policy-mapping */ +#define X509_V_FLAG_INHIBIT_ANY 0x100 +/* Policy variable inhibit-any-policy */ +#define X509_V_FLAG_INHIBIT_MAP 0x200 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, X509_NAME *name); @@ -410,6 +418,36 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, long flags, time_t t); void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, int (*verify_cb)(int, X509_STORE_CTX *)); +int X509_policy_check(X509_POLICY_TREE **ptree, int *explicit, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, + unsigned int flags); + +void X509_policy_tree_free(X509_POLICY_TREE *tree); + +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree); +X509_POLICY_LEVEL * + X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i); + +STACK_OF(X509_POLICY_NODE) * + X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree); + +STACK_OF(X509_POLICY_NODE) * + X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree); + +int X509_policy_level_node_count(X509_POLICY_LEVEL *level); + +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i); + +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node); + +STACK_OF(POLICYQUALIFIER) * + X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node); +const X509_POLICY_NODE * + X509_policy_node_get0_parent(const X509_POLICY_NODE *node); + +void X509_policy_lib_init(void); + #ifdef __cplusplus } #endif diff --git a/crypto/x509v3/Makefile.ssl b/crypto/x509v3/Makefile.ssl index e29f366cbe..ab13173263 100644 --- a/crypto/x509v3/Makefile.ssl +++ b/crypto/x509v3/Makefile.ssl @@ -26,16 +26,18 @@ LIB=$(TOP)/libcrypto.a LIBSRC= v3_bcons.c v3_bitst.c v3_conf.c v3_extku.c v3_ia5.c v3_lib.c \ v3_prn.c v3_utl.c v3err.c v3_genn.c v3_alt.c v3_skey.c v3_akey.c v3_pku.c \ v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c v3_info.c \ -v3_ocsp.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c +v3_ocsp.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c pcy_cache.c pcy_node.c \ +pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c LIBOBJ= v3_bcons.o v3_bitst.o v3_conf.o v3_extku.o v3_ia5.o v3_lib.o \ v3_prn.o v3_utl.o v3err.o v3_genn.o v3_alt.o v3_skey.o v3_akey.o v3_pku.o \ v3_int.o v3_enum.o v3_sxnet.o v3_cpols.o v3_crld.o v3_purp.o v3_info.o \ -v3_ocsp.o v3_akeya.o v3_pmaps.o v3_pcons.o v3_ncons.o +v3_ocsp.o v3_akeya.o v3_pmaps.o v3_pcons.o v3_ncons.o pcy_cache.o pcy_node.o \ +pcy_data.o pcy_map.o pcy_tree.o pcy_lib.o SRC= $(LIBSRC) EXHEADER= x509v3.h -HEADER= $(EXHEADER) +HEADER= $(EXHEADER) pcy_int.h ALL= $(GENERAL) $(SRC) $(HEADER) diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c new file mode 100644 index 0000000000..23d930dd9c --- /dev/null +++ b/crypto/x509v3/pcy_cache.c @@ -0,0 +1,286 @@ +/* pcy_cache.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "cryptlib.h" +#include <openssl/x509.h> +#include <openssl/x509v3.h> + +#include "pcy_int.h" + +static int policy_data_cmp(void *pa, void *pb); +static int policy_cache_set_int(long *out, ASN1_INTEGER *value); + +/* Set cache entry according to CertificatePolicies extension. + * Note: this destroys the passed CERTIFICATEPOLICIES structure. + */ + +static int policy_cache_create(X509 *x, + CERTIFICATEPOLICIES *policies, int crit) + { + int i; + int ret = 0; + X509_POLICY_CACHE *cache = x->policy_cache; + X509_POLICY_DATA *data = NULL; + POLICYINFO *policy; + if (sk_POLICYINFO_num(policies) == 0) + goto bad_policy; + cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); + if (!cache->data) + goto bad_policy; + for (i = 0; i < sk_POLICYINFO_num(policies); i++) + { + policy = sk_POLICYINFO_value(policies, i); + data = policy_data_new(policy, NULL, crit); + if (!data) + goto bad_policy; + /* Duplicate policy OIDs are illegal: reject if matches + * found. + */ + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) + { + if (cache->anyPolicy) + { + ret = -1; + goto bad_policy; + } + cache->anyPolicy = data; + } + else if (sk_X509_POLICY_DATA_find(cache->data, data) != -1) + { + ret = -1; + goto bad_policy; + } + else if (!sk_X509_POLICY_DATA_push(cache->data, data)) + goto bad_policy; + data = NULL; + } + ret = 1; + bad_policy: + if (ret == -1) + x->ex_flags |= EXFLAG_INVALID_POLICY; + if (data) + policy_data_free(data); + sk_POLICYINFO_pop_free(policies, POLICYINFO_free); + if (ret <= 0) + { + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + cache->data = NULL; + } + return ret; + } + + +static int policy_cache_new(X509 *x) + { + X509_POLICY_CACHE *cache; + ASN1_INTEGER *ext_any = NULL; + POLICY_CONSTRAINTS *ext_pcons = NULL; + CERTIFICATEPOLICIES *ext_cpols = NULL; + POLICY_MAPPINGS *ext_pmaps = NULL; + int i; + cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE)); + if (!cache) + return 0; + cache->anyPolicy = NULL; + cache->data = NULL; + cache->maps = NULL; + cache->any_skip = -1; + cache->explicit_skip = -1; + cache->map_skip = -1; + + x->policy_cache = cache; + + /* Handle requireExplicitPolicy *first*. Need to process this + * even if we don't have any policies. + */ + ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL); + + if (!ext_pcons) + { + if (i != -1) + goto bad_cache; + } + else + { + if (!ext_pcons->requireExplicitPolicy + && !ext_pcons->inhibitPolicyMapping) + goto bad_cache; + if (!policy_cache_set_int(&cache->explicit_skip, + ext_pcons->requireExplicitPolicy)) + goto bad_cache; + if (!policy_cache_set_int(&cache->map_skip, + ext_pcons->inhibitPolicyMapping)) + goto bad_cache; + } + + /* Process CertificatePolicies */ + + ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL); + /* If no CertificatePolicies extension or problem decoding then + * there is no point continuing because the valid policies will be + * NULL. + */ + if (!ext_cpols) + { + /* If not absent some problem with extension */ + if (i != -1) + goto bad_cache; + return 1; + } + + i = policy_cache_create(x, ext_cpols, i); + + /* NB: ext_cpols freed by policy_cache_set_policies */ + + if (i <= 0) + return i; + + ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL); + + if (!ext_pmaps) + { + /* If not absent some problem with extension */ + if (i != -1) + goto bad_cache; + } + else + { + i = policy_cache_set_mapping(x, ext_pmaps); + if (i <= 0) + goto bad_cache; + } + + ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL); + + if (!ext_any) + { + if (i != -1) + goto bad_cache; + } + else if (!policy_cache_set_int(&cache->any_skip, ext_any)) + goto bad_cache; + + if (0) + { + bad_cache: + x->ex_flags |= EXFLAG_INVALID_POLICY; + } + + if(ext_pcons) + POLICY_CONSTRAINTS_free(ext_pcons); + + if (ext_any) + ASN1_INTEGER_free(ext_any); + + return 1; + + +} + +void policy_cache_free(X509_POLICY_CACHE *cache) + { + if (!cache) + return; + if (cache->anyPolicy) + policy_data_free(cache->anyPolicy); + if (cache->data) + sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free); + OPENSSL_free(cache); + } + +const X509_POLICY_CACHE *policy_cache_set(X509 *x) + { + + if (x->policy_cache == NULL) + { + CRYPTO_w_lock(CRYPTO_LOCK_X509); + policy_cache_new(x); + CRYPTO_w_unlock(CRYPTO_LOCK_X509); + } + + return x->policy_cache; + + } + +X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id) + { + int idx; + X509_POLICY_DATA tmp; + tmp.valid_policy = (ASN1_OBJECT *)id; + idx = sk_X509_POLICY_DATA_find(cache->data, &tmp); + if (idx == -1) + return NULL; + return sk_X509_POLICY_DATA_value(cache->data, idx); + } + +static int policy_data_cmp(void *pa, void *pb) + { + X509_POLICY_DATA **a = pa; X509_POLICY_DATA **b = pb; + return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy); + } + +static int policy_cache_set_int(long *out, ASN1_INTEGER *value) + { + if (value == NULL) + return 1; + if (value->type == V_ASN1_NEG_INTEGER) + return 0; + *out = ASN1_INTEGER_get(value); + return 1; + } diff --git a/crypto/x509v3/pcy_data.c b/crypto/x509v3/pcy_data.c new file mode 100644 index 0000000000..fae74cac92 --- /dev/null +++ b/crypto/x509v3/pcy_data.c @@ -0,0 +1,123 @@ +/* pcy_data.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "cryptlib.h" +#include <openssl/x509.h> +#include <openssl/x509v3.h> + +#include "pcy_int.h" + +/* Policy Node routines */ + +void policy_data_free(X509_POLICY_DATA *data) + { + ASN1_OBJECT_free(data->valid_policy); + /* Don't free qualifiers if shared */ + if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS)) + sk_POLICYINFO_pop_free(data->qualifier_set, + POLICYQUALINFO_free); + sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free); + OPENSSL_free(data); + } + +/* Create a data based on an existing policy. If 'id' is NULL use the + * oid in the policy, otherwise use 'id'. This behaviour covers the two + * types of data in RFC3280: data with from a CertificatePolcies extension + * and additional data with just the qualifiers of anyPolicy and ID from + * another source. + */ + +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, ASN1_OBJECT *id, int crit) + { + X509_POLICY_DATA *ret; + if (!policy && !id) + return NULL; + ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA)); + if (!ret) + return NULL; + ret->expected_policy_set = sk_ASN1_OBJECT_new_null(); + if (!ret->expected_policy_set) + { + OPENSSL_free(ret); + return NULL; + } + + if (crit) + ret->flags = POLICY_DATA_FLAG_CRITICAL; + else + ret->flags = 0; + + if (id) + ret->valid_policy = id; + else + { + ret->valid_policy = policy->policyid; + policy->policyid = NULL; + } + + if (policy) + { + ret->qualifier_set = policy->qualifiers; + policy->qualifiers = NULL; + } + else + ret->qualifier_set = NULL; + + return ret; + } + diff --git a/crypto/x509v3/pcy_int.h b/crypto/x509v3/pcy_int.h new file mode 100644 index 0000000000..65689880a6 --- /dev/null +++ b/crypto/x509v3/pcy_int.h @@ -0,0 +1,220 @@ +/* pcy_int.h */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +DECLARE_STACK_OF(X509_POLICY_DATA) +DECLARE_STACK_OF(X509_POLICY_REF) +DECLARE_STACK_OF(X509_POLICY_NODE) + +typedef struct X509_POLICY_DATA_st X509_POLICY_DATA; +typedef struct X509_POLICY_REF_st X509_POLICY_REF; + +/* Internal structures */ + +/* This structure and the field names correspond to the Policy 'node' of + * RFC3280. NB this structure contains no pointers to parent or child + * data: X509_POLICY_NODE contains that. This means that the main policy data + * can be kept static and cached with the certificate. + */ + +struct X509_POLICY_DATA_st + { + unsigned int flags; + /* Policy OID and qualifiers for this data */ + ASN1_OBJECT *valid_policy; + STACK_OF(POLICYQUALIFIER) *qualifier_set; + STACK_OF(ASN1_OBJECT) *expected_policy_set; + }; + +/* X509_POLICY_DATA flags values */ + +/* This flag indicates the structure has been mapped using a policy mapping + * extension. If policy mapping is not active its references get deleted. + */ + +#define POLICY_DATA_FLAG_MAPPED 0x1 + +/* This flag indicates the data doesn't correspond to a policy in Certificate + * Policies: it has been mapped to any policy. + */ + +#define POLICY_DATA_FLAG_MAPPED_ANY 0x2 + +/* AND with flags to see if any mapping has occurred */ + +#define POLICY_DATA_FLAG_MAP_MASK 0x3 + +/* qualifiers are shared and shouldn't be freed */ + +#define POLICY_DATA_FLAG_SHARED_QUALIFIERS 0x4 + +/* Parent node is an extra node and should be freed */ + +#define POLICY_DATA_FLAG_EXTRA_NODE 0x8 + +/* Corresponding CertificatePolicies is critical */ + +#define POLICY_DATA_FLAG_CRITICAL 0x10 + +/* This structure is an entry from a table of mapped policies which + * cross reference the policy it refers to. + */ + +struct X509_POLICY_REF_st + { + ASN1_OBJECT *subjectDomainPolicy; + const X509_POLICY_DATA *data; + }; + +/* This structure is cached with a certificate */ + +struct X509_POLICY_CACHE_st { + /* anyPolicy data or NULL if no anyPolicy */ + X509_POLICY_DATA *anyPolicy; + /* other policy data */ + STACK_OF(X509_POLICY_DATA) *data; + /* If policyMappings extension present a table of mapped policies */ + STACK_OF(POLICY_REF) *maps; + /* If InhibitAnyPolicy present this is its value or -1 if absent. */ + long any_skip; + /* If policyConstraints and requireExplicitPolicy present this is its + * value or -1 if absent. + */ + long explicit_skip; + /* If policyConstraints and policyMapping present this is its + * value or -1 if absent. + */ + long map_skip; + }; + +/*#define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL*/ + +/* This structure represents the relationship between nodes */ + +struct X509_POLICY_NODE_st + { + /* node data this refers to */ + const X509_POLICY_DATA *data; + /* Parent node */ + X509_POLICY_NODE *parent; + /* Number of child nodes */ + int nchild; + }; + +struct X509_POLICY_LEVEL_st + { + /* Cert for this level */ + X509 *cert; + /* nodes at this level */ + STACK_OF(X509_POLICY_NODE) *nodes; + /* anyPolicy node */ + X509_POLICY_NODE *anyPolicy; + /* Extra data */ + /*STACK_OF(X509_POLICY_DATA) *extra_data;*/ + unsigned int flags; + }; + +struct X509_POLICY_TREE_st + { + /* This is the tree 'level' data */ + X509_POLICY_LEVEL *levels; + int nlevel; + /* Extra policy data when additional nodes (not from the certificate) + * are required. + */ + STACK_OF(X509_POLICY_DATA) *extra_data; + /* This is the authority constained policy set */ + STACK_OF(X509_POLICY_NODE) *auth_policies; + STACK_OF(X509_POLICY_NODE) *user_policies; + unsigned int flags; + }; + +/* Set if anyPolicy present in user policies */ +#define POLICY_FLAG_ANY_POLICY 0x2 + +/* Useful macros */ + +#define node_critical(node) ((node)->data->flags & POLICY_DATA_FLAG_CRITICAL) + +/* Internal functions */ + +X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, ASN1_OBJECT *id, + int crit); +void policy_data_free(X509_POLICY_DATA *data); + +X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, + const ASN1_OBJECT *id); +int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps); + + +STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void); + +void policy_cache_init(void); + +X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + const ASN1_OBJECT *id); + +X509_POLICY |