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