Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/x509/x509_conf.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: x509_conf.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 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
 */
58
/* extension creation utilities */
59
60
#include <ctype.h>
61
#include <stdio.h>
62
#include <string.h>
63
64
#include <openssl/conf.h>
65
#include <openssl/err.h>
66
#include <openssl/x509.h>
67
#include <openssl/x509v3.h>
68
69
#include "x509_lcl.h"
70
71
static int v3_check_critical(const char **value);
72
static int v3_check_generic(const char **value);
73
static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
74
    int crit, const char *value);
75
static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value,
76
    int crit, int type, X509V3_CTX *ctx);
77
static char *conf_lhash_get_string(void *db, const char *section,
78
    const char *value);
79
static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db,
80
    const char *section);
81
static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
82
    int crit, void *ext_struc);
83
static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx,
84
    long *ext_len);
85
86
/* CONF *conf:  Config file    */
87
/* char *name:  Name    */
88
/* char *value:  Value    */
89
X509_EXTENSION *
90
X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
91
    const char *value)
92
0
{
93
0
  int crit;
94
0
  int ext_type;
95
0
  X509_EXTENSION *ret;
96
97
0
  crit = v3_check_critical(&value);
98
0
  if ((ext_type = v3_check_generic(&value)))
99
0
    return v3_generic_extension(name, value, crit, ext_type, ctx);
100
0
  ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
101
0
  if (!ret) {
102
0
    X509V3error(X509V3_R_ERROR_IN_EXTENSION);
103
0
    ERR_asprintf_error_data("name=%s, value=%s", name, value);
104
0
  }
105
0
  return ret;
106
0
}
107
108
/* CONF *conf:  Config file    */
109
/* char *value:  Value    */
110
X509_EXTENSION *
111
X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
112
    const char *value)
113
0
{
114
0
  int crit;
115
0
  int ext_type;
116
117
0
  crit = v3_check_critical(&value);
118
0
  if ((ext_type = v3_check_generic(&value)))
119
0
    return v3_generic_extension(OBJ_nid2sn(ext_nid),
120
0
        value, crit, ext_type, ctx);
121
0
  return do_ext_nconf(conf, ctx, ext_nid, crit, value);
122
0
}
123
124
/* CONF *conf:  Config file    */
125
/* char *value:  Value    */
126
static X509_EXTENSION *
127
do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit,
128
    const char *value)
129
0
{
130
0
  const X509V3_EXT_METHOD *method;
131
0
  X509_EXTENSION *ext;
132
0
  void *ext_struc;
133
134
0
  if (ext_nid == NID_undef) {
135
0
    X509V3error(X509V3_R_UNKNOWN_EXTENSION_NAME);
136
0
    return NULL;
137
0
  }
138
0
  if (!(method = X509V3_EXT_get_nid(ext_nid))) {
139
0
    X509V3error(X509V3_R_UNKNOWN_EXTENSION);
140
0
    return NULL;
141
0
  }
142
  /* Now get internal extension representation based on type */
143
0
  if (method->v2i) {
144
0
    STACK_OF(CONF_VALUE) *nval;
145
146
0
    if (*value == '@')
147
0
      nval = NCONF_get_section(conf, value + 1);
148
0
    else
149
0
      nval = X509V3_parse_list(value);
150
0
    if (sk_CONF_VALUE_num(nval) <= 0) {
151
0
      X509V3error(X509V3_R_INVALID_EXTENSION_STRING);
152
0
      ERR_asprintf_error_data("name=%s,section=%s",
153
0
          OBJ_nid2sn(ext_nid), value);
154
0
      if (*value != '@')
155
0
        sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
156
0
      return NULL;
157
0
    }
158
0
    ext_struc = method->v2i(method, ctx, nval);
159
0
    if (*value != '@')
160
0
      sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
161
0
  } else if (method->s2i) {
162
0
    ext_struc = method->s2i(method, ctx, value);
163
0
  } else if (method->r2i) {
164
0
    if (!ctx->db || !ctx->db_meth) {
165
0
      X509V3error(X509V3_R_NO_CONFIG_DATABASE);
166
0
      return NULL;
167
0
    }
168
0
    ext_struc = method->r2i(method, ctx, value);
169
0
  } else {
170
0
    X509V3error(X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
171
0
    ERR_asprintf_error_data("name=%s", OBJ_nid2sn(ext_nid));
172
0
    return NULL;
173
0
  }
174
0
  if (ext_struc == NULL)
175
0
    return NULL;
176
177
0
  ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
178
0
  if (method->it)
179
0
    ASN1_item_free(ext_struc, method->it);
180
0
  else
181
0
    method->ext_free(ext_struc);
182
0
  return ext;
183
0
}
184
185
static X509_EXTENSION *
186
do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit,
187
    void *ext_struc)
