1 /*
2 * Written by Dr Stephen N Henson (steve@openssl.org) 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 * licensing@OpenSSL.org.
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 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com). */
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 #include <openssl/x509v3.h>
70
71 #include "../internal.h"
72 #include "../x509/internal.h"
73 #include "internal.h"
74
75 static int v3_check_critical(const char **value);
76 static int v3_check_generic(const char **value);
77 static X509_EXTENSION *do_ext_nconf(const CONF *conf, const X509V3_CTX *ctx,
78 int ext_nid, int crit, const char *value);
79 static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
80 int crit, int type,
81 const X509V3_CTX *ctx);
82 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
83 int crit, void *ext_struc);
84 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
85 size_t *ext_len);
86
X509V3_EXT_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * name,const char * value)87 X509_EXTENSION *X509V3_EXT_nconf(const CONF *conf, const X509V3_CTX *ctx,
88 const char *name, const char *value) {
89 // If omitted, fill in an empty |X509V3_CTX|.
90 X509V3_CTX ctx_tmp;
91 if (ctx == NULL) {
92 X509V3_set_ctx(&ctx_tmp, NULL, NULL, NULL, NULL, 0);
93 X509V3_set_nconf(&ctx_tmp, conf);
94 ctx = &ctx_tmp;
95 }
96
97 int crit = v3_check_critical(&value);
98 int ext_type = v3_check_generic(&value);
99 if (ext_type != 0) {
100 return v3_generic_extension(name, value, crit, ext_type, ctx);
101 }
102 X509_EXTENSION *ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
103 if (!ret) {
104 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
105 ERR_add_error_data(4, "name=", name, ", value=", value);
106 }
107 return ret;
108 }
109
X509V3_EXT_nconf_nid(const CONF * conf,const X509V3_CTX * ctx,int ext_nid,const char * value)110 X509_EXTENSION *X509V3_EXT_nconf_nid(const CONF *conf, const X509V3_CTX *ctx,
111 int ext_nid, const char *value) {
112 // If omitted, fill in an empty |X509V3_CTX|.
113 X509V3_CTX ctx_tmp;
114 if (ctx == NULL) {
115 X509V3_set_ctx(&ctx_tmp, NULL, NULL, NULL, NULL, 0);
116 X509V3_set_nconf(&ctx_tmp, conf);
117 ctx = &ctx_tmp;
118 }
119
120 int crit = v3_check_critical(&value);
121 int ext_type = v3_check_generic(&value);
122 if (ext_type != 0) {
123 return v3_generic_extension(OBJ_nid2sn(ext_nid), value, crit, ext_type,
124 ctx);
125 }
126 return do_ext_nconf(conf, ctx, ext_nid, crit, value);
127 }
128
129 // CONF *conf: Config file
130 // char *value: Value
do_ext_nconf(const CONF * conf,const X509V3_CTX * ctx,int ext_nid,int crit,const char * value)131 static X509_EXTENSION *do_ext_nconf(const CONF *conf, const X509V3_CTX *ctx,
132 int ext_nid, int crit, const char *value) {
133 const X509V3_EXT_METHOD *method;
134 X509_EXTENSION *ext;
135 const STACK_OF(CONF_VALUE) *nval;
136 STACK_OF(CONF_VALUE) *nval_owned = NULL;
137 void *ext_struc;
138 if (ext_nid == NID_undef) {
139 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
140 return NULL;
141 }
142 if (!(method = X509V3_EXT_get_nid(ext_nid))) {
143 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
144 return NULL;
145 }
146 // Now get internal extension representation based on type
147 if (method->v2i) {
148 if (*value == '@') {
149 // TODO(davidben): This is the only place where |X509V3_EXT_nconf|'s
150 // |conf| parameter is used. All other codepaths use the copy inside
151 // |ctx|. Should this be switched and then the parameter ignored?
152 if (conf == NULL) {
153 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
154 return NULL;
155 }
156 nval = NCONF_get_section(conf, value + 1);
157 } else {
158 nval_owned = X509V3_parse_list(value);
159 nval = nval_owned;
160 }
161 if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
162 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
163 ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value);
164 sk_CONF_VALUE_pop_free(nval_owned, X509V3_conf_free);
165 return NULL;
166 }
167 ext_struc = method->v2i(method, ctx, nval);
168 sk_CONF_VALUE_pop_free(nval_owned, X509V3_conf_free);
169 if (!ext_struc) {
170 return NULL;
171 }
172 } else if (method->s2i) {
173 if (!(ext_struc = method->s2i(method, ctx, value))) {
174 return NULL;
175 }
176 } else if (method->r2i) {
177 // TODO(davidben): Should this check be removed? This matches OpenSSL, but
178 // r2i-based extensions do not necessarily require a config database. The
179 // two built-in extensions only use it some of the time, and already handle
180 // |X509V3_get_section| returning NULL.
181 if (!ctx->db) {
182 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
183 return NULL;
184 }
185 if (!(ext_struc = method->r2i(method, ctx, value))) {
186 return NULL;
187 }
188 } else {
189 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
190 ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
191 return NULL;
192 }
193
194 ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
195 ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
196 return ext;
197 }
198
do_ext_i2d(const X509V3_EXT_METHOD * method,int ext_nid,int crit,void * ext_struc)199 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
200 int crit, void *ext_struc) {
201 // Convert the extension's internal representation to DER.
202 unsigned char *ext_der = NULL;
203 int ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
204 if (ext_len < 0) {
205 return NULL;
206 }
207
208 ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
209 if (ext_oct == NULL) {
210 OPENSSL_free(ext_der);
211 return NULL;
212 }
213 ASN1_STRING_set0(ext_oct, ext_der, ext_len);
214
215 X509_EXTENSION *ext =
216 X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
217 ASN1_OCTET_STRING_free(ext_oct);
218 return ext;
219 }
220
221 // Given an internal structure, nid and critical flag create an extension
222
X509V3_EXT_i2d(int ext_nid,int crit,void * ext_struc)223 X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) {
224 const X509V3_EXT_METHOD *method;
225 if (!(method = X509V3_EXT_get_nid(ext_nid))) {
226 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
227 return NULL;
228 }
229 return do_ext_i2d(method, ext_nid, crit, ext_struc);
230 }
231
232 // Check the extension string for critical flag
v3_check_critical(const char ** value)233 static int v3_check_critical(const char **value) {
234 const char *p = *value;
235 if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) {
236 return 0;
237 }
238 p += 9;
239 while (OPENSSL_isspace((unsigned char)*p)) {
240 p++;
241 }
242 *value = p;
243 return 1;
244 }
245
246 // Check extension string for generic extension and return the type
v3_check_generic(const char ** value)247 static int v3_check_generic(const char **value) {
248 int gen_type = 0;
249 const char *p = *value;
250 if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
251 p += 4;
252 gen_type = 1;
253 } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
254 p += 5;
255 gen_type = 2;
256 } else {
257 return 0;
258 }
259
260 while (OPENSSL_isspace((unsigned char)*p)) {
261 p++;
262 }
263 *value = p;
264 return gen_type;
265 }
266
267 // 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)268 static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
269 int crit, int gen_type,
270 const X509V3_CTX *ctx) {
271 unsigned char *ext_der = NULL;
272 size_t ext_len = 0;
273 ASN1_OBJECT *obj = NULL;
274 ASN1_OCTET_STRING *oct = NULL;
275 X509_EXTENSION *extension = NULL;
276 if (!(obj = OBJ_txt2obj(ext, 0))) {
277 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
278 ERR_add_error_data(2, "name=", ext);
279 goto err;
280 }
281
282 if (gen_type == 1) {
283 ext_der = x509v3_hex_to_bytes(value, &ext_len);
284 } else if (gen_type == 2) {
285 ext_der = generic_asn1(value, ctx, &ext_len);
286 }
287
288 if (ext_der == NULL) {
289 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
290 ERR_add_error_data(2, "value=", value);
291 goto err;
292 }
293
294 if (ext_len > INT_MAX) {
295 OPENSSL_PUT_ERROR(X509V3, ERR_R_OVERFLOW);
296 goto err;
297 }
298
299 oct = ASN1_OCTET_STRING_new();
300 if (oct == NULL) {
301 goto err;
302 }
303
304 ASN1_STRING_set0(oct, ext_der, (int)ext_len);
305 ext_der = NULL;
306
307 extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
308
309 err:
310 ASN1_OBJECT_free(obj);
311 ASN1_OCTET_STRING_free(oct);
312 OPENSSL_free(ext_der);
313 return extension;
314 }
315
generic_asn1(const char * value,const X509V3_CTX * ctx,size_t * ext_len)316 static unsigned char *generic_asn1(const char *value, const X509V3_CTX *ctx,
317 size_t *ext_len) {
318 ASN1_TYPE *typ = ASN1_generate_v3(value, ctx);
319 if (typ == NULL) {
320 return NULL;
321 }
322 unsigned char *ext_der = NULL;
323 int len = i2d_ASN1_TYPE(typ, &ext_der);
324 ASN1_TYPE_free(typ);
325 if (len < 0) {
326 return NULL;
327 }
328 *ext_len = len;
329 return ext_der;
330 }
331
332 // This is the main function: add a bunch of extensions based on a config
333 // file section to an extension STACK.
334
X509V3_EXT_add_nconf_sk(const CONF * conf,const X509V3_CTX * ctx,const char * section,STACK_OF (X509_EXTENSION)** sk)335 int X509V3_EXT_add_nconf_sk(const CONF *conf, const X509V3_CTX *ctx,
336 const char *section,
337 STACK_OF(X509_EXTENSION) **sk) {
338 const STACK_OF(CONF_VALUE) *nval = NCONF_get_section(conf, section);
339 if (nval == NULL) {
340 return 0;
341 }
342 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
343 const CONF_VALUE *val = sk_CONF_VALUE_value(nval, i);
344 X509_EXTENSION *ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value);
345 int ok = ext != NULL && //
346 (sk == NULL || X509v3_add_ext(sk, ext, -1) != NULL);
347 X509_EXTENSION_free(ext);
348 if (!ok) {
349 return 0;
350 }
351 }
352 return 1;
353 }
354
355 // Convenience functions to add extensions to a certificate, CRL and request
356
X509V3_EXT_add_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * section,X509 * cert)357 int X509V3_EXT_add_nconf(const CONF *conf, const X509V3_CTX *ctx,
358 const char *section, X509 *cert) {
359 STACK_OF(X509_EXTENSION) **sk = NULL;
360 if (cert) {
361 sk = &cert->cert_info->extensions;
362 }
363 return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
364 }
365
366 // Same as above but for a CRL
367
X509V3_EXT_CRL_add_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * section,X509_CRL * crl)368 int X509V3_EXT_CRL_add_nconf(const CONF *conf, const X509V3_CTX *ctx,
369 const char *section, X509_CRL *crl) {
370 STACK_OF(X509_EXTENSION) **sk = NULL;
371 if (crl) {
372 sk = &crl->crl->extensions;
373 }
374 return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
375 }
376
377 // Add extensions to certificate request
378
X509V3_EXT_REQ_add_nconf(const CONF * conf,const X509V3_CTX * ctx,const char * section,X509_REQ * req)379 int X509V3_EXT_REQ_add_nconf(const CONF *conf, const X509V3_CTX *ctx,
380 const char *section, X509_REQ *req) {
381 STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
382 int i;
383 if (req) {
384 sk = &extlist;
385 }
386 i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
387 if (!i || !sk) {
388 return i;
389 }
390 i = X509_REQ_add_extensions(req, extlist);
391 sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
392 return i;
393 }
394
395 // Config database functions
396
STACK_OF(CONF_VALUE)397 const STACK_OF(CONF_VALUE) *X509V3_get_section(const X509V3_CTX *ctx,
398 const char *section) {
399 if (ctx->db == NULL) {
400 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
401 return NULL;
402 }
403 return NCONF_get_section(ctx->db, section);
404 }
405
X509V3_set_nconf(X509V3_CTX * ctx,const CONF * conf)406 void X509V3_set_nconf(X509V3_CTX *ctx, const CONF *conf) {
407 ctx->db = conf;
408 }
409
X509V3_set_ctx(X509V3_CTX * ctx,const X509 * issuer,const X509 * subj,const X509_REQ * req,const X509_CRL * crl,int flags)410 void X509V3_set_ctx(X509V3_CTX *ctx, const X509 *issuer, const X509 *subj,
411 const X509_REQ *req, const X509_CRL *crl, int flags) {
412 OPENSSL_memset(ctx, 0, sizeof(*ctx));
413 ctx->issuer_cert = issuer;
414 ctx->subject_cert = subj;
415 ctx->crl = crl;
416 ctx->subject_req = req;
417 ctx->flags = flags;
418 }
419