2 * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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
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.
15 #define OPENSSL_SUPPRESS_DEPRECATED
19 #ifndef OPENSSL_NO_ENGINE
23 # include <openssl/engine.h>
24 # include <openssl/store.h>
27 * Support for legacy private engine keys via the 'org.openssl.engine:' scheme
29 * org.openssl.engine:{engineid}:{keyid}
31 * Note: we ONLY support ENGINE_load_private_key() and ENGINE_load_public_key()
32 * Note 2: This scheme has a precedent in code in PKIX-SSH. for exactly
33 * this sort of purpose.
36 /* Local definition of OSSL_STORE_LOADER_CTX */
37 struct ossl_store_loader_ctx_st {
38 ENGINE *e; /* Structural reference */
41 int loaded; /* 0 = key not loaded yet, 1 = key loaded */
44 static OSSL_STORE_LOADER_CTX *OSSL_STORE_LOADER_CTX_new(ENGINE *e, char *keyid)
46 OSSL_STORE_LOADER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
55 static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
59 OPENSSL_free(ctx->keyid);
64 static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader,
66 const UI_METHOD *ui_method,
69 const char *p = uri, *q;
72 OSSL_STORE_LOADER_CTX *ctx = NULL;
74 if (!CHECK_AND_SKIP_CASE_PREFIX(p, ENGINE_SCHEME_COLON))
77 /* Look for engine ID */
79 if (q != NULL /* There is both an engine ID and a key ID */
80 && p[0] != ':' /* The engine ID is at least one character */
81 && q[1] != '\0') { /* The key ID is at least one character */
83 size_t engineid_l = q - p;
85 strncpy(engineid, p, engineid_l);
86 engineid[engineid_l] = '\0';
87 e = ENGINE_by_id(engineid);
89 keyid = OPENSSL_strdup(q + 1);
93 ctx = OSSL_STORE_LOADER_CTX_new(e, keyid);
103 static int engine_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
106 || expected == OSSL_STORE_INFO_PUBKEY
107 || expected == OSSL_STORE_INFO_PKEY) {
108 ctx->expected = expected;
114 static OSSL_STORE_INFO *engine_load(OSSL_STORE_LOADER_CTX *ctx,
115 const UI_METHOD *ui_method, void *ui_data)
117 EVP_PKEY *pkey = NULL, *pubkey = NULL;
118 OSSL_STORE_INFO *info = NULL;
120 if (ctx->loaded == 0) {
121 if (ENGINE_init(ctx->e)) {
122 if (ctx->expected == 0
123 || ctx->expected == OSSL_STORE_INFO_PKEY)
125 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)
130 ENGINE_load_public_key(ctx->e, ctx->keyid,
131 (UI_METHOD *)ui_method, ui_data);
132 ENGINE_finish(ctx->e);
139 info = OSSL_STORE_INFO_new_PUBKEY(pubkey);
140 else if (pkey != NULL)
141 info = OSSL_STORE_INFO_new_PKEY(pkey);
144 EVP_PKEY_free(pubkey);
149 static int engine_eof(OSSL_STORE_LOADER_CTX *ctx)
151 return ctx->loaded != 0;
154 static int engine_error(OSSL_STORE_LOADER_CTX *ctx)
159 static int engine_close(OSSL_STORE_LOADER_CTX *ctx)
161 OSSL_STORE_LOADER_CTX_free(ctx);
165 int setup_engine_loader(void)
167 OSSL_STORE_LOADER *loader = NULL;
169 if ((loader = OSSL_STORE_LOADER_new(NULL, ENGINE_SCHEME)) == NULL
170 || !OSSL_STORE_LOADER_set_open(loader, engine_open)
171 || !OSSL_STORE_LOADER_set_expect(loader, engine_expect)
172 || !OSSL_STORE_LOADER_set_load(loader, engine_load)
173 || !OSSL_STORE_LOADER_set_eof(loader, engine_eof)
174 || !OSSL_STORE_LOADER_set_error(loader, engine_error)
175 || !OSSL_STORE_LOADER_set_close(loader, engine_close)
176 || !OSSL_STORE_register_loader(loader)) {
177 OSSL_STORE_LOADER_free(loader);
181 return loader != NULL;
184 void destroy_engine_loader(void)
186 OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader(ENGINE_SCHEME);
187 OSSL_STORE_LOADER_free(loader);
190 #else /* !OPENSSL_NO_ENGINE */
192 int setup_engine_loader(void)
197 void destroy_engine_loader(void)