188
0
{
189
0
  unsigned char *ext_der;
190
0
  int ext_len;
191
0
  ASN1_OCTET_STRING *ext_oct = NULL;
192
0
  X509_EXTENSION *ext;
193
194
  /* Convert internal representation to DER */
195
0
  if (method->it) {
196
0
    ext_der = NULL;
197
0
    ext_len = ASN1_item_i2d(ext_struc, &ext_der,
198
0
        method->it);
199
0
    if (ext_len < 0)
200
0
      goto merr;
201
0
  } else {
202
0
    unsigned char *p;
203
0
    ext_len = method->i2d(ext_struc, NULL);
204
0
    if (!(ext_der = malloc(ext_len)))
205
0
      goto merr;
206
0
    p = ext_der;
207
0
    method->i2d(ext_struc, &p);
208
0
  }
209
0
  if (!(ext_oct = ASN1_OCTET_STRING_new()))
210
0
    goto merr;
211
0
  ext_oct->data = ext_der;
212
0
  ext_oct->length = ext_len;
213
214
0
  ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
215
0
  if (!ext)
216
0
    goto merr;
217
0
  ASN1_OCTET_STRING_free(ext_oct);
218
219
0
  return ext;
220
221
0
merr:
222
0
  ASN1_OCTET_STRING_free(ext_oct);
223
0
  X509V3error(ERR_R_MALLOC_FAILURE);
224
0
  return NULL;
225
226
0
}
227
228
/* Given an internal structure, nid and critical flag create an extension */
229
230
X509_EXTENSION *
231
X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
232
0
{
233
0
  const X509V3_EXT_METHOD *method;
234
235
0
  if (!(method = X509V3_EXT_get_nid(ext_nid))) {
236
0
    X509V3error(X509V3_R_UNKNOWN_EXTENSION);
237
0
    return NULL;
238
0
  }
239
0
  return do_ext_i2d(method, ext_nid, crit, ext_struc);
240
0
}
241
242
/* Check the extension string for critical flag */
243
static int
244
v3_check_critical(const char **value)
245
0
{
246
0
  const char *p = *value;
247
248
0
  if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
249
0
    return 0;
250
0
  p += 9;
251
0
  while (isspace((unsigned char)*p)) p++;
252
0
    *value = p;
253
0
  return 1;
254
0
}
255
256
/* Check extension string for generic extension and return the type */
257
static int
258
v3_check_generic(const char **value)
259
0
{
260
0
  int gen_type = 0;
261
0
  const char *p = *value;
262
263
0
  if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
264
0
    p += 4;
265
0
    gen_type = 1;
266
0
  } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
267
0
    p += 5;
268
0
    gen_type = 2;
269
0
  } else
270
0
    return 0;
271
272
0
  while (isspace((unsigned char)*p))
273
0
    p++;
274
0
  *value = p;
275
0
  return gen_type;
276
0
}
277
278
/* Create a generic extension: for now just handle DER type */
279
static X509_EXTENSION *
280
v3_generic_extension(const char *ext, const char *value, int crit, int gen_type,
281
    X509V3_CTX *ctx)
