Home | History | Annotate | Line # | Download | only in lib
      1 /*
      2  * Copyright 2018-2022 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 an STORE loader for ENGINE backed keys.  It relies on deprecated
     12  * functions, and therefore need to have deprecation warnings suppressed.
     13  * This file is not compiled at all in a '--api=3 no-deprecated' configuration.
     14  */
     15 #define OPENSSL_SUPPRESS_DEPRECATED
     16 
     17 #include "internal/e_os.h"
     18 #include "apps.h"
     19 
     20 #ifndef OPENSSL_NO_ENGINE
     21 
     22 #include <stdarg.h>
     23 #include <string.h>
     24 #include <openssl/engine.h>
     25 #include <openssl/store.h>
     26 
     27 /*
     28  * Support for legacy private engine keys via the 'org.openssl.engine:' scheme
     29  *
     30  * org.openssl.engine:{engineid}:{keyid}
     31  *
     32  * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()
     33  * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly
     34  * this sort of purpose.
     35  */
     36 
     37 /* Local definition of OSSL_STORE_LOADER_CTX */
     38 struct ossl_store_loader_ctx_st {
     39     ENGINE *e; /* Structural reference */
     40     char *keyid;
     41     int expected;
     42     int loaded; /* 0 = key not loaded yet, 1 = key loaded */
     43 };
     44 
     45 static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)
     46 {
     47     OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
     48 
     49     if (ctx != NULL) {
     50         ctx->e = e;
     51         ctx->keyid = keyid;
     52     }
     53     return ctx;
     54 }
     55 
     56 static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
     57 {
     58     if (ctx != NULL) {
     59         ENGINE_free(ctx->e);
     60         OPENSSL_free(ctx->keyid);
     61         OPENSSL_free(ctx);
     62     }
     63 }
     64 
     65 static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
     66     const char *uri,
     67     const UI_METHOD *ui_method,
     68     void *ui_data)
     69 {
     70     const char *p = uri, *q;
     71     ENGINE *e = NULL;
     72     char *keyid = NULL;
     73     OSSL_STORE_LOADER_CTX *ctx = NULL;
     74 
     75     if (!CHECK_AND_SKIP_CASE_PREFIX(p, ENGINE_SCHEME_COLON))
     76         return NULL;
     77 
     78     /* Look for engine ID */
     79     q = strchr(p, ':');
     80     if (q != NULL /* There is both an engine ID and a key ID */
     81         && p[0] != ':' /* The engine ID is at least one character */
     82         && q[1] != '\0') { /* The key ID is at least one character */
     83         char engineid[256];
     84         size_t engineid_l = q - p;
     85 
     86         strncpy(engineid, p, engineid_l);
     87         engineid[engineid_l] = '\0';
     88         e = ENGINE_by_id(engineid);
     89 
     90         keyid = OPENSSL_strdup(q + 1);
     91     }
     92 
     93     if (e != NULL && keyid != NULL)
     94         ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);
     95 
     96     if (ctx == NULL) {
     97         OPENSSL_free(keyid);
     98         ENGINE_free(e);
     99     }
    100 
    101     return ctx;
    102 }
    103 
    104 static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
    105 {
    106     if (expected == 0
    107         || expected == OSSL_STORE_INFO_PUBKEY
    108         || expected == OSSL_STORE_INFO_PKEY) {
    109         ctx->expected = expected;
    110         return 1;
    111     }
    112     return 0;
    113 }
    114 
    115 static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,
    116     const UI_METHOD *ui_method, void *ui_data)
    117 {
    118     EVP_PKEY *pkey = NULL, *pubkey = NULL;
    119     OSSL_STORE_INFO *info = NULL;
    120 
    121     if (ctx->loaded == 0) {
    122         if (ENGINE_init(ctx->e)) {
    123             if (ctx->expected == 0
    124                 || ctx->expected == OSSL_STORE_INFO_PKEY)
    125                 pkey = ENGINE_load_private_key(ctx->e, ctx->keyid,
    126                     (UI_METHOD *)ui_method, ui_data);
    127             if ((pkey == NULL && ctx->expected == 0)
    128                 || ctx->expected == OSSL_STORE_INFO_PUBKEY)
    129                 pubkey = ENGINE_load_public_key(ctx->e, ctx->keyid,
    130                     (UI_METHOD *)ui_method, ui_data);
    131             ENGINE_finish(ctx->e);
    132         }
    133     }
    134 
    135     ctx->loaded = 1;
    136 
    137     if (pubkey != NULL)
    138         info = OSSL_STORE_INFO_new_PUBKEY(pubkey);
    139     else if (pkey != NULL)
    140         info = OSSL_STORE_INFO_new_PKEY(pkey);
    141     if (info == NULL) {
    142         EVP_PKEY_free(pkey);
    143         EVP_PKEY_free(pubkey);
    144     }
    145     return info;
    146 }
    147 
    148 static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)
    149 {
    150     return ctx->loaded != 0;
    151 }
    152 
    153 static int engine_error(OSSL_STORE_LOADER_CTX *ctx)
    154 {
    155     return 0;
    156 }
    157 
    158 static int engine_close(OSSL_STORE_LOADER_CTX *ctx)
    159 {
    160     OSSL_STORE_LOADER_CTX_free(ctx);
    161     return 1;
    162 }
    163 
    164 int setup_engine_loader(void)
    165 {
    166     OSSL_STORE_LOADER *loader = NULL;
    167 
    168     if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL
    169         || !OSSL_STORE_LOADER_set_open(loader, engine_open)
    170         || !OSSL_STORE_LOADER_set_expect(loader, engine_expect)
    171         || !OSSL_STORE_LOADER_set_load(loader, engine_load)
    172         || !OSSL_STORE_LOADER_set_eof(loader, engine_eof)
    173         || !OSSL_STORE_LOADER_set_error(loader, engine_error)
    174         || !OSSL_STORE_LOADER_set_close(loader, engine_close)
    175         || !OSSL_STORE_register_loader(loader)) {
    176         OSSL_STORE_LOADER_free(loader);
    177         loader = NULL;
    178     }
    179 
    180     return loader != NULL;
    181 }
    182 
    183 void destroy_engine_loader(void)
    184 {
    185     OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);
    186     OSSL_STORE_LOADER_free(loader);
    187 }
    188 
    189 #else /* !OPENSSL_NO_ENGINE */
    190 
    191 int setup_engine_loader(void)
    192 {
    193     return 0;
    194 }
    195 
    196 void destroy_engine_loader(void)
    197 {
    198 }
    199 
    200 #endif
    201