Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/apps/lib/engine_loader.c
34878 views
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
204