1 /* $OpenBSD: ts_conf.c,v 1.8 2014/10/28 05:46:56 miod 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 TSerr(TS_F_TS_CONF_SET_DEFAULT_ENGINE, 249 TS_R_COULD_NOT_SET_ENGINE); 250 ERR_asprintf_error_data("engine:%s", name); 251 } 252 if (e) 253 ENGINE_free(e); 254 return ret; 255 } 256 257 #endif 258 259 int 260 TS_CONF_set_signer_cert(CONF *conf, const char *section, const char *cert, 261 TS_RESP_CTX *ctx) 262 { 263 int ret = 0; 264 X509 *cert_obj = NULL; 265 266 if (!cert) 267 cert = NCONF_get_string(conf, section, ENV_SIGNER_CERT); 268 if (!cert) { 269 TS_CONF_lookup_fail(section, ENV_SIGNER_CERT); 270 goto err; 271 } 272 if (!(cert_obj = TS_CONF_load_cert(cert))) 273 goto err; 274 if (!TS_RESP_CTX_set_signer_cert(ctx, cert_obj)) 275 goto err; 276 277 ret = 1; 278 279 err: 280 X509_free(cert_obj); 281 return ret; 282 } 283 284 int 285 TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, 286 TS_RESP_CTX *ctx) 287 { 288 int ret = 0; 289 STACK_OF(X509) *certs_obj = NULL; 290 291 if (!certs) 292 certs = NCONF_get_string(conf, section, ENV_CERTS); 293 /* Certificate chain is optional. */ 294 if (!certs) 295 goto end; 296 if (!(certs_obj = TS_CONF_load_certs(certs))) 297 goto err; 298 if (!TS_RESP_CTX_set_certs(ctx, certs_obj)) 299 goto err; 300 301 end: 302 ret = 1; 303 err: 304 sk_X509_pop_free(certs_obj, X509_free); 305 return ret; 306 } 307 308 int 309 TS_CONF_set_signer_key(CONF *conf, const char *section, const char *key, 310 const char *pass, TS_RESP_CTX *ctx) 311 { 312 int ret = 0; 313 EVP_PKEY *key_obj = NULL; 314 315 if (!key) 316 key = NCONF_get_string(conf, section, ENV_SIGNER_KEY); 317 if (!key) { 318 TS_CONF_lookup_fail(section, ENV_SIGNER_KEY); 319 goto err; 320 } 321 if (!(key_obj = TS_CONF_load_key(key, pass))) 322 goto err; 323 if (!TS_RESP_CTX_set_signer_key(ctx, key_obj)) 324 goto err; 325 326 ret = 1; 327 328 err: 329 EVP_PKEY_free(key_obj); 330 return ret; 331 } 332 333 int 334 TS_CONF_set_def_policy(CONF *conf, const char *section, const char *policy, 335 TS_RESP_CTX *ctx) 336 { 337 int ret = 0; 338 ASN1_OBJECT *policy_obj = NULL; 339 340 if (!policy) 341 policy = NCONF_get_string(conf, section, ENV_DEFAULT_POLICY); 342 if (!policy) { 343 TS_CONF_lookup_fail(section, ENV_DEFAULT_POLICY); 344 goto err; 345 } 346 if (!(policy_obj = OBJ_txt2obj(policy, 0))) { 347 TS_CONF_invalid(section, ENV_DEFAULT_POLICY); 348 goto err; 349 } 350 if (!TS_RESP_CTX_set_def_policy(ctx, policy_obj)) 351 goto err; 352 353 ret = 1; 354 355 err: 356 ASN1_OBJECT_free(policy_obj); 357 return ret; 358 } 359 360 int 361 TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx) 362 { 363 int ret = 0; 364 int i; 365 STACK_OF(CONF_VALUE) *list = NULL; 366 char *policies = NCONF_get_string(conf, section, ENV_OTHER_POLICIES); 367 368 /* If no other policy is specified, that's fine. */ 369 if (policies && !(list = X509V3_parse_list(policies))) { 370 TS_CONF_invalid(section, ENV_OTHER_POLICIES); 371 goto err; 372 } 373 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 374 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 375 const char *extval = val->value ? val->value : val->name; 376 ASN1_OBJECT *objtmp; 377 if (!(objtmp = OBJ_txt2obj(extval, 0))) { 378 TS_CONF_invalid(section, ENV_OTHER_POLICIES); 379 goto err; 380 } 381 if (!TS_RESP_CTX_add_policy(ctx, objtmp)) 382 goto err; 383 ASN1_OBJECT_free(objtmp); 384 } 385 386 ret = 1; 387 388 err: 389 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 390 return ret; 391 } 392 393 int 394 TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx) 395 { 396 int ret = 0; 397 int i; 398 STACK_OF(CONF_VALUE) *list = NULL; 399 char *digests = NCONF_get_string(conf, section, ENV_DIGESTS); 400 401 if (!digests) { 402 TS_CONF_lookup_fail(section, ENV_DIGESTS); 403 goto err; 404 } 405 if (!(list = X509V3_parse_list(digests))) { 406 TS_CONF_invalid(section, ENV_DIGESTS); 407 goto err; 408 } 409 if (sk_CONF_VALUE_num(list) == 0) { 410 TS_CONF_invalid(section, ENV_DIGESTS); 411 goto err; 412 } 413 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 414 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 415 const char *extval = val->value ? val->value : val->name; 416 const EVP_MD *md; 417 if (!(md = EVP_get_digestbyname(extval))) { 418 TS_CONF_invalid(section, ENV_DIGESTS); 419 goto err; 420 } 421 if (!TS_RESP_CTX_add_md(ctx, md)) 422 goto err; 423 } 424 425 ret = 1; 426 427 err: 428 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 429 return ret; 430 } 431 432 int 433 TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx) 434 { 435 int ret = 0; 436 int i; 437 int secs = 0, millis = 0, micros = 0; 438 STACK_OF(CONF_VALUE) *list = NULL; 439 char *accuracy = NCONF_get_string(conf, section, ENV_ACCURACY); 440 441 if (accuracy && !(list = X509V3_parse_list(accuracy))) { 442 TS_CONF_invalid(section, ENV_ACCURACY); 443 goto err; 444 } 445 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 446 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 447 if (strcmp(val->name, ENV_VALUE_SECS) == 0) { 448 if (val->value) 449 secs = atoi(val->value); 450 } else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0) { 451 if (val->value) 452 millis = atoi(val->value); 453 } else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0) { 454 if (val->value) 455 micros = atoi(val->value); 456 } else { 457 TS_CONF_invalid(section, ENV_ACCURACY); 458 goto err; 459 } 460 } 461 if (!TS_RESP_CTX_set_accuracy(ctx, secs, millis, micros)) 462 goto err; 463 464 ret = 1; 465 466 err: 467 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 468 return ret; 469 } 470 471 int 472 TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, 473 TS_RESP_CTX *ctx) 474 { 475 int ret = 0; 476 long digits = 0; 477 478 /* If not specified, set the default value to 0, i.e. sec precision */ 479 if (!NCONF_get_number_e(conf, section, ENV_CLOCK_PRECISION_DIGITS, 480 &digits)) 481 digits = 0; 482 if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS) { 483 TS_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS); 484 goto err; 485 } 486 487 if (!TS_RESP_CTX_set_clock_precision_digits(ctx, digits)) 488 goto err; 489 490 return 1; 491 492 err: 493 return ret; 494 } 495 496 static int 497 TS_CONF_add_flag(CONF *conf, const char *section, const char *field, int flag, 498 TS_RESP_CTX *ctx) 499 { 500 /* Default is false. */ 501 const char *value = NCONF_get_string(conf, section, field); 502 503 if (value) { 504 if (strcmp(value, ENV_VALUE_YES) == 0) 505 TS_RESP_CTX_add_flags(ctx, flag); 506 else if (strcmp(value, ENV_VALUE_NO) != 0) { 507 TS_CONF_invalid(section, field); 508 return 0; 509 } 510 } 511 512 return 1; 513 } 514 515 int 516 TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx) 517 { 518 return TS_CONF_add_flag(conf, section, ENV_ORDERING, TS_ORDERING, ctx); 519 } 520 521 int 522 TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx) 523 { 524 return TS_CONF_add_flag(conf, section, ENV_TSA_NAME, TS_TSA_NAME, ctx); 525 } 526 527 int 528 TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, TS_RESP_CTX *ctx) 529 { 530 return TS_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN, 531 TS_ESS_CERT_ID_CHAIN, ctx); 532 } 533