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