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