282
0
{
283
0
  unsigned char *ext_der = NULL;
284
0
  long ext_len = 0;
285
0
  ASN1_OBJECT *obj = NULL;
286
0
  ASN1_OCTET_STRING *oct = NULL;
287
0
  X509_EXTENSION *extension = NULL;
288
289
0
  if (!(obj = OBJ_txt2obj(ext, 0))) {
290
0
    X509V3error(X509V3_R_EXTENSION_NAME_ERROR);
291
0
    ERR_asprintf_error_data("name=%s", ext);
292
0
    goto err;
293
0
  }
294
295
0
  if (gen_type == 1)
296
0
    ext_der = string_to_hex(value, &ext_len);
297
0
  else if (gen_type == 2)
298
0
    ext_der = generic_asn1(value, ctx, &ext_len);
299
0
  else {
300
0
    ERR_asprintf_error_data("Unexpected generic extension type %d", gen_type);
301
0
    goto err;
302
0
  }
303
304
0
  if (ext_der == NULL) {
305
0
    X509V3error(X509V3_R_EXTENSION_VALUE_ERROR);
306
0
    ERR_asprintf_error_data("value=%s", value);
307
0
    goto err;
308
0
  }
309
310
0
  if (!(oct = ASN1_OCTET_STRING_new())) {
311
0
    X509V3error(ERR_R_MALLOC_FAILURE);
312
0
    goto err;
313
0
  }
314
315
0
  oct->data = ext_der;
316
0
  oct->length = ext_len;
317
0
  ext_der = NULL;
318
319
0
  extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
320
321
0
err:
322
0
  ASN1_OBJECT_free(obj);
323
0
  ASN1_OCTET_STRING_free(oct);
324
0
  free(ext_der);
325
0
  return extension;
326
0
}
327
328
static unsigned char *
329
generic_asn1(const char *value, X509V3_CTX *ctx, long *ext_len)
330
0
{
331
0
  ASN1_TYPE *typ;
332
0
  unsigned char *ext_der = NULL;
333
334
0
  typ = ASN1_generate_v3(value, ctx);
335
0
  if (typ == NULL)
336
0
    return NULL;
337
0
  *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
338
0
  ASN1_TYPE_free(typ);
339
0
  return ext_der;
340
0
}
341
342
/* This is the main function: add a bunch of extensions based on a config file
343
 * section to an extension STACK.
344
 */
345
346
int
347
X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
348
    STACK_OF(X509_EXTENSION) **sk)
349
0
{
350
0
  X509_EXTENSION *ext;
351
0
  STACK_OF(CONF_VALUE) *nval;
352
0
  CONF_VALUE *val;
353
0
  int i;
354
355
0
  if (!(nval = NCONF_get_section(conf, section)))
356
0
    return 0;
357
0
  for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
358
0
    val = sk_CONF_VALUE_value(nval, i);
359
0
    if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
360
0
      return 0;
361
0
    if (sk)
362
0
      X509v3_add_ext(sk, ext, -1);
363
0
    X509_EXTENSION_free(ext);
364
0
  }
365
0
  return 1;
366
0
}
367
368
/* Convenience functions to add extensions to a certificate, CRL and request */
369
370
int
371
X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
372
    X509 *cert)
373
0
{
374
0
  STACK_OF(X509_EXTENSION) **sk = NULL;
375
376
0
  if (cert)
377
0
    sk = &cert->cert_info->extensions;
378
0
  return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
379
0
}
380
381
/* Same as above but for a CRL */
382
383
int
384
X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
385
    X509_CRL *crl)
386
0
{
387
0
  STACK_OF(X509_EXTENSION) **sk = NULL;
388
389
0
  if (crl)
390
0
    sk = &crl->crl->extensions;
391
0
  return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
392
0
}
393
394
/* Add extensions to certificate request */
395
396
int
397
X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
398
    X509_REQ *req)
399
0
{
400
0
  STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
401
0
  int i;
402
403
0
  if (req)
404
0
    sk = &extlist;
405
0
  i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
406
0
  if (!i || !sk)
407
0
    return i;
408
0
  i = X509_REQ_add_extensions(req, extlist);
409
0
  sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
410
0
  return i;
411
0
}
412
413
/* Config database functions */
414
415
char *
416
X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section)
417
0
{
418
0
  if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
419
0
    X509V3error(X509V3_R_OPERATION_NOT_DEFINED);
420
0
    return NULL;
421
0
  }
422
0
  return ctx->db_meth->get_string(ctx->db, name, section);
