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