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