423
0
}
424
425
STACK_OF(CONF_VALUE) *
426
X509V3_get_section(X509V3_CTX *ctx, const char *section)
427
0
{
428
0
  if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
429
0
    X509V3error(X509V3_R_OPERATION_NOT_DEFINED);
430
0
    return NULL;
431
0
  }
432
0
  return ctx->db_meth->get_section(ctx->db, section);
433
0
}
434
435
void
436
X509V3_string_free(X509V3_CTX *ctx, char *str)
437
0
{
438
0
  if (!str)
439
0
    return;
440
0
  if (ctx->db_meth->free_string)
441
0
    ctx->db_meth->free_string(ctx->db, str);
442
0
}
443
444
void
445
X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
446
0
{
447
0
  if (!section)
448
0
    return;
449
0
  if (ctx->db_meth->free_section)
450
0
    ctx->db_meth->free_section(ctx->db, section);
451
0
}
452
453
static char *
454
nconf_get_string(void *db, const char *section, const char *value)
455
0
{
456
0
  return NCONF_get_string(db, section, value);
457
0
}
458
459
static STACK_OF(CONF_VALUE) *
460
nconf_get_section(void *db, const char *section)
461
0
{
462
0
  return NCONF_get_section(db, section);
463
0
}
464
465
static X509V3_CONF_METHOD nconf_method = {
466
  nconf_get_string,
467
  nconf_get_section,
468
  NULL,
469
  NULL
470
};
471
472
void
473
X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
474
0
{
475
0
  ctx->db_meth = &nconf_method;
476
0
  ctx->db = conf;
477
0
}
478
479
void
480
X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
481
    X509_CRL *crl, int flags)
482
0
{
483
0
  ctx->issuer_cert = issuer;
484
0
  ctx->subject_cert = subj;
485
0
  ctx->crl = crl;
486
0
  ctx->subject_req = req;
487
0
  ctx->flags = flags;
488
0
}
489
490
/* Old conf compatibility functions */
491
492
X509_EXTENSION *
493
X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, const char *name,
494
    const char *value)
495
0
{
496
0
  CONF ctmp;
497
498
0
  CONF_set_nconf(&ctmp, conf);
499
0
  return X509V3_EXT_nconf(&ctmp, ctx, name, value);
500
0
}
501
502
/* LHASH *conf:  Config file    */
503
/* char *value:  Value    */
504
X509_EXTENSION *
505
X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, int ext_nid,
506
    const char *value)
507
0
{
508
0
  CONF ctmp;
509
510
0
  CONF_set_nconf(&ctmp, conf);
511
0
  return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value);
512
0
}
513
514
static char *
515
conf_lhash_get_string(void *db, const char *section, const char *value)
516
0
{
517
0
  return CONF_get_string(db, section, value);
518
0
}
519
520
static STACK_OF(CONF_VALUE) *
521
conf_lhash_get_section(void *db, const char *section)
522
0
{
523
0
  return CONF_get_section(db, section);
524
0
}
525
526
static X509V3_CONF_METHOD conf_lhash_method = {
527
  conf_lhash_get_string,
528
  conf_lhash_get_section,
529
  NULL,
530
  NULL
531
};
532
533
void
534
X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash)
535
0
{
536
0
  ctx->db_meth = &conf_lhash_method;
537
0
  ctx->db = lhash;
538
0
}
539
540
int
541
X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
542
    const char *section, X509 *cert)
543
0
{
544
0
  CONF ctmp;
545
546
0
  CONF_set_nconf(&ctmp, conf);
547
0
  return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert);
548
0
}
549
550
/* Same as above but for a CRL */
551
552
int
553
X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
554
    const char *section, X509_CRL *crl)
555
0
{
556
0
  CONF ctmp;
557
558
0
  CONF_set_nconf(&ctmp, conf);
559
0
  return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl);
560
0
}
561
562
/* Add extensions to certificate request */
563
564
int
565
X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
566
    const char *section, X509_REQ *req)
567
0
{
568
0
  CONF ctmp;
569
570
0
  CONF_set_nconf(&ctmp, conf);
571
0
  return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req);
572
0
}