1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/* We need to use some engine deprecated APIs */
11e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED
12e1051a39Sopenharmony_ci
13e1051a39Sopenharmony_ci#include "eng_local.h"
14e1051a39Sopenharmony_ci#include <openssl/conf.h>
15e1051a39Sopenharmony_ci#include <openssl/trace.h>
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci/* ENGINE config module */
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_cistatic const char *skip_dot(const char *name)
20e1051a39Sopenharmony_ci{
21e1051a39Sopenharmony_ci    const char *p = strchr(name, '.');
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ci    if (p != NULL)
24e1051a39Sopenharmony_ci        return p + 1;
25e1051a39Sopenharmony_ci    return name;
26e1051a39Sopenharmony_ci}
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_cistatic STACK_OF(ENGINE) *initialized_engines = NULL;
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_cistatic int int_engine_init(ENGINE *e)
31e1051a39Sopenharmony_ci{
32e1051a39Sopenharmony_ci    if (!ENGINE_init(e))
33e1051a39Sopenharmony_ci        return 0;
34e1051a39Sopenharmony_ci    if (!initialized_engines)
35e1051a39Sopenharmony_ci        initialized_engines = sk_ENGINE_new_null();
36e1051a39Sopenharmony_ci    if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e)) {
37e1051a39Sopenharmony_ci        ENGINE_finish(e);
38e1051a39Sopenharmony_ci        return 0;
39e1051a39Sopenharmony_ci    }
40e1051a39Sopenharmony_ci    return 1;
41e1051a39Sopenharmony_ci}
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_cistatic int int_engine_configure(const char *name, const char *value, const CONF *cnf)
44e1051a39Sopenharmony_ci{
45e1051a39Sopenharmony_ci    int i;
46e1051a39Sopenharmony_ci    int ret = 0;
47e1051a39Sopenharmony_ci    long do_init = -1;
48e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *ecmds;
49e1051a39Sopenharmony_ci    CONF_VALUE *ecmd = NULL;
50e1051a39Sopenharmony_ci    const char *ctrlname, *ctrlvalue;
51e1051a39Sopenharmony_ci    ENGINE *e = NULL;
52e1051a39Sopenharmony_ci    int soft = 0;
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_ci    name = skip_dot(name);
55e1051a39Sopenharmony_ci    OSSL_TRACE1(CONF, "Configuring engine %s\n", name);
56e1051a39Sopenharmony_ci    /* Value is a section containing ENGINE commands */
57e1051a39Sopenharmony_ci    ecmds = NCONF_get_section(cnf, value);
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci    if (!ecmds) {
60e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_SECTION_ERROR);
61e1051a39Sopenharmony_ci        return 0;
62e1051a39Sopenharmony_ci    }
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) {
65e1051a39Sopenharmony_ci        ecmd = sk_CONF_VALUE_value(ecmds, i);
66e1051a39Sopenharmony_ci        ctrlname = skip_dot(ecmd->name);
67e1051a39Sopenharmony_ci        ctrlvalue = ecmd->value;
68e1051a39Sopenharmony_ci        OSSL_TRACE2(CONF, "ENGINE: doing ctrl(%s,%s)\n",
69e1051a39Sopenharmony_ci                    ctrlname, ctrlvalue);
70e1051a39Sopenharmony_ci
71e1051a39Sopenharmony_ci        /* First handle some special pseudo ctrls */
72e1051a39Sopenharmony_ci
73e1051a39Sopenharmony_ci        /* Override engine name to use */
74e1051a39Sopenharmony_ci        if (strcmp(ctrlname, "engine_id") == 0)
75e1051a39Sopenharmony_ci            name = ctrlvalue;
76e1051a39Sopenharmony_ci        else if (strcmp(ctrlname, "soft_load") == 0)
77e1051a39Sopenharmony_ci            soft = 1;
78e1051a39Sopenharmony_ci        /* Load a dynamic ENGINE */
79e1051a39Sopenharmony_ci        else if (strcmp(ctrlname, "dynamic_path") == 0) {
80e1051a39Sopenharmony_ci            e = ENGINE_by_id("dynamic");
81e1051a39Sopenharmony_ci            if (!e)
82e1051a39Sopenharmony_ci                goto err;
83e1051a39Sopenharmony_ci            if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
84e1051a39Sopenharmony_ci                goto err;
85e1051a39Sopenharmony_ci            if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
86e1051a39Sopenharmony_ci                goto err;
87e1051a39Sopenharmony_ci            if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
88e1051a39Sopenharmony_ci                goto err;
89e1051a39Sopenharmony_ci        }
90e1051a39Sopenharmony_ci        /* ... add other pseudos here ... */
91e1051a39Sopenharmony_ci        else {
92e1051a39Sopenharmony_ci            /*
93e1051a39Sopenharmony_ci             * At this point we need an ENGINE structural reference if we
94e1051a39Sopenharmony_ci             * don't already have one.
95e1051a39Sopenharmony_ci             */
96e1051a39Sopenharmony_ci            if (!e) {
97e1051a39Sopenharmony_ci                e = ENGINE_by_id(name);
98e1051a39Sopenharmony_ci                if (!e && soft) {
99e1051a39Sopenharmony_ci                    ERR_clear_error();
100e1051a39Sopenharmony_ci                    return 1;
101e1051a39Sopenharmony_ci                }
102e1051a39Sopenharmony_ci                if (!e)
103e1051a39Sopenharmony_ci                    goto err;
104e1051a39Sopenharmony_ci            }
105e1051a39Sopenharmony_ci            /*
106e1051a39Sopenharmony_ci             * Allow "EMPTY" to mean no value: this allows a valid "value" to
107e1051a39Sopenharmony_ci             * be passed to ctrls of type NO_INPUT
108e1051a39Sopenharmony_ci             */
109e1051a39Sopenharmony_ci            if (strcmp(ctrlvalue, "EMPTY") == 0)
110e1051a39Sopenharmony_ci                ctrlvalue = NULL;
111e1051a39Sopenharmony_ci            if (strcmp(ctrlname, "init") == 0) {
112e1051a39Sopenharmony_ci                if (!NCONF_get_number_e(cnf, value, "init", &do_init))
113e1051a39Sopenharmony_ci                    goto err;
114e1051a39Sopenharmony_ci                if (do_init == 1) {
115e1051a39Sopenharmony_ci                    if (!int_engine_init(e))
116e1051a39Sopenharmony_ci                        goto err;
117e1051a39Sopenharmony_ci                } else if (do_init != 0) {
118e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INVALID_INIT_VALUE);
119e1051a39Sopenharmony_ci                    goto err;
120e1051a39Sopenharmony_ci                }
121e1051a39Sopenharmony_ci            } else if (strcmp(ctrlname, "default_algorithms") == 0) {
122e1051a39Sopenharmony_ci                if (!ENGINE_set_default_string(e, ctrlvalue))
123e1051a39Sopenharmony_ci                    goto err;
124e1051a39Sopenharmony_ci            } else if (!ENGINE_ctrl_cmd_string(e, ctrlname, ctrlvalue, 0))
125e1051a39Sopenharmony_ci                goto err;
126e1051a39Sopenharmony_ci        }
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ci    }
129e1051a39Sopenharmony_ci    if (e && (do_init == -1) && !int_engine_init(e)) {
130e1051a39Sopenharmony_ci        ecmd = NULL;
131e1051a39Sopenharmony_ci        goto err;
132e1051a39Sopenharmony_ci    }
133e1051a39Sopenharmony_ci    ret = 1;
134e1051a39Sopenharmony_ci err:
135e1051a39Sopenharmony_ci    if (ret != 1) {
136e1051a39Sopenharmony_ci        if (ecmd == NULL)
137e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_CONFIGURATION_ERROR);
138e1051a39Sopenharmony_ci        else
139e1051a39Sopenharmony_ci            ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_ENGINE_CONFIGURATION_ERROR,
140e1051a39Sopenharmony_ci                           "section=%s, name=%s, value=%s",
141e1051a39Sopenharmony_ci                           ecmd->section, ecmd->name, ecmd->value);
142e1051a39Sopenharmony_ci    }
143e1051a39Sopenharmony_ci    ENGINE_free(e);
144e1051a39Sopenharmony_ci    return ret;
145e1051a39Sopenharmony_ci}
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_cistatic int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
148e1051a39Sopenharmony_ci{
149e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *elist;
150e1051a39Sopenharmony_ci    CONF_VALUE *cval;
151e1051a39Sopenharmony_ci    int i;
152e1051a39Sopenharmony_ci    OSSL_TRACE2(CONF, "Called engine module: name %s, value %s\n",
153e1051a39Sopenharmony_ci                CONF_imodule_get_name(md), CONF_imodule_get_value(md));
154e1051a39Sopenharmony_ci    /* Value is a section containing ENGINEs to configure */
155e1051a39Sopenharmony_ci    elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci    if (!elist) {
158e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINES_SECTION_ERROR);
159e1051a39Sopenharmony_ci        return 0;
160e1051a39Sopenharmony_ci    }
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
163e1051a39Sopenharmony_ci        cval = sk_CONF_VALUE_value(elist, i);
164e1051a39Sopenharmony_ci        if (!int_engine_configure(cval->name, cval->value, cnf))
165e1051a39Sopenharmony_ci            return 0;
166e1051a39Sopenharmony_ci    }
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ci    return 1;
169e1051a39Sopenharmony_ci}
170e1051a39Sopenharmony_ci
171e1051a39Sopenharmony_cistatic void int_engine_module_finish(CONF_IMODULE *md)
172e1051a39Sopenharmony_ci{
173e1051a39Sopenharmony_ci    ENGINE *e;
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci    while ((e = sk_ENGINE_pop(initialized_engines)))
176e1051a39Sopenharmony_ci        ENGINE_finish(e);
177e1051a39Sopenharmony_ci    sk_ENGINE_free(initialized_engines);
178e1051a39Sopenharmony_ci    initialized_engines = NULL;
179e1051a39Sopenharmony_ci}
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_civoid ENGINE_add_conf_module(void)
182e1051a39Sopenharmony_ci{
183e1051a39Sopenharmony_ci    CONF_module_add("engines",
184e1051a39Sopenharmony_ci                    int_engine_module_init, int_engine_module_finish);
185e1051a39Sopenharmony_ci}
186