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         }