Home | History | Annotate | Line # | Download | only in lib
      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