1*8b5faa71Stb /* $OpenBSD: x509_lib.c,v 1.24 2024/07/13 15:08:58 tb Exp $ */
2e500e238Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3e500e238Sjsing * project 1999.
4e500e238Sjsing */
5e500e238Sjsing /* ====================================================================
6e500e238Sjsing * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
7e500e238Sjsing *
8e500e238Sjsing * Redistribution and use in source and binary forms, with or without
9e500e238Sjsing * modification, are permitted provided that the following conditions
10e500e238Sjsing * are met:
11e500e238Sjsing *
12e500e238Sjsing * 1. Redistributions of source code must retain the above copyright
13e500e238Sjsing * notice, this list of conditions and the following disclaimer.
14e500e238Sjsing *
15e500e238Sjsing * 2. Redistributions in binary form must reproduce the above copyright
16e500e238Sjsing * notice, this list of conditions and the following disclaimer in
17e500e238Sjsing * the documentation and/or other materials provided with the
18e500e238Sjsing * distribution.
19e500e238Sjsing *
20e500e238Sjsing * 3. All advertising materials mentioning features or use of this
21e500e238Sjsing * software must display the following acknowledgment:
22e500e238Sjsing * "This product includes software developed by the OpenSSL Project
23e500e238Sjsing * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24e500e238Sjsing *
25e500e238Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26e500e238Sjsing * endorse or promote products derived from this software without
27e500e238Sjsing * prior written permission. For written permission, please contact
28e500e238Sjsing * licensing@OpenSSL.org.
29e500e238Sjsing *
30e500e238Sjsing * 5. Products derived from this software may not be called "OpenSSL"
31e500e238Sjsing * nor may "OpenSSL" appear in their names without prior written
32e500e238Sjsing * permission of the OpenSSL Project.
33e500e238Sjsing *
34e500e238Sjsing * 6. Redistributions of any form whatsoever must retain the following
35e500e238Sjsing * acknowledgment:
36e500e238Sjsing * "This product includes software developed by the OpenSSL Project
37e500e238Sjsing * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38e500e238Sjsing *
39e500e238Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40e500e238Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41e500e238Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42e500e238Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43e500e238Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44e500e238Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45e500e238Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46e500e238Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47e500e238Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48e500e238Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49e500e238Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50e500e238Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE.
51e500e238Sjsing * ====================================================================
52e500e238Sjsing *
53e500e238Sjsing * This product includes cryptographic software written by Eric Young
54e500e238Sjsing * (eay@cryptsoft.com). This product includes software written by Tim
55e500e238Sjsing * Hudson (tjh@cryptsoft.com).
56e500e238Sjsing *
57e500e238Sjsing */
58e500e238Sjsing /* X509 v3 extension utilities */
59e500e238Sjsing
60e500e238Sjsing #include <stdio.h>
61e500e238Sjsing
62e500e238Sjsing #include <openssl/conf.h>
63e500e238Sjsing #include <openssl/err.h>
64e500e238Sjsing #include <openssl/x509v3.h>
65e500e238Sjsing
66c9675a23Stb #include "x509_local.h"
67e500e238Sjsing
68e500e238Sjsing const X509V3_EXT_METHOD *
X509V3_EXT_get_nid(int nid)69e500e238Sjsing X509V3_EXT_get_nid(int nid)
70e500e238Sjsing {
71*8b5faa71Stb switch (nid) {
72*8b5faa71Stb case NID_authority_key_identifier:
73*8b5faa71Stb return x509v3_ext_method_authority_key_identifier();
74*8b5faa71Stb case NID_basic_constraints:
75*8b5faa71Stb return x509v3_ext_method_basic_constraints();
76*8b5faa71Stb case NID_certificate_issuer:
77*8b5faa71Stb return x509v3_ext_method_certificate_issuer();
78*8b5faa71Stb case NID_certificate_policies:
79*8b5faa71Stb return x509v3_ext_method_certificate_policies();
80*8b5faa71Stb case NID_crl_distribution_points:
81*8b5faa71Stb return x509v3_ext_method_crl_distribution_points();
82*8b5faa71Stb case NID_crl_number:
83*8b5faa71Stb return x509v3_ext_method_crl_number();
84*8b5faa71Stb case NID_crl_reason:
85*8b5faa71Stb return x509v3_ext_method_crl_reason();
86*8b5faa71Stb #ifndef OPENSSL_NO_CT
87*8b5faa71Stb case NID_ct_cert_scts:
88*8b5faa71Stb return x509v3_ext_method_ct_cert_scts();
89*8b5faa71Stb case NID_ct_precert_poison:
90*8b5faa71Stb return x509v3_ext_method_ct_precert_poison();
91*8b5faa71Stb case NID_ct_precert_scts:
92*8b5faa71Stb return x509v3_ext_method_ct_precert_scts();
93*8b5faa71Stb #endif
94*8b5faa71Stb case NID_delta_crl:
95*8b5faa71Stb return x509v3_ext_method_delta_crl();
96*8b5faa71Stb case NID_ext_key_usage:
97*8b5faa71Stb return x509v3_ext_method_ext_key_usage();
98*8b5faa71Stb case NID_freshest_crl:
99*8b5faa71Stb return x509v3_ext_method_freshest_crl();
100*8b5faa71Stb #ifndef OPENSSL_NO_OCSP
101*8b5faa71Stb case NID_hold_instruction_code:
102*8b5faa71Stb return x509v3_ext_method_hold_instruction_code();
103*8b5faa71Stb case NID_id_pkix_OCSP_CrlID:
104*8b5faa71Stb return x509v3_ext_method_id_pkix_OCSP_CrlID();
105*8b5faa71Stb case NID_id_pkix_OCSP_Nonce:
106*8b5faa71Stb return x509v3_ext_method_id_pkix_OCSP_Nonce();
107*8b5faa71Stb case NID_id_pkix_OCSP_acceptableResponses:
108*8b5faa71Stb return x509v3_ext_method_id_pkix_OCSP_acceptableResponses();
109*8b5faa71Stb case NID_id_pkix_OCSP_archiveCutoff:
110*8b5faa71Stb return x509v3_ext_method_id_pkix_OCSP_archiveCutoff();
111*8b5faa71Stb case NID_id_pkix_OCSP_serviceLocator:
112*8b5faa71Stb return x509v3_ext_method_id_pkix_OCSP_serviceLocator();
113*8b5faa71Stb #endif
114*8b5faa71Stb case NID_info_access:
115*8b5faa71Stb return x509v3_ext_method_info_access();
116*8b5faa71Stb case NID_inhibit_any_policy:
117*8b5faa71Stb return x509v3_ext_method_inhibit_any_policy();
118*8b5faa71Stb case NID_invalidity_date:
119*8b5faa71Stb return x509v3_ext_method_invalidity_date();
120*8b5faa71Stb case NID_issuer_alt_name:
121*8b5faa71Stb return x509v3_ext_method_issuer_alt_name();
122*8b5faa71Stb case NID_issuing_distribution_point:
123*8b5faa71Stb return x509v3_ext_method_issuing_distribution_point();
124*8b5faa71Stb case NID_key_usage:
125*8b5faa71Stb return x509v3_ext_method_key_usage();
126*8b5faa71Stb case NID_name_constraints:
127*8b5faa71Stb return x509v3_ext_method_name_constraints();
128*8b5faa71Stb case NID_netscape_base_url:
129*8b5faa71Stb return x509v3_ext_method_netscape_base_url();
130*8b5faa71Stb case NID_netscape_ca_policy_url:
131*8b5faa71Stb return x509v3_ext_method_netscape_ca_policy_url();
132*8b5faa71Stb case NID_netscape_ca_revocation_url:
133*8b5faa71Stb return x509v3_ext_method_netscape_ca_revocation_url();
134*8b5faa71Stb case NID_netscape_cert_type:
135*8b5faa71Stb return x509v3_ext_method_netscape_cert_type();
136*8b5faa71Stb case NID_netscape_comment:
137*8b5faa71Stb return x509v3_ext_method_netscape_comment();
138*8b5faa71Stb case NID_netscape_renewal_url:
139*8b5faa71Stb return x509v3_ext_method_netscape_renewal_url();
140*8b5faa71Stb case NID_netscape_revocation_url:
141*8b5faa71Stb return x509v3_ext_method_netscape_revocation_url();
142*8b5faa71Stb case NID_netscape_ssl_server_name:
143*8b5faa71Stb return x509v3_ext_method_netscape_ssl_server_name();
144*8b5faa71Stb case NID_policy_constraints:
145*8b5faa71Stb return x509v3_ext_method_policy_constraints();
146*8b5faa71Stb case NID_policy_mappings:
147*8b5faa71Stb return x509v3_ext_method_policy_mappings();
148*8b5faa71Stb case NID_private_key_usage_period:
149*8b5faa71Stb return x509v3_ext_method_private_key_usage_period();
150*8b5faa71Stb #ifndef OPENSSL_NO_RFC3779
151*8b5faa71Stb case NID_sbgp_ipAddrBlock:
152*8b5faa71Stb return x509v3_ext_method_sbgp_ipAddrBlock();
153*8b5faa71Stb case NID_sbgp_autonomousSysNum:
154*8b5faa71Stb return x509v3_ext_method_sbgp_autonomousSysNum();
155*8b5faa71Stb #endif
156*8b5faa71Stb case NID_sinfo_access:
157*8b5faa71Stb return x509v3_ext_method_sinfo_access();
158*8b5faa71Stb case NID_subject_alt_name:
159*8b5faa71Stb return x509v3_ext_method_subject_alt_name();
160*8b5faa71Stb case NID_subject_key_identifier:
161*8b5faa71Stb return x509v3_ext_method_subject_key_identifier();
162*8b5faa71Stb default:
163e500e238Sjsing return NULL;
164e500e238Sjsing }
165*8b5faa71Stb };
166cedac418Stb LCRYPTO_ALIAS(X509V3_EXT_get_nid);
167e500e238Sjsing
168e500e238Sjsing const X509V3_EXT_METHOD *
X509V3_EXT_get(X509_EXTENSION * ext)169e500e238Sjsing X509V3_EXT_get(X509_EXTENSION *ext)
170e500e238Sjsing {
171e500e238Sjsing int nid;
172e500e238Sjsing
173e500e238Sjsing if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
174e500e238Sjsing return NULL;
175e500e238Sjsing return X509V3_EXT_get_nid(nid);
176e500e238Sjsing }
177cedac418Stb LCRYPTO_ALIAS(X509V3_EXT_get);
178e500e238Sjsing
179e500e238Sjsing /* Return an extension internal structure */
180e500e238Sjsing
181e500e238Sjsing void *
X509V3_EXT_d2i(X509_EXTENSION * ext)182e500e238Sjsing X509V3_EXT_d2i(X509_EXTENSION *ext)
183e500e238Sjsing {
184e500e238Sjsing const X509V3_EXT_METHOD *method;
185e500e238Sjsing const unsigned char *p;
186e500e238Sjsing
187f4b64d97Stb if ((method = X509V3_EXT_get(ext)) == NULL)
188e500e238Sjsing return NULL;
189e500e238Sjsing p = ext->value->data;
190f4b64d97Stb if (method->it != NULL)
191bb6d6b69Stb return ASN1_item_d2i(NULL, &p, ext->value->length, method->it);
192e500e238Sjsing return method->d2i(NULL, &p, ext->value->length);
193e500e238Sjsing }
194cedac418Stb LCRYPTO_ALIAS(X509V3_EXT_d2i);
195e500e238Sjsing
1960e6355d3Stb /*
1970e6355d3Stb * This API is only safe to call with known nid, crit != NULL and idx == NULL.
1980e6355d3Stb * On NULL return, crit acts as a failure indicator: crit == -1 means an
1990e6355d3Stb * extension of type nid was not present, crit != -1 is fatal: crit == -2
2000e6355d3Stb * means multiple extensions of type nid are present; if crit is 0 or 1, this
2010e6355d3Stb * implies the extension was found but could not be decoded.
202e500e238Sjsing */
203e500e238Sjsing
204e500e238Sjsing void *
X509V3_get_d2i(const STACK_OF (X509_EXTENSION)* x509_exts,int nid,int * crit,int * idx)205fd1d0ae5Stb X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x509_exts, int nid, int *crit,
206fd1d0ae5Stb int *idx)
207e500e238Sjsing {
2080e6355d3Stb X509_EXTENSION *ext;
2090e6355d3Stb int lastpos = idx == NULL ? -1 : *idx;
210e500e238Sjsing
2110e6355d3Stb if (crit != NULL)
212e500e238Sjsing *crit = -1;
2130e6355d3Stb if (idx != NULL)
2140e6355d3Stb *idx = -1;
2150e6355d3Stb
2160e6355d3Stb /*
2170e6355d3Stb * Nothing to do if no extensions, unknown nid, or missing extension.
2180e6355d3Stb */
2190e6355d3Stb
220fd1d0ae5Stb if (x509_exts == NULL)
221e500e238Sjsing return NULL;
222fd1d0ae5Stb if ((lastpos = X509v3_get_ext_by_NID(x509_exts, nid, lastpos)) < 0)
2230e6355d3Stb return NULL;
224fd1d0ae5Stb if ((ext = X509v3_get_ext(x509_exts, lastpos)) == NULL)
2250e6355d3Stb return NULL;
2260e6355d3Stb
2270e6355d3Stb /*
2280e6355d3Stb * API madness. Only check for a second extension of type nid if
2290e6355d3Stb * idx == NULL. Indicate this by setting *crit to -2. If idx != NULL,
2300e6355d3Stb * don't care and set *idx to the index of the first extension found.
2310e6355d3Stb */
2320e6355d3Stb
233fd1d0ae5Stb if (idx == NULL && X509v3_get_ext_by_NID(x509_exts, nid, lastpos) > 0) {
2340e6355d3Stb if (crit != NULL)
235e500e238Sjsing *crit = -2;
236e500e238Sjsing return NULL;
237e500e238Sjsing }
238e500e238Sjsing
2390e6355d3Stb /*
2400e6355d3Stb * Another beautiful API detail: *crit will be set to 0 or 1, so if the
2410e6355d3Stb * extension fails to decode, we can deduce this from return value NULL
2420e6355d3Stb * and crit != -1.
2430e6355d3Stb */
2440e6355d3Stb
2450e6355d3Stb if (crit != NULL)
2460e6355d3Stb *crit = X509_EXTENSION_get_critical(ext);
2470e6355d3Stb if (idx != NULL)
2480e6355d3Stb *idx = lastpos;
2490e6355d3Stb
2500e6355d3Stb return X509V3_EXT_d2i(ext);
251e500e238Sjsing }
252cedac418Stb LCRYPTO_ALIAS(X509V3_get_d2i);
253e500e238Sjsing
254e500e238Sjsing int
X509V3_add1_i2d(STACK_OF (X509_EXTENSION)** x509_exts,int nid,void * value,int crit,unsigned long flags)255fd1d0ae5Stb X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x509_exts, int nid, void *value,
256e500e238Sjsing int crit, unsigned long flags)
257e500e238Sjsing {
258fd1d0ae5Stb STACK_OF(X509_EXTENSION) *exts = *x509_exts;
25910903369Stb X509_EXTENSION *ext = NULL;
26010903369Stb X509_EXTENSION *existing;
26110903369Stb int extidx;
26210903369Stb int errcode = 0;
26310903369Stb int ret = 0;
264e500e238Sjsing
26510903369Stb /* See if the extension already exists. */
266fd1d0ae5Stb extidx = X509v3_get_ext_by_NID(*x509_exts, nid, -1);
267e500e238Sjsing
26810903369Stb switch (flags & X509V3_ADD_OP_MASK) {
26910903369Stb case X509V3_ADD_DEFAULT:
27010903369Stb /* If the extension exists, adding another one is an error. */
271e500e238Sjsing if (extidx >= 0) {
272e500e238Sjsing errcode = X509V3_R_EXTENSION_EXISTS;
273e500e238Sjsing goto err;
274e500e238Sjsing }
27510903369Stb break;
27610903369Stb case X509V3_ADD_APPEND:
27710903369Stb /*
27810903369Stb * XXX - Total misfeature. If the extension exists, appending
27910903369Stb * another one will invalidate the certificate. Unfortunately
28010903369Stb * things use this, in particular Viktor's DANE code.
281e500e238Sjsing */
28210903369Stb /* Pretend the extension didn't exist and append the new one. */
28310903369Stb extidx = -1;
28410903369Stb break;
28510903369Stb case X509V3_ADD_REPLACE:
28610903369Stb /* Replace existing extension, otherwise append the new one. */
28710903369Stb break;
28810903369Stb case X509V3_ADD_REPLACE_EXISTING:
28910903369Stb /* Can't replace a non-existent extension. */
29010903369Stb if (extidx < 0) {
291e500e238Sjsing errcode = X509V3_R_EXTENSION_NOT_FOUND;
292e500e238Sjsing goto err;
293e500e238Sjsing }
29410903369Stb break;
29510903369Stb case X509V3_ADD_KEEP_EXISTING:
29610903369Stb /* If the extension exists, there's nothing to do. */
29710903369Stb if (extidx >= 0)
29810903369Stb goto done;
29910903369Stb break;
30010903369Stb case X509V3_ADD_DELETE:
30110903369Stb /* Can't delete a non-existent extension. */
30210903369Stb if (extidx < 0) {
30310903369Stb errcode = X509V3_R_EXTENSION_NOT_FOUND;
30410903369Stb goto err;
30510903369Stb }
306fd1d0ae5Stb if ((existing = sk_X509_EXTENSION_delete(*x509_exts,
307fd1d0ae5Stb extidx)) == NULL) {
30810903369Stb ret = -1;
30910903369Stb goto err;
31010903369Stb }
31110903369Stb X509_EXTENSION_free(existing);
31210903369Stb existing = NULL;
31310903369Stb goto done;
31410903369Stb default:
31510903369Stb errcode = X509V3_R_UNSUPPORTED_OPTION; /* XXX */
31610903369Stb ret = -1;
31710903369Stb goto err;
318e500e238Sjsing }
319e500e238Sjsing
32010903369Stb if ((ext = X509V3_EXT_i2d(nid, crit, value)) == NULL) {
321e500e238Sjsing X509V3error(X509V3_R_ERROR_CREATING_EXTENSION);
32210903369Stb goto err;
323e500e238Sjsing }
324e500e238Sjsing
32510903369Stb /* From here, errors are fatal. */
32610903369Stb ret = -1;
32710903369Stb
32810903369Stb /* If extension exists, replace it. */
329e500e238Sjsing if (extidx >= 0) {
330fd1d0ae5Stb existing = sk_X509_EXTENSION_value(*x509_exts, extidx);
33110903369Stb X509_EXTENSION_free(existing);
33210903369Stb existing = NULL;
333fd1d0ae5Stb if (sk_X509_EXTENSION_set(*x509_exts, extidx, ext) == NULL) {
33410903369Stb /*
33510903369Stb * XXX - Can't happen. If it did happen, |existing| is
33610903369Stb * now a freed pointer. Nothing we can do here.
33710903369Stb */
33810903369Stb goto err;
33910903369Stb }
34010903369Stb goto done;
341e500e238Sjsing }
342e500e238Sjsing
34310903369Stb if (exts == NULL)
34410903369Stb exts = sk_X509_EXTENSION_new_null();
34510903369Stb if (exts == NULL)
34610903369Stb goto err;
347e500e238Sjsing
34810903369Stb if (!sk_X509_EXTENSION_push(exts, ext))
34910903369Stb goto err;
35010903369Stb ext = NULL;
35110903369Stb
352fd1d0ae5Stb *x509_exts = exts;
35310903369Stb
35410903369Stb done:
355e500e238Sjsing return 1;
356e500e238Sjsing
357e500e238Sjsing err:
35810903369Stb if ((flags & X509V3_ADD_SILENT) == 0 && errcode != 0)
359e500e238Sjsing X509V3error(errcode);
36010903369Stb
361fd1d0ae5Stb if (exts != *x509_exts)
36210903369Stb sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
36310903369Stb X509_EXTENSION_free(ext);
36410903369Stb
36510903369Stb return ret;
366e500e238Sjsing }
367cedac418Stb LCRYPTO_ALIAS(X509V3_add1_i2d);
368ac522c4fStb
369ac522c4fStb int
X509V3_add_standard_extensions(void)370ac522c4fStb X509V3_add_standard_extensions(void)
371ac522c4fStb {
372ac522c4fStb return 1;
373ac522c4fStb }
374ac522c4fStb LCRYPTO_ALIAS(X509V3_add_standard_extensions);
375