| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Here is a set of wrappers for the ENGINE API, which are no-ops when the | 
					
						
							|  |  |  |  * ENGINE API is disabled / removed. | 
					
						
							|  |  |  |  * We need to suppress deprecation warnings to make this work. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define OPENSSL_SUPPRESS_DEPRECATED
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-09 23:27:20 +08:00
										 |  |  | #include <string.h> /* strcmp */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  | #include <openssl/types.h> /* Ensure we have the ENGINE type, regardless */
 | 
					
						
							| 
									
										
										
										
											2020-11-02 19:04:06 +08:00
										 |  |  | #include <openssl/err.h>
 | 
					
						
							| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  | # include <openssl/engine.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #include "apps.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  | /* Try to load an engine in a shareable library */ | 
					
						
							|  |  |  | static ENGINE *try_load_engine(const char *engine) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ENGINE *e = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((e = ENGINE_by_id("dynamic")) != NULL) { | 
					
						
							|  |  |  |         if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) | 
					
						
							|  |  |  |             || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { | 
					
						
							|  |  |  |             ENGINE_free(e); | 
					
						
							|  |  |  |             e = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ENGINE *setup_engine_methods(const char *id, unsigned int methods, int debug) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ENGINE *e = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  |     if (id != NULL) { | 
					
						
							|  |  |  |         if (strcmp(id, "auto") == 0) { | 
					
						
							|  |  |  |             BIO_printf(bio_err, "Enabling auto ENGINE support\n"); | 
					
						
							|  |  |  |             ENGINE_register_all_complete(); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ((e = ENGINE_by_id(id)) == NULL | 
					
						
							|  |  |  |             && (e = try_load_engine(id)) == NULL) { | 
					
						
							|  |  |  |             BIO_printf(bio_err, "Invalid engine \"%s\"\n", id); | 
					
						
							|  |  |  |             ERR_print_errors(bio_err); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (debug) | 
					
						
							|  |  |  |             (void)ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); | 
					
						
							|  |  |  |         if (!ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, | 
					
						
							|  |  |  |                              (void *)get_ui_method(), 0, 1) | 
					
						
							|  |  |  |                 || !ENGINE_set_default(e, methods)) { | 
					
						
							|  |  |  |             BIO_printf(bio_err, "Cannot use engine \"%s\"\n", ENGINE_get_id(e)); | 
					
						
							|  |  |  |             ERR_print_errors(bio_err); | 
					
						
							|  |  |  |             ENGINE_free(e); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         BIO_printf(bio_err, "Engine \"%s\" set.\n", ENGINE_get_id(e)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void release_engine(ENGINE *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  |     /* Free our "structural" reference. */ | 
					
						
							|  |  |  |     ENGINE_free(e); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int init_engine(ENGINE *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int rv = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  |     rv = ENGINE_init(e); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return rv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int finish_engine(ENGINE *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int rv = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  |     rv = ENGINE_finish(e); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return rv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 14:25:46 +08:00
										 |  |  | char *make_engine_uri(ENGINE *e, const char *key_id, const char *desc) | 
					
						
							| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-30 14:25:46 +08:00
										 |  |  |     char *new_uri = NULL; | 
					
						
							| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							| 
									
										
										
										
											2020-11-30 14:25:46 +08:00
										 |  |  |     if (e == NULL) { | 
					
						
							|  |  |  |         BIO_printf(bio_err, "No engine specified for loading %s\n", desc); | 
					
						
							|  |  |  |     } else if (key_id == NULL) { | 
					
						
							|  |  |  |         BIO_printf(bio_err, "No engine key id specified for loading %s\n", desc); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         const char *engineid = ENGINE_get_id(e); | 
					
						
							|  |  |  |         size_t uri_sz = | 
					
						
							|  |  |  |             sizeof(ENGINE_SCHEME_COLON) - 1 | 
					
						
							|  |  |  |             + strlen(engineid) | 
					
						
							|  |  |  |             + 1 /* : */ | 
					
						
							|  |  |  |             + strlen(key_id) | 
					
						
							|  |  |  |             + 1 /* \0 */ | 
					
						
							|  |  |  |             ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new_uri = OPENSSL_malloc(uri_sz); | 
					
						
							|  |  |  |         if (new_uri != NULL) { | 
					
						
							|  |  |  |             OPENSSL_strlcpy(new_uri, ENGINE_SCHEME_COLON, uri_sz); | 
					
						
							|  |  |  |             OPENSSL_strlcat(new_uri, engineid, uri_sz); | 
					
						
							|  |  |  |             OPENSSL_strlcat(new_uri, ":", uri_sz); | 
					
						
							|  |  |  |             OPENSSL_strlcat(new_uri, key_id, uri_sz); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     BIO_printf(bio_err, "Engines not supported for loading %s\n", desc); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-11-30 14:25:46 +08:00
										 |  |  |     return new_uri; | 
					
						
							| 
									
										
										
										
											2020-10-01 00:01:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 19:04:06 +08:00
										 |  |  | int get_legacy_pkey_id(OSSL_LIB_CTX *libctx, const char *algname, ENGINE *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const EVP_PKEY_ASN1_METHOD *ameth; | 
					
						
							|  |  |  |     ENGINE *tmpeng = NULL; | 
					
						
							|  |  |  |     int pkey_id = NID_undef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ERR_set_mark(); | 
					
						
							|  |  |  |     ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(OPENSSL_NO_ENGINE)
 | 
					
						
							|  |  |  |     ENGINE_finish(tmpeng); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ameth == NULL && e != NULL) | 
					
						
							|  |  |  |         ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     /* We're only interested if it comes from an ENGINE */ | 
					
						
							|  |  |  |     if (tmpeng == NULL) | 
					
						
							|  |  |  |         ameth = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ERR_pop_to_mark(); | 
					
						
							|  |  |  |     if (ameth == NULL) | 
					
						
							|  |  |  |         return NID_undef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pkey_id; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-12-11 10:15:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const EVP_MD *get_digest_from_engine(const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  |     ENGINE *eng; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     eng = ENGINE_get_digest_engine(OBJ_sn2nid(name)); | 
					
						
							|  |  |  |     if (eng != NULL) { | 
					
						
							|  |  |  |         ENGINE_finish(eng); | 
					
						
							|  |  |  |         return EVP_get_digestbyname(name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const EVP_CIPHER *get_cipher_from_engine(const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef OPENSSL_NO_ENGINE
 | 
					
						
							|  |  |  |     ENGINE *eng; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     eng = ENGINE_get_cipher_engine(OBJ_sn2nid(name)); | 
					
						
							|  |  |  |     if (eng != NULL) { | 
					
						
							|  |  |  |         ENGINE_finish(eng); | 
					
						
							|  |  |  |         return EVP_get_cipherbyname(name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } |