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