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 = 126 ENGINE_load_private_key(ctx->e, ctx->keyid, 127 (UI_METHOD *)ui_method, ui_data); 128 if ((pkey == NULL && ctx->expected == 0) 129 || ctx->expected == OSSL_STORE_INFO_PUBKEY) 130 pubkey = 131 ENGINE_load_public_key(ctx->e, ctx->keyid, 132 (UI_METHOD *)ui_method, ui_data); 133 ENGINE_finish(ctx->e); 134 } 135 } 136 137 ctx->loaded = 1; 138 139 if (pubkey != NULL) 140 info = OSSL_STORE_INFO_new_PUBKEY(pubkey); 141 else if (pkey != NULL) 142 info = OSSL_STORE_INFO_new_PKEY(pkey); 143 if (info == NULL) { 144 EVP_PKEY_free(pkey); 145 EVP_PKEY_free(pubkey); 146 } 147 return info; 148 } 149 150 static int engine_eof(OSSL_STORE_LOADER_CTX *ctx) 151 { 152 return ctx->loaded != 0; 153 } 154 155 static int engine_error(OSSL_STORE_LOADER_CTX *ctx) 156 { 157 return 0; 158 } 159 160 static int engine_close(OSSL_STORE_LOADER_CTX *ctx) 161 { 162 OSSL_STORE_LOADER_CTX_free(ctx); 163 return 1; 164 } 165 166 int setup_engine_loader(void) 167 { 168 OSSL_STORE_LOADER *loader = NULL; 169 170 if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL 171 || !OSSL_STORE_LOADER_set_open(loader, engine_open) 172 || !OSSL_STORE_LOADER_set_expect(loader, engine_expect) 173 || !OSSL_STORE_LOADER_set_load(loader, engine_load) 174 || !OSSL_STORE_LOADER_set_eof(loader, engine_eof) 175 || !OSSL_STORE_LOADER_set_error(loader, engine_error) 176 || !OSSL_STORE_LOADER_set_close(loader, engine_close) 177 || !OSSL_STORE_register_loader(loader)) { 178 OSSL_STORE_LOADER_free(loader); 179 loader = NULL; 180 } 181 182 return loader != NULL; 183 } 184 185 void destroy_engine_loader(void) 186 { 187 OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME); 188 OSSL_STORE_LOADER_free(loader); 189 } 190 191 #else /* !OPENSSL_NO_ENGINE */ 192 193 int setup_engine_loader(void) 194 { 195 return 0; 196 } 197 198 void destroy_engine_loader(void) 199 { 200 } 201 202 #endif 203