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