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