xref: /aosp_15_r20/external/boringssl/src/crypto/x509/v3_conf.c (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1 /*
2  * Written by Dr Stephen N Henson ([email protected]) for the OpenSSL project
3  * 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    [email protected].
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * ([email protected]).  This product includes software written by Tim
55  * Hudson ([email protected]). */
56 
57 // extension creation utilities
58 
59 #include <ctype.h>
60 #include <limits.h>
61 #include <stdio.h>
62 #include <string.h>
63 
64 #include <openssl/conf.h>
65 #include <openssl/err.h>
66 #include <openssl/mem.h>
67 #include <openssl/obj.h>
68 #include <openssl/x509.h>
69 
70 #include "../internal.h"
71 #include "internal.h"
72 
73 static int v3_check_critical(const char **value);
74 static int v3_check_generic(const char **value);
75 static X509_EXTENSION *do_ext_nconf(const CONF *conf, const X509V3_CTX *ctx,
76                                     int ext_nid, int crit, const char *value);
77 static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
78                                             int crit, int type,
79                                             const X509V3_CTX *ctx);
80 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
81                                   int crit, void *ext_struc);
82 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
83                                    size_t *ext_len);
84 
X509V3_EXT_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * name,const char * value)85 X509_EXTENSION *X509V3_EXT_nconf(const CONF *conf, const X509V3_CTX *ctx,
86                                  const char *name, const char *value) {
87   // If omitted, fill in an empty |X509V3_CTX|.
88   X509V3_CTX ctx_tmp;
89   if (ctx == NULL) {
90     X509V3_set_ctx(&ctx_tmp, NULL, NULL, NULL, NULL, 0);
91     X509V3_set_nconf(&ctx_tmp, conf);
92     ctx = &ctx_tmp;
93   }
94 
95   int crit = v3_check_critical(&value);
96   int ext_type = v3_check_generic(&value);
97   if (ext_type != 0) {
98     return v3_generic_extension(name, value, crit, ext_type, ctx);
99   }
100   X509_EXTENSION *ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
101   if (!ret) {
102     OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
103     ERR_add_error_data(4, "name=", name, ", value=", value);
104   }
105   return ret;
106 }
107 
X509V3_EXT_nconf_nid(const CONF * conf,const X509V3_CTX * ctx,int ext_nid,const char * value)108 X509_EXTENSION *X509V3_EXT_nconf_nid(const CONF *conf, const X509V3_CTX *ctx,
109                                      int ext_nid, const char *value) {
110   // If omitted, fill in an empty |X509V3_CTX|.
111   X509V3_CTX ctx_tmp;
112   if (ctx == NULL) {
113     X509V3_set_ctx(&ctx_tmp, NULL, NULL, NULL, NULL, 0);
114     X509V3_set_nconf(&ctx_tmp, conf);
115     ctx = &ctx_tmp;
116   }
117 
118   int crit = v3_check_critical(&value);
119   int ext_type = v3_check_generic(&value);
120   if (ext_type != 0) {
121     return v3_generic_extension(OBJ_nid2sn(ext_nid), value, crit, ext_type,
122                                 ctx);
123   }
124   return do_ext_nconf(conf, ctx, ext_nid, crit, value);
125 }
126 
127 // CONF *conf:  Config file
128 // char *value:  Value
do_ext_nconf(const CONF * conf,const X509V3_CTX * ctx,int ext_nid,int crit,const char * value)129 static X509_EXTENSION *do_ext_nconf(const CONF *conf, const X509V3_CTX *ctx,
130                                     int ext_nid, int crit, const char *value) {
131   const X509V3_EXT_METHOD *method;
132   X509_EXTENSION *ext;
133   const STACK_OF(CONF_VALUE) *nval;
134   STACK_OF(CONF_VALUE) *nval_owned = NULL;
135   void *ext_struc;
136   if (ext_nid == NID_undef) {
137     OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
138     return NULL;
139   }
140   if (!(method = X509V3_EXT_get_nid(ext_nid))) {
141     OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
142     return NULL;
143   }
144   // Now get internal extension representation based on type
145   if (method->v2i) {
146     if (*value == '@') {
147       // TODO(davidben): This is the only place where |X509V3_EXT_nconf|'s
148       // |conf| parameter is used. All other codepaths use the copy inside
149       // |ctx|. Should this be switched and then the parameter ignored?
150       if (conf == NULL) {
151         OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
152         return NULL;
153       }
154       nval = NCONF_get_section(conf, value + 1);
155     } else {
156       nval_owned = X509V3_parse_list(value);
157       nval = nval_owned;
158     }
159     if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
160       OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
161       ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value);
162       sk_CONF_VALUE_pop_free(nval_owned, X509V3_conf_free);
163       return NULL;
164     }
165     ext_struc = method->v2i(method, ctx, nval);
166     sk_CONF_VALUE_pop_free(nval_owned, X509V3_conf_free);
167     if (!ext_struc) {
168       return NULL;
169     }
170   } else if (method->s2i) {
171     if (!(ext_struc = method->s2i(method, ctx, value))) {
172       return NULL;
173     }
174   } else if (method->r2i) {
175     // TODO(davidben): Should this check be removed? This matches OpenSSL, but
176     // r2i-based extensions do not necessarily require a config database. The
177     // two built-in extensions only use it some of the time, and already handle
178     // |X509V3_get_section| returning NULL.
179     if (!ctx->db) {
180       OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
181       return NULL;
182     }
183     if (!(ext_struc = method->r2i(method, ctx, value))) {
184       return NULL;
185     }
186   } else {
187     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
188     ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
189     return NULL;
190   }
191 
192   ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
193   ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
194   return ext;
195 }
196 
do_ext_i2d(const X509V3_EXT_METHOD * method,int ext_nid,int crit,void * ext_struc)197 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
198                                   int crit, void *ext_struc) {
199   // Convert the extension's internal representation to DER.
200   unsigned char *ext_der = NULL;
201   int ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
202   if (ext_len < 0) {
203     return NULL;
204   }
205 
206   ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
207   if (ext_oct == NULL) {
208     OPENSSL_free(ext_der);
209     return NULL;
210   }
211   ASN1_STRING_set0(ext_oct, ext_der, ext_len);
212 
213   X509_EXTENSION *ext =
214       X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
215   ASN1_OCTET_STRING_free(ext_oct);
216   return ext;
217 }
218 
219 // Given an internal structure, nid and critical flag create an extension
220 
X509V3_EXT_i2d(int ext_nid,int crit,void * ext_struc)221 X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) {
222   const X509V3_EXT_METHOD *method;
223   if (!(method = X509V3_EXT_get_nid(ext_nid))) {
224     OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
225     return NULL;
226   }
227   return do_ext_i2d(method, ext_nid, crit, ext_struc);
228 }
229 
230 // Check the extension string for critical flag
v3_check_critical(const char ** value)231 static int v3_check_critical(const char **value) {
232   const char *p = *value;
233   if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) {
234     return 0;
235   }
236   p += 9;
237   while (OPENSSL_isspace((unsigned char)*p)) {
238     p++;
239   }
240   *value = p;
241   return 1;
242 }
243 
244 // Check extension string for generic extension and return the type
v3_check_generic(const char ** value)245 static int v3_check_generic(const char **value) {
246   int gen_type = 0;
247   const char *p = *value;
248   if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
249     p += 4;
250     gen_type = 1;
251   } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
252     p += 5;
253     gen_type = 2;
254   } else {
255     return 0;
256   }
257 
258   while (OPENSSL_isspace((unsigned char)*p)) {
259     p++;
260   }
261   *value = p;
262   return gen_type;
263 }
264 
265 // Create a generic extension: for now just handle DER type
v3_generic_extension(const char * ext,const char * value,int crit,int gen_type,const X509V3_CTX * ctx)266 static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
267                                             int crit, int gen_type,
268                                             const X509V3_CTX *ctx) {
269   unsigned char *ext_der = NULL;
270   size_t ext_len = 0;
271   ASN1_OBJECT *obj = NULL;
272   ASN1_OCTET_STRING *oct = NULL;
273   X509_EXTENSION *extension = NULL;
274   if (!(obj = OBJ_txt2obj(ext, 0))) {
275     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
276     ERR_add_error_data(2, "name=", ext);
277     goto err;
278   }
279 
280   if (gen_type == 1) {
281     ext_der = x509v3_hex_to_bytes(value, &ext_len);
282   } else if (gen_type == 2) {
283     ext_der = generic_asn1(value, ctx, &ext_len);
284   }
285 
286   if (ext_der == NULL) {
287     OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
288     ERR_add_error_data(2, "value=", value);
289     goto err;
290   }
291 
292   if (ext_len > INT_MAX) {
293     OPENSSL_PUT_ERROR(X509V3, ERR_R_OVERFLOW);
294     goto err;
295   }
296 
297   oct = ASN1_OCTET_STRING_new();
298   if (oct == NULL) {
299     goto err;
300   }
301 
302   ASN1_STRING_set0(oct, ext_der, (int)ext_len);
303   ext_der = NULL;
304 
305   extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
306 
307 err:
308   ASN1_OBJECT_free(obj);
309   ASN1_OCTET_STRING_free(oct);
310   OPENSSL_free(ext_der);
311   return extension;
312 }
313 
generic_asn1(const char * value,const X509V3_CTX * ctx,size_t * ext_len)314 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
315                                    size_t *ext_len) {
316   ASN1_TYPE *typ = ASN1_generate_v3(value, ctx);
317   if (typ == NULL) {
318     return NULL;
319   }
320   unsigned char *ext_der = NULL;
321   int len = i2d_ASN1_TYPE(typ, &ext_der);
322   ASN1_TYPE_free(typ);
323   if (len < 0) {
324     return NULL;
325   }
326   *ext_len = len;
327   return ext_der;
328 }
329 
330 // This is the main function: add a bunch of extensions based on a config
331 // file section to an extension STACK.
332 
X509V3_EXT_add_nconf_sk(const CONF * conf,const X509V3_CTX * ctx,const char * section,STACK_OF (X509_EXTENSION)** sk)333 int X509V3_EXT_add_nconf_sk(const CONF *conf, const X509V3_CTX *ctx,
334                             const char *section,
335                             STACK_OF(X509_EXTENSION) **sk) {
336   const STACK_OF(CONF_VALUE) *nval = NCONF_get_section(conf, section);
337   if (nval == NULL) {
338     return 0;
339   }
340   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
341     const CONF_VALUE *val = sk_CONF_VALUE_value(nval, i);
342     X509_EXTENSION *ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value);
343     int ok = ext != NULL &&  //
344              (sk == NULL || X509v3_add_ext(sk, ext, -1) != NULL);
345     X509_EXTENSION_free(ext);
346     if (!ok) {
347       return 0;
348     }
349   }
350   return 1;
351 }
352 
353 // Convenience functions to add extensions to a certificate, CRL and request
354 
X509V3_EXT_add_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * section,X509 * cert)355 int X509V3_EXT_add_nconf(const CONF *conf, const X509V3_CTX *ctx,
356                          const char *section, X509 *cert) {
357   STACK_OF(X509_EXTENSION) **sk = NULL;
358   if (cert) {
359     sk = &cert->cert_info->extensions;
360   }
361   return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
362 }
363 
364 // Same as above but for a CRL
365 
X509V3_EXT_CRL_add_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * section,X509_CRL * crl)366 int X509V3_EXT_CRL_add_nconf(const CONF *conf, const X509V3_CTX *ctx,
367                              const char *section, X509_CRL *crl) {
368   STACK_OF(X509_EXTENSION) **sk = NULL;
369   if (crl) {
370     sk = &crl->crl->extensions;
371   }
372   return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
373 }
374 
375 // Add extensions to certificate request
376 
X509V3_EXT_REQ_add_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * section,X509_REQ * req)377 int X509V3_EXT_REQ_add_nconf(const CONF *conf, const X509V3_CTX *ctx,
378                              const char *section, X509_REQ *req) {
379   STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
380   int i;
381   if (req) {
382     sk = &extlist;
383   }
384   i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
385   if (!i || !sk) {
386     return i;
387   }
388   i = X509_REQ_add_extensions(req, extlist);
389   sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
390   return i;
391 }
392 
393 // Config database functions
394 
STACK_OF(CONF_VALUE)395 const STACK_OF(CONF_VALUE) *X509V3_get_section(const X509V3_CTX *ctx,
396                                                const char *section) {
397   if (ctx->db == NULL) {
398     OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
399     return NULL;
400   }
401   return NCONF_get_section(ctx->db, section);
402 }
403 
X509V3_set_nconf(X509V3_CTX * ctx,const CONF * conf)404 void X509V3_set_nconf(X509V3_CTX *ctx, const CONF *conf) {
405   ctx->db = conf;
406 }
407 
X509V3_set_ctx(X509V3_CTX * ctx,const X509 * issuer,const X509 * subj,const X509_REQ * req,const X509_CRL * crl,int flags)408 void X509V3_set_ctx(X509V3_CTX *ctx, const X509 *issuer, const X509 *subj,
409                     const X509_REQ *req, const X509_CRL *crl, int flags) {
410   OPENSSL_memset(ctx, 0, sizeof(*ctx));
411   ctx->issuer_cert = issuer;
412   ctx->subject_cert = subj;
413   ctx->crl = crl;
414   ctx->subject_req = req;
415   ctx->flags = flags;
416 }
417