ts_conf.c revision 296341
1/* crypto/ts/ts_conf.c */ 2/* 3 * Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL project 4 * 2002. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <string.h> 61 62#include <openssl/crypto.h> 63#include "cryptlib.h" 64#include <openssl/pem.h> 65#ifndef OPENSSL_NO_ENGINE 66# include <openssl/engine.h> 67#endif 68#include <openssl/ts.h> 69 70/* Macro definitions for the configuration file. */ 71 72#define BASE_SECTION "tsa" 73#define ENV_DEFAULT_TSA "default_tsa" 74#define ENV_SERIAL "serial" 75#define ENV_CRYPTO_DEVICE "crypto_device" 76#define ENV_SIGNER_CERT "signer_cert" 77#define ENV_CERTS "certs" 78#define ENV_SIGNER_KEY "signer_key" 79#define ENV_DEFAULT_POLICY "default_policy" 80#define ENV_OTHER_POLICIES "other_policies" 81#define ENV_DIGESTS "digests" 82#define ENV_ACCURACY "accuracy" 83#define ENV_ORDERING "ordering" 84#define ENV_TSA_NAME "tsa_name" 85#define ENV_ESS_CERT_ID_CHAIN "ess_cert_id_chain" 86#define ENV_VALUE_SECS "secs" 87#define ENV_VALUE_MILLISECS "millisecs" 88#define ENV_VALUE_MICROSECS "microsecs" 89#define ENV_CLOCK_PRECISION_DIGITS "clock_precision_digits" 90#define ENV_VALUE_YES "yes" 91#define ENV_VALUE_NO "no" 92 93/* Function definitions for certificate and key loading. */ 94 95X509 *TS_CONF_load_cert(const char *file) 96{ 97 BIO *cert = NULL; 98 X509 *x = NULL; 99 100 if ((cert = BIO_new_file(file, "r")) == NULL) 101 goto end; 102 x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); 103 end: 104 if (x == NULL) 105 fprintf(stderr, "unable to load certificate: %s\n", file); 106 BIO_free(cert); 107 return x; 108} 109 110STACK_OF(X509) *TS_CONF_load_certs(const char *file) 111{ 112 BIO *certs = NULL; 113 STACK_OF(X509) *othercerts = NULL; 114 STACK_OF(X509_INFO) *allcerts = NULL; 115 int i; 116 117 if (!(certs = BIO_new_file(file, "r"))) 118 goto end; 119 120 if (!(othercerts = sk_X509_new_null())) 121 goto end; 122 allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL); 123 for (i = 0; i < sk_X509_INFO_num(allcerts); i++) { 124 X509_INFO *xi = sk_X509_INFO_value(allcerts, i); 125 if (xi->x509) { 126 sk_X509_push(othercerts, xi->x509); 127 xi->x509 = NULL; 128 } 129 } 130 end: 131 if (othercerts == NULL) 132 fprintf(stderr, "unable to load certificates: %s\n", file); 133 sk_X509_INFO_pop_free(allcerts, X509_INFO_free); 134 BIO_free(certs); 135 return othercerts; 136} 137 138EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass) 139{ 140 BIO *key = NULL; 141 EVP_PKEY *pkey = NULL; 142 143 if (!(key = BIO_new_file(file, "r"))) 144 goto end; 145 pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *)pass); 146 end: 147 if (pkey == NULL) 148 fprintf(stderr, "unable to load private key: %s\n", file); 149 BIO_free(key); 150 return pkey; 151} 152 153/* Function definitions for handling configuration options. */ 154 155static void TS_CONF_lookup_fail(const char *name, const char *tag) 156{ 157 fprintf(stderr, "variable lookup failed for %s::%s\n", name, tag); 158} 159 160static void TS_CONF_invalid(const char *name, const char *tag) 161{ 162 fprintf(stderr, "invalid variable value for %s::%s\n", name, tag); 163} 164 165const char *TS_CONF_get_tsa_section(CONF *conf, const char *section) 166{ 167 if (!section) { 168 section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_TSA); 169 if (!section) 170 TS_CONF_lookup_fail(BASE_SECTION, ENV_DEFAULT_TSA); 171 } 172 return section; 173} 174 175int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, 176 TS_RESP_CTX *ctx) 177{ 178 int ret = 0; 179 char *serial = NCONF_get_string(conf, section, ENV_SERIAL); 180 if (!serial) { 181 TS_CONF_lookup_fail(section, ENV_SERIAL); 182 goto err; 183 } 184 TS_RESP_CTX_set_serial_cb(ctx, cb, serial); 185 186 ret = 1; 187 err: 188 return ret; 189} 190 191#ifndef OPENSSL_NO_ENGINE 192 193int TS_CONF_set_crypto_device(CONF *conf, const char *section, 194 const char *device) 195{ 196 int ret = 0; 197 198 if (!device) 199 device = NCONF_get_string(conf, section, ENV_CRYPTO_DEVICE); 200 201 if (device && !TS_CONF_set_default_engine(device)) { 202 TS_CONF_invalid(section, ENV_CRYPTO_DEVICE); 203 goto err; 204 } 205 ret = 1; 206 err: 207 return ret; 208} 209 210int TS_CONF_set_default_engine(const char *name) 211{ 212 ENGINE *e = NULL; 213 int ret = 0; 214 215 /* Leave the default if builtin specified. */ 216 if (strcmp(name, "builtin") == 0) 217 return 1; 218 219 if (!(e = ENGINE_by_id(name))) 220 goto err; 221 /* Enable the use of the NCipher HSM for forked children. */ 222 if (strcmp(name, "chil") == 0) 223 ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0); 224 /* All the operations are going to be carried out by the engine. */ 225 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) 226 goto err; 227 ret = 1; 228 err: 229 if (!ret) { 230 TSerr(TS_F_TS_CONF_SET_DEFAULT_ENGINE, TS_R_COULD_NOT_SET_ENGINE); 231 ERR_add_error_data(2, "engine:", name); 232 } 233 if (e) 234 ENGINE_free(e); 235 return ret; 236} 237 238#endif 239 240int TS_CONF_set_signer_cert(CONF *conf, const char *section, 241 const char *cert, TS_RESP_CTX *ctx) 242{ 243 int ret = 0; 244 X509 *cert_obj = NULL; 245 if (!cert) 246 cert = NCONF_get_string(conf, section, ENV_SIGNER_CERT); 247 if (!cert) { 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 262int 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) 271 goto end; 272 if (!(certs_obj = TS_CONF_load_certs(certs))) 273 goto err; 274 if (!TS_RESP_CTX_set_certs(ctx, certs_obj)) 275 goto err; 276 end: 277 ret = 1; 278 err: 279 sk_X509_pop_free(certs_obj, X509_free); 280 return ret; 281} 282 283int TS_CONF_set_signer_key(CONF *conf, const char *section, 284 const char *key, const char *pass, 285 TS_RESP_CTX *ctx) 286{ 287 int ret = 0; 288 EVP_PKEY *key_obj = NULL; 289 if (!key) 290 key = NCONF_get_string(conf, section, ENV_SIGNER_KEY); 291 if (!key) { 292 TS_CONF_lookup_fail(section, ENV_SIGNER_KEY); 293 goto err; 294 } 295 if (!(key_obj = TS_CONF_load_key(key, pass))) 296 goto err; 297 if (!TS_RESP_CTX_set_signer_key(ctx, key_obj)) 298 goto err; 299 300 ret = 1; 301 err: 302 EVP_PKEY_free(key_obj); 303 return ret; 304} 305 306int TS_CONF_set_def_policy(CONF *conf, const char *section, 307 const char *policy, TS_RESP_CTX *ctx) 308{ 309 int ret = 0; 310 ASN1_OBJECT *policy_obj = NULL; 311 if (!policy) 312 policy = NCONF_get_string(conf, section, ENV_DEFAULT_POLICY); 313 if (!policy) { 314 TS_CONF_lookup_fail(section, ENV_DEFAULT_POLICY); 315 goto err; 316 } 317 if (!(policy_obj = OBJ_txt2obj(policy, 0))) { 318 TS_CONF_invalid(section, ENV_DEFAULT_POLICY); 319 goto err; 320 } 321 if (!TS_RESP_CTX_set_def_policy(ctx, policy_obj)) 322 goto err; 323 324 ret = 1; 325 err: 326 ASN1_OBJECT_free(policy_obj); 327 return ret; 328} 329 330int TS_CONF_set_policies(CONF *conf, const char *section, 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 TS_CONF_invalid(section, ENV_OTHER_POLICIES); 340 goto err; 341 } 342 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 343 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 344 const char *extval = val->value ? val->value : val->name; 345 ASN1_OBJECT *objtmp; 346 if (!(objtmp = OBJ_txt2obj(extval, 0))) { 347 TS_CONF_invalid(section, ENV_OTHER_POLICIES); 348 goto err; 349 } 350 if (!TS_RESP_CTX_add_policy(ctx, objtmp)) 351 goto err; 352 ASN1_OBJECT_free(objtmp); 353 } 354 355 ret = 1; 356 err: 357 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 358 return ret; 359} 360 361int TS_CONF_set_digests(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 *digests = NCONF_get_string(conf, section, ENV_DIGESTS); 367 if (!digests) { 368 TS_CONF_lookup_fail(section, ENV_DIGESTS); 369 goto err; 370 } 371 if (!(list = X509V3_parse_list(digests))) { 372 TS_CONF_invalid(section, ENV_DIGESTS); 373 goto err; 374 } 375 if (sk_CONF_VALUE_num(list) == 0) { 376 TS_CONF_invalid(section, ENV_DIGESTS); 377 goto err; 378 } 379 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 380 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 381 const char *extval = val->value ? val->value : val->name; 382 const EVP_MD *md; 383 if (!(md = EVP_get_digestbyname(extval))) { 384 TS_CONF_invalid(section, ENV_DIGESTS); 385 goto err; 386 } 387 if (!TS_RESP_CTX_add_md(ctx, md)) 388 goto err; 389 } 390 391 ret = 1; 392 err: 393 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 394 return ret; 395} 396 397int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx) 398{ 399 int ret = 0; 400 int i; 401 int secs = 0, millis = 0, micros = 0; 402 STACK_OF(CONF_VALUE) *list = NULL; 403 char *accuracy = NCONF_get_string(conf, section, ENV_ACCURACY); 404 405 if (accuracy && !(list = X509V3_parse_list(accuracy))) { 406 TS_CONF_invalid(section, ENV_ACCURACY); 407 goto err; 408 } 409 for (i = 0; i < sk_CONF_VALUE_num(list); ++i) { 410 CONF_VALUE *val = sk_CONF_VALUE_value(list, i); 411 if (strcmp(val->name, ENV_VALUE_SECS) == 0) { 412 if (val->value) 413 secs = atoi(val->value); 414 } else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0) { 415 if (val->value) 416 millis = atoi(val->value); 417 } else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0) { 418 if (val->value) 419 micros = atoi(val->value); 420 } else { 421 TS_CONF_invalid(section, ENV_ACCURACY); 422 goto err; 423 } 424 } 425 if (!TS_RESP_CTX_set_accuracy(ctx, secs, millis, micros)) 426 goto err; 427 428 ret = 1; 429 err: 430 sk_CONF_VALUE_pop_free(list, X509V3_conf_free); 431 return ret; 432} 433 434int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, 435 TS_RESP_CTX *ctx) 436{ 437 int ret = 0; 438 long digits = 0; 439 440 /* 441 * If not specified, set the default value to 0, i.e. sec precision 442 */ 443 if (!NCONF_get_number_e(conf, section, ENV_CLOCK_PRECISION_DIGITS, 444 &digits)) 445 digits = 0; 446 if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS) { 447 TS_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS); 448 goto err; 449 } 450 451 if (!TS_RESP_CTX_set_clock_precision_digits(ctx, digits)) 452 goto err; 453 454 return 1; 455 err: 456 return ret; 457} 458 459static int TS_CONF_add_flag(CONF *conf, const char *section, 460 const char *field, int flag, TS_RESP_CTX *ctx) 461{ 462 /* Default is false. */ 463 const char *value = NCONF_get_string(conf, section, field); 464 if (value) { 465 if (strcmp(value, ENV_VALUE_YES) == 0) 466 TS_RESP_CTX_add_flags(ctx, flag); 467 else if (strcmp(value, ENV_VALUE_NO) != 0) { 468 TS_CONF_invalid(section, field); 469 return 0; 470 } 471 } 472 473 return 1; 474} 475 476int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx) 477{ 478 return TS_CONF_add_flag(conf, section, ENV_ORDERING, TS_ORDERING, ctx); 479} 480 481int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx) 482{ 483 return TS_CONF_add_flag(conf, section, ENV_TSA_NAME, TS_TSA_NAME, ctx); 484} 485 486int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, 487 TS_RESP_CTX *ctx) 488{ 489 return TS_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN, 490 TS_ESS_CERT_ID_CHAIN, ctx); 491} 492