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