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