1 /* $OpenBSD: ts_conf.c,v 1.12 2023/07/07 07:25:21 beck Exp $ */ 2 /* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL 3 * project 2002. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2006 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 59 #include <string.h> 60 61 #include <openssl/opensslconf.h> 62 63 #include <openssl/crypto.h> 64 #include <openssl/err.h> 65 #include <openssl/pem.h> 66 #include <openssl/ts.h> 67 68 #ifndef OPENSSL_NO_ENGINE 69 #include <openssl/engine.h> 70 #endif 71 72 /* Macro definitions for the configuration file. */ 73 74 #define BASE_SECTION "tsa" 75 #define ENV_DEFAULT_TSA "default_tsa" 76 #define ENV_SERIAL "serial" 77 #define ENV_CRYPTO_DEVICE "crypto_device" 78 #define ENV_SIGNER_CERT "signer_cert" 79 #define ENV_CERTS "certs" 80 #define ENV_SIGNER_KEY "signer_key" 81 #define ENV_DEFAULT_POLICY "default_policy" 82 #define ENV_OTHER_POLICIES "other_policies" 83 #define ENV_DIGESTS "digests" 84 #define ENV_ACCURACY "accuracy" 85 #define ENV_ORDERING "ordering" 86 #define ENV_TSA_NAME "tsa_name" 87 #define ENV_ESS_CERT_ID_CHAIN "ess_cert_id_chain" 88 #define ENV_VALUE_SECS "secs" 89 #define ENV_VALUE_MILLISECS "millisecs" 90 #define ENV_VALUE_MICROSECS "microsecs" 91 #define ENV_CLOCK_PRECISION_DIGITS "clock_precision_digits" 92 #define ENV_VALUE_YES "yes" 93 #define ENV_VALUE_NO "no" 94 95 /* Function definitions for certificate and key loading. */ 96 97 X509 * 98 TS_CONF_load_cert(const char *file) 99 { 100 BIO *cert = NULL; 101 X509 *x = NULL; 102 103 if ((cert = BIO_new_file(file, "r")) == NULL) 104 goto end; 105 x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); 106 107 end: 108 if (x == NULL) 109 fprintf(stderr, "unable to load certificate: %s\n", file); 110 BIO_free(cert); 111 return x; 112 } 113 LCRYPTO_ALIAS(TS_CONF_load_cert); 114 115 STACK_OF(X509) * 116 TS_CONF_load_certs(const char *file) 117 { 118 BIO *certs = NULL; 119 STACK_OF(X509) *othercerts = NULL; 120 STACK_OF(X509_INFO) *allcerts = NULL; 121 int i; 122 123 if (!(certs = BIO_new_file(file, "r"))) 124 goto end; 125 126 if (!(othercerts = sk_X509_new_null())) 127 goto end; 128 allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL); 129 for (i = 0; i < sk_X509_INFO_num(allcerts); i++) { 130 X509_INFO *xi = sk_X509_INFO_value(allcerts, i); 131 if (xi->x509) { 132 if (sk_X509_push(othercerts, xi->x509) == 0) { 133 sk_X509_pop_free(othercerts, X509_free); 134 othercerts = NULL; 135 goto end; 136 } 137 xi->x509 = NULL; 138 } 139 } 140 141 end: 142 if (othercerts == NULL) 143 fprintf(stderr, "unable to load certificates: %s\n", file); 144 sk_X509_INFO_pop_free(allcerts, X509_INFO_free); 145 BIO_free(certs); 146 return othercerts; 147 } 148 LCRYPTO_ALIAS(TS_CONF_load_certs); 149 150 EVP_PKEY * 151 TS_CONF_load_key(const char *file, const char *pass) 152 { 153 BIO *key = NULL; 154 EVP_PKEY *pkey = NULL; 155 156 if (!(key = BIO_new_file(file, "r"))) 157 goto end; 158 pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *) pass); 159 160 end: 161 if (pkey == NULL) 162 fprintf(stderr, "unable to load private key: %s\n", file); 163 BIO_free(key); 164 return pkey; 165 } 166 LCRYPTO_ALIAS(TS_CONF_load_key); 167 168 /* Function definitions for handling configuration options. */ 169 170 static void 171 TS_CONF_lookup_fail(const char *name, const char *tag) 172 { 173 fprintf(stderr, "variable lookup failed for %s::%s\n", name, tag); 174 } 175 176 static void 177 TS_CONF_invalid(const char *name, const char *tag) 178 { 179 fprintf(stderr, "invalid variable value for %s::%s\n", name, tag); 180 } 181 182 const char * 183 TS_CONF_get_tsa_section(CONF *conf, const char *section) 184 { 185 if (!section) { 186 section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_TSA); 187 if (!section) 188 TS_CONF_lookup_fail(BASE_SECTION, ENV_DEFAULT_TSA); 189 } 190 return section; 191 } 192 LCRYPTO_ALIAS(TS_CONF_get_tsa_section); 193 194 int 195 TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, 196 TS_RESP_CTX *ctx) 197 { 198 int ret = 0; 199 char *serial = NCONF_get_string(conf, section, ENV_SERIAL); 200 201 if (!serial) { 202 TS_CONF_lookup_fail(section, ENV_SERIAL); 203 goto err; 204 } 205 TS_RESP_CTX_set_serial_cb(ctx, cb, serial); 206 207 ret = 1; 208 209 err: 210 return ret; 211 } 212 LCRYPTO_ALIAS(TS_CONF_set_serial); 213 214 #ifndef OPENSSL_NO_ENGINE 215 216 int 217 TS_CONF_set_crypto_device(CONF *conf, const char *section, const char *device) 218 { 219 int ret = 0; 220 221 if (!device) 222 device = NCONF_get_string(conf, section, ENV_CRYPTO_DEVICE); 223 224 if (device && !TS_CONF_set_default_engine(device)) { 225 TS_CONF_invalid(section, ENV_CRYPTO_DEVICE); 226 goto err; 227 } 228 ret = 1; 229 230 err: 231 return ret; 232 } 233 LCRYPTO_ALIAS(TS_CONF_set_crypto_device); 234 235 int 236 TS_CONF_set_default_engine(const char *name) 237 { 238 ENGINE *e = NULL; 239 int ret = 0; 240 241 /* Leave the default if builtin specified. */ 242 if (strcmp(name, "builtin") == 0) 243 return 1; 244 245 if (!(e = ENGINE_by_id(name))) 246 goto err; 247 /* All the operations are going to be carried out by the engine. */ 248 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) 249 goto err; 250 ret = 1; 251 252 err: 253 if (!ret) { 254 TSerror(TS_R_COULD_NOT_SET_ENGINE); 255 ERR_asprintf_error_data("engine:%s", name); 256 } 257 ENGINE_free(e); 258 return ret; 259 } 260 LCRYPTO_ALIAS(TS_CONF_set_default_engine); 261 262 #endif 263 264 int 265 TS_CONF_set_signer_cert(CONF *conf, const char *section, const char *cert, 266 TS_RESP_CTX *ctx) 267 { 268 int ret = 0; 269 X509 *cert_obj = NULL; 270 271 if (!cert) 272 cert = NCONF_get_string(conf, section, ENV_SIGNER_CERT); 273 if (!cert) { 274 TS_CONF_lookup_fail(section, ENV_SIGNER_CERT); 275 goto err; 276 } 277 if (!(cert_obj = TS_CONF_load_cert(cert))) 278 goto err; 279 if (!TS_RESP_CTX_set_signer_cert(ctx, cert_obj)) 280 goto err; 281 282 ret = 1; 283 284 err: 285 X509_free(cert_obj); 286 return ret; 287 } 288 LCRYPTO_ALIAS(TS_CONF_set_signer_cert); 289 290 int 291 TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, 292 TS_RESP_CTX *ctx) 293 { 294 int ret = 0; 295 STACK_OF(X509) *certs_obj = NULL; 296 297 if (!certs) 298 certs = NCONF_get_string(conf, section, ENV_CERTS); 299 /* Certificate chain is optional. */ 300 if (!certs) 301 goto end; 302 if (!(certs_obj = TS_CONF_load_certs(certs))) 303 goto err; 304 if (!TS_RESP_CTX_set_certs(ctx, certs_obj)) 305 goto err; 306 307 end: 308 ret = 1; 309 err: 310 sk_X509_pop_free(certs_obj, X509_free); 311 return ret; 312 } 313 LCRYPTO_ALIAS(TS_CONF_set_certs); 314 315 int 316 TS_CONF_set_signer_key(CONF *conf, const char *section, const char *key, 317 const char *pass, TS_RESP_CTX *ctx) 318 { 319 int ret = 0; 320 EVP_PKEY *key_obj = NULL; 321 322 if (!key) 323 key = NCONF_get_string(conf, section, ENV_SIGNER_KEY); 324 if (!key) { 325 TS_CONF_lookup_fail(section, ENV_SIGNER_KEY); 326 goto err; 327 } 328 if (!(key_obj = TS_CONF_load_key(key, pass))) 329 goto err; 330 if (!TS_RESP_CTX_set_signer_key(ctx, key_obj)) 331 goto err; 332 333 ret = 1; 334 335 err: 336 EVP_PKEY_free(key_obj); 337 return ret; 338 } 339 LCRYPTO_ALIAS(TS_CONF_set_signer_key); 340 341 int 342 TS_CONF_set_def_policy(CONF *conf, const char *section, const char *policy, 343 TS_RESP_CTX *ctx) 344 { 345 int ret = 0; 346 ASN1_OBJECT *policy_obj = NULL; 347 348 if (!policy) 349 policy = NCONF_get_string(conf, section, ENV_DEFAULT_POLICY); 350 if (!policy) { 351 TS_CONF_lookup_fail(section, ENV_DEFAULT_POLICY); 352 goto err; 353 } 354 if (!(policy_obj = OBJ_txt2obj(policy, 0))) { 355 TS_CONF_invalid(section, ENV_DEFAULT_POLICY); 356 goto err; 357 } 358 if (!TS_RESP_CTX_set_def_policy(ctx, policy_obj)) 359 goto err; 360 361 ret = 1; 362 363 err: 364 ASN1_OBJECT_free(policy_obj); 365 return ret; 366 } 367 LCRYPTO_ALIAS(TS_CONF_set_def_policy); 368 369 int 370 TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx) 371 { 372 int ret = 0; 373 int i; 374 STACK_OF(CONF_VALUE) *list = NULL; 375 char *policies = NCONF_get_string(conf, section, ENV_OTHER_POLICIES); 376 377 /* If no other policy is specified, that's fine. */ 378 if (policies && !(list = X509V3_parse_list(policies))) { 379 TS_CONF_invalid(section, ENV_OTHER_POLICIES); 380 goto err; 381 } 382 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 383 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 384 const char *extval = val->value ? val->value : val->name; 385 ASN1_OBJECT *objtmp; 386 if (!(objtmp = OBJ_txt2obj(extval, 0))) { 387 TS_CONF_invalid(section, ENV_OTHER_POLICIES); 388 goto err; 389 } 390 if (!TS_RESP_CTX_add_policy(ctx, objtmp)) 391 goto err; 392 ASN1_OBJECT_free(objtmp); 393 } 394 395 ret = 1; 396 397 err: 398 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 399 return ret; 400 } 401 LCRYPTO_ALIAS(TS_CONF_set_policies); 402 403 int 404 TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx) 405 { 406 int ret = 0; 407 int i; 408 STACK_OF(CONF_VALUE) *list = NULL; 409 char *digests = NCONF_get_string(conf, section, ENV_DIGESTS); 410 411 if (!digests) { 412 TS_CONF_lookup_fail(section, ENV_DIGESTS); 413 goto err; 414 } 415 if (!(list = X509V3_parse_list(digests))) { 416 TS_CONF_invalid(section, ENV_DIGESTS); 417 goto err; 418 } 419 if (sk_CONF_VALUE_num(list) == 0) { 420 TS_CONF_invalid(section, ENV_DIGESTS); 421 goto err; 422 } 423 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 424 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 425 const char *extval = val->value ? val->value : val->name; 426 const EVP_MD *md; 427 if (!(md = EVP_get_digestbyname(extval))) { 428 TS_CONF_invalid(section, ENV_DIGESTS); 429 goto err; 430 } 431 if (!TS_RESP_CTX_add_md(ctx, md)) 432 goto err; 433 } 434 435 ret = 1; 436 437 err: 438 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 439 return ret; 440 } 441 LCRYPTO_ALIAS(TS_CONF_set_digests); 442 443 int 444 TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx) 445 { 446 int ret = 0; 447 int i; 448 int secs = 0, millis = 0, micros = 0; 449 STACK_OF(CONF_VALUE) *list = NULL; 450 char *accuracy = NCONF_get_string(conf, section, ENV_ACCURACY); 451 452 if (accuracy && !(list = X509V3_parse_list(accuracy))) { 453 TS_CONF_invalid(section, ENV_ACCURACY); 454 goto err; 455 } 456 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 457 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 458 if (strcmp(val->name, ENV_VALUE_SECS) == 0) { 459 if (val->value) 460 secs = atoi(val->value); 461 } else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0) { 462 if (val->value) 463 millis = atoi(val->value); 464 } else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0) { 465 if (val->value) 466 micros = atoi(val->value); 467 } else { 468 TS_CONF_invalid(section, ENV_ACCURACY); 469 goto err; 470 } 471 } 472 if (!TS_RESP_CTX_set_accuracy(ctx, secs, millis, micros)) 473 goto err; 474 475 ret = 1; 476 477 err: 478 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 479 return ret; 480 } 481 LCRYPTO_ALIAS(TS_CONF_set_accuracy); 482 483 int 484 TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, 485 TS_RESP_CTX *ctx) 486 { 487 int ret = 0; 488 long digits = 0; 489 490 /* If not specified, set the default value to 0, i.e. sec precision */ 491 if (!NCONF_get_number_e(conf, section, ENV_CLOCK_PRECISION_DIGITS, 492 &digits)) 493 digits = 0; 494 if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS) { 495 TS_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS); 496 goto err; 497 } 498 499 if (!TS_RESP_CTX_set_clock_precision_digits(ctx, digits)) 500 goto err; 501 502 return 1; 503 504 err: 505 return ret; 506 } 507 LCRYPTO_ALIAS(TS_CONF_set_clock_precision_digits); 508 509 static int 510 TS_CONF_add_flag(CONF *conf, const char *section, const char *field, int flag, 511 TS_RESP_CTX *ctx) 512 { 513 /* Default is false. */ 514 const char *value = NCONF_get_string(conf, section, field); 515 516 if (value) { 517 if (strcmp(value, ENV_VALUE_YES) == 0) 518 TS_RESP_CTX_add_flags(ctx, flag); 519 else if (strcmp(value, ENV_VALUE_NO) != 0) { 520 TS_CONF_invalid(section, field); 521 return 0; 522 } 523 } 524 525 return 1; 526 } 527 528 int 529 TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx) 530 { 531 return TS_CONF_add_flag(conf, section, ENV_ORDERING, TS_ORDERING, ctx); 532 } 533 LCRYPTO_ALIAS(TS_CONF_set_ordering); 534 535 int 536 TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx) 537 { 538 return TS_CONF_add_flag(conf, section, ENV_TSA_NAME, TS_TSA_NAME, ctx); 539 } 540 LCRYPTO_ALIAS(TS_CONF_set_tsa_name); 541 542 int 543 TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, TS_RESP_CTX *ctx) 544 { 545 return TS_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN, 546 TS_ESS_CERT_ID_CHAIN, ctx); 547 } 548 LCRYPTO_ALIAS(TS_CONF_set_ess_cert_id_chain); 549