1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 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/*
11e1051a39Sopenharmony_ci * Here is a set of wrappers for the ENGINE API, which are no-ops when the
12e1051a39Sopenharmony_ci * ENGINE API is disabled / removed.
13e1051a39Sopenharmony_ci * We need to suppress deprecation warnings to make this work.
14e1051a39Sopenharmony_ci */
15e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include <string.h> /* strcmp */
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci#include <openssl/types.h> /* Ensure we have the ENGINE type, regardless */
20e1051a39Sopenharmony_ci#include <openssl/err.h>
21e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
22e1051a39Sopenharmony_ci# include <openssl/engine.h>
23e1051a39Sopenharmony_ci#endif
24e1051a39Sopenharmony_ci#include "apps.h"
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
27e1051a39Sopenharmony_ci/* Try to load an engine in a shareable library */
28e1051a39Sopenharmony_cistatic ENGINE *try_load_engine(const char *engine)
29e1051a39Sopenharmony_ci{
30e1051a39Sopenharmony_ci    ENGINE *e = NULL;
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_ci    if ((e = ENGINE_by_id("dynamic")) != NULL) {
33e1051a39Sopenharmony_ci        if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
34e1051a39Sopenharmony_ci            || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
35e1051a39Sopenharmony_ci            ENGINE_free(e);
36e1051a39Sopenharmony_ci            e = NULL;
37e1051a39Sopenharmony_ci        }
38e1051a39Sopenharmony_ci    }
39e1051a39Sopenharmony_ci    return e;
40e1051a39Sopenharmony_ci}
41e1051a39Sopenharmony_ci#endif
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_ciENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug)
44e1051a39Sopenharmony_ci{
45e1051a39Sopenharmony_ci    ENGINE *e = NULL;
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
48e1051a39Sopenharmony_ci    if (id != NULL) {
49e1051a39Sopenharmony_ci        if (strcmp(id, "auto") == 0) {
50e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Enabling auto ENGINE support\n");
51e1051a39Sopenharmony_ci            ENGINE_register_all_complete();
52e1051a39Sopenharmony_ci            return NULL;
53e1051a39Sopenharmony_ci        }
54e1051a39Sopenharmony_ci        if ((e = ENGINE_by_id(id)) == NULL
55e1051a39Sopenharmony_ci            && (e = try_load_engine(id)) == NULL) {
56e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Invalid engine \"%s\"\n", id);
57e1051a39Sopenharmony_ci            ERR_print_errors(bio_err);
58e1051a39Sopenharmony_ci            return NULL;
59e1051a39Sopenharmony_ci        }
60e1051a39Sopenharmony_ci        if (debug)
61e1051a39Sopenharmony_ci            (void)ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0);
62e1051a39Sopenharmony_ci        if (!ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0,
63e1051a39Sopenharmony_ci                             (void *)get_ui_method(), 0, 1)
64e1051a39Sopenharmony_ci                || !ENGINE_set_default(e, methods)) {
65e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Cannot use engine \"%s\"\n", ENGINE_get_id(e));
66e1051a39Sopenharmony_ci            ERR_print_errors(bio_err);
67e1051a39Sopenharmony_ci            ENGINE_free(e);
68e1051a39Sopenharmony_ci            return NULL;
69e1051a39Sopenharmony_ci        }
70e1051a39Sopenharmony_ci
71e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Engine \"%s\" set.\n", ENGINE_get_id(e));
72e1051a39Sopenharmony_ci    }
73e1051a39Sopenharmony_ci#endif
74e1051a39Sopenharmony_ci    return e;
75e1051a39Sopenharmony_ci}
76e1051a39Sopenharmony_ci
77e1051a39Sopenharmony_civoid release_engine(ENGINE *e)
78e1051a39Sopenharmony_ci{
79e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
80e1051a39Sopenharmony_ci    /* Free our "structural" reference. */
81e1051a39Sopenharmony_ci    ENGINE_free(e);
82e1051a39Sopenharmony_ci#endif
83e1051a39Sopenharmony_ci}
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ciint init_engine(ENGINE *e)
86e1051a39Sopenharmony_ci{
87e1051a39Sopenharmony_ci    int rv = 1;
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
90e1051a39Sopenharmony_ci    rv = ENGINE_init(e);
91e1051a39Sopenharmony_ci#endif
92e1051a39Sopenharmony_ci    return rv;
93e1051a39Sopenharmony_ci}
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ciint finish_engine(ENGINE *e)
96e1051a39Sopenharmony_ci{
97e1051a39Sopenharmony_ci    int rv = 1;
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
100e1051a39Sopenharmony_ci    rv = ENGINE_finish(e);
101e1051a39Sopenharmony_ci#endif
102e1051a39Sopenharmony_ci    return rv;
103e1051a39Sopenharmony_ci}
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_cichar *make_engine_uri(ENGINE *e, const char *key_id, const char *desc)
106e1051a39Sopenharmony_ci{
107e1051a39Sopenharmony_ci    char *new_uri = NULL;
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
110e1051a39Sopenharmony_ci    if (e == NULL) {
111e1051a39Sopenharmony_ci        BIO_printf(bio_err, "No engine specified for loading %s\n", desc);
112e1051a39Sopenharmony_ci    } else if (key_id == NULL) {
113e1051a39Sopenharmony_ci        BIO_printf(bio_err, "No engine key id specified for loading %s\n", desc);
114e1051a39Sopenharmony_ci    } else {
115e1051a39Sopenharmony_ci        const char *engineid = ENGINE_get_id(e);
116e1051a39Sopenharmony_ci        size_t uri_sz =
117e1051a39Sopenharmony_ci            sizeof(ENGINE_SCHEME_COLON) - 1
118e1051a39Sopenharmony_ci            + strlen(engineid)
119e1051a39Sopenharmony_ci            + 1 /* : */
120e1051a39Sopenharmony_ci            + strlen(key_id)
121e1051a39Sopenharmony_ci            + 1 /* \0 */
122e1051a39Sopenharmony_ci            ;
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ci        new_uri = OPENSSL_malloc(uri_sz);
125e1051a39Sopenharmony_ci        if (new_uri != NULL) {
126e1051a39Sopenharmony_ci            OPENSSL_strlcpy(new_uri, ENGINE_SCHEME_COLON, uri_sz);
127e1051a39Sopenharmony_ci            OPENSSL_strlcat(new_uri, engineid, uri_sz);
128e1051a39Sopenharmony_ci            OPENSSL_strlcat(new_uri, ":", uri_sz);
129e1051a39Sopenharmony_ci            OPENSSL_strlcat(new_uri, key_id, uri_sz);
130e1051a39Sopenharmony_ci        }
131e1051a39Sopenharmony_ci    }
132e1051a39Sopenharmony_ci#else
133e1051a39Sopenharmony_ci    BIO_printf(bio_err, "Engines not supported for loading %s\n", desc);
134e1051a39Sopenharmony_ci#endif
135e1051a39Sopenharmony_ci    return new_uri;
136e1051a39Sopenharmony_ci}
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ciint get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e)
139e1051a39Sopenharmony_ci{
140e1051a39Sopenharmony_ci    const EVP_PKEY_ASN1_METHOD *ameth;
141e1051a39Sopenharmony_ci    ENGINE *tmpeng = NULL;
142e1051a39Sopenharmony_ci    int pkey_id = NID_undef;
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci    ERR_set_mark();
145e1051a39Sopenharmony_ci    ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE)
148e1051a39Sopenharmony_ci    ENGINE_finish(tmpeng);
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci    if (ameth == NULL && e != NULL)
151e1051a39Sopenharmony_ci        ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
152e1051a39Sopenharmony_ci    else
153e1051a39Sopenharmony_ci#endif
154e1051a39Sopenharmony_ci    /* We're only interested if it comes from an ENGINE */
155e1051a39Sopenharmony_ci    if (tmpeng == NULL)
156e1051a39Sopenharmony_ci        ameth = NULL;
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_ci    ERR_pop_to_mark();
159e1051a39Sopenharmony_ci    if (ameth == NULL)
160e1051a39Sopenharmony_ci        return NID_undef;
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ci    EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci    return pkey_id;
165e1051a39Sopenharmony_ci}
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ciconst EVP_MD *get_digest_from_engine(const char *name)
168e1051a39Sopenharmony_ci{
169e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
170e1051a39Sopenharmony_ci    ENGINE *eng;
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci    eng = ENGINE_get_digest_engine(OBJ_sn2nid(name));
173e1051a39Sopenharmony_ci    if (eng != NULL) {
174e1051a39Sopenharmony_ci        ENGINE_finish(eng);
175e1051a39Sopenharmony_ci        return EVP_get_digestbyname(name);
176e1051a39Sopenharmony_ci    }
177e1051a39Sopenharmony_ci#endif
178e1051a39Sopenharmony_ci    return NULL;
179e1051a39Sopenharmony_ci}
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_ciconst EVP_CIPHER *get_cipher_from_engine(const char *name)
182e1051a39Sopenharmony_ci{
183e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
184e1051a39Sopenharmony_ci    ENGINE *eng;
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci    eng = ENGINE_get_cipher_engine(OBJ_sn2nid(name));
187e1051a39Sopenharmony_ci    if (eng != NULL) {
188e1051a39Sopenharmony_ci        ENGINE_finish(eng);
189e1051a39Sopenharmony_ci        return EVP_get_cipherbyname(name);
190e1051a39Sopenharmony_ci    }
191e1051a39Sopenharmony_ci#endif
192e1051a39Sopenharmony_ci    return NULL;
193e1051a39Sopenharmony_ci}
194