]>
Commit | Line | Data |
---|---|---|
8efc4a9c MC |
1 | /* |
2 | * Copyright 2020 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 | #include <openssl/core_numbers.h> | |
11 | #include <openssl/core_names.h> | |
12 | #include <openssl/err.h> | |
13 | #include <openssl/pem.h> | |
14 | #include <openssl/types.h> | |
15 | #include <openssl/params.h> | |
244bc297 | 16 | #include "crypto/ecx.h" |
8efc4a9c MC |
17 | #include "prov/bio.h" |
18 | #include "prov/implementations.h" | |
d40b42ab | 19 | #include "prov/provider_ctx.h" |
8efc4a9c MC |
20 | #include "serializer_local.h" |
21 | ||
22 | static OSSL_OP_serializer_newctx_fn x25519_priv_newctx; | |
23 | static OSSL_OP_serializer_newctx_fn x448_priv_newctx; | |
244bc297 MC |
24 | static OSSL_OP_serializer_newctx_fn ed25519_priv_newctx; |
25 | static OSSL_OP_serializer_newctx_fn ed448_priv_newctx; | |
8efc4a9c MC |
26 | static OSSL_OP_serializer_freectx_fn ecx_priv_freectx; |
27 | static OSSL_OP_serializer_set_ctx_params_fn ecx_priv_set_ctx_params; | |
28 | static OSSL_OP_serializer_settable_ctx_params_fn ecx_priv_settable_ctx_params; | |
29 | static OSSL_OP_serializer_serialize_data_fn ecx_priv_der_data; | |
30 | static OSSL_OP_serializer_serialize_object_fn ecx_priv_der; | |
31 | static OSSL_OP_serializer_serialize_data_fn ecx_priv_pem_data; | |
32 | static OSSL_OP_serializer_serialize_object_fn ecx_priv_pem; | |
33 | ||
34 | static OSSL_OP_serializer_serialize_data_fn ecx_priv_print_data; | |
35 | static OSSL_OP_serializer_serialize_object_fn ecx_priv_print; | |
36 | ||
37 | /* | |
38 | * Context used for private key serialization. | |
39 | */ | |
40 | struct ecx_priv_ctx_st { | |
41 | void *provctx; | |
42 | ||
43 | struct pkcs8_encrypt_ctx_st sc; | |
44 | ECX_KEY_TYPE type; | |
45 | }; | |
46 | ||
47 | /* Private key : context */ | |
48 | static void *ecx_priv_newctx(void *provctx, ECX_KEY_TYPE type) | |
49 | { | |
50 | struct ecx_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); | |
51 | ||
52 | if (ctx != NULL) { | |
53 | ctx->provctx = provctx; | |
54 | ||
55 | /* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */ | |
56 | ctx->sc.pbe_nid = -1; | |
57 | ctx->type = type; | |
58 | } | |
59 | return ctx; | |
60 | } | |
61 | ||
62 | static void *x25519_priv_newctx(void *provctx) | |
63 | { | |
64 | return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X25519); | |
65 | } | |
66 | ||
67 | static void *x448_priv_newctx(void *provctx) | |
68 | { | |
69 | return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X448); | |
70 | } | |
71 | ||
244bc297 MC |
72 | static void *ed25519_priv_newctx(void *provctx) |
73 | { | |
74 | return ecx_priv_newctx(provctx, ECX_KEY_TYPE_ED25519); | |
75 | } | |
76 | ||
77 | static void *ed448_priv_newctx(void *provctx) | |
78 | { | |
79 | return ecx_priv_newctx(provctx, ECX_KEY_TYPE_ED448); | |
80 | } | |
81 | ||
8efc4a9c MC |
82 | static void ecx_priv_freectx(void *vctx) |
83 | { | |
84 | struct ecx_priv_ctx_st *ctx = vctx; | |
85 | ||
86 | EVP_CIPHER_free(ctx->sc.cipher); | |
87 | OPENSSL_free(ctx->sc.cipher_pass); | |
88 | OPENSSL_free(ctx); | |
89 | } | |
90 | ||
91 | static const OSSL_PARAM *ecx_priv_settable_ctx_params(void) | |
92 | { | |
93 | static const OSSL_PARAM settables[] = { | |
94 | OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0), | |
95 | OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0), | |
96 | OSSL_PARAM_END, | |
97 | }; | |
98 | ||
99 | return settables; | |
100 | } | |
101 | ||
102 | static int ecx_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
103 | { | |
104 | struct ecx_priv_ctx_st *ctx = vctx; | |
105 | const OSSL_PARAM *p; | |
106 | ||
107 | p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER); | |
108 | if (p != NULL) { | |
109 | const OSSL_PARAM *propsp = | |
110 | OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES); | |
111 | const char *props; | |
112 | ||
113 | if (p->data_type != OSSL_PARAM_UTF8_STRING) | |
114 | return 0; | |
115 | if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING) | |
116 | return 0; | |
117 | props = (propsp != NULL ? propsp->data : NULL); | |
118 | ||
119 | EVP_CIPHER_free(ctx->sc.cipher); | |
120 | ctx->sc.cipher_intent = p->data != NULL; | |
121 | if (p->data != NULL | |
122 | && ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props)) | |
123 | == NULL)) | |
124 | return 0; | |
125 | } | |
126 | p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS); | |
127 | if (p != NULL) { | |
128 | OPENSSL_free(ctx->sc.cipher_pass); | |
129 | ctx->sc.cipher_pass = NULL; | |
130 | if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0, | |
131 | &ctx->sc.cipher_pass_length)) | |
132 | return 0; | |
133 | } | |
134 | return 1; | |
135 | } | |
136 | ||
137 | /* Private key : DER */ | |
d40b42ab MC |
138 | static int ecx_priv_der_data(void *vctx, const OSSL_PARAM params[], |
139 | OSSL_CORE_BIO *out, | |
8efc4a9c MC |
140 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) |
141 | { | |
142 | struct ecx_priv_ctx_st *ctx = vctx; | |
143 | OSSL_OP_keymgmt_new_fn *ecx_new; | |
144 | OSSL_OP_keymgmt_free_fn *ecx_free; | |
145 | OSSL_OP_keymgmt_import_fn *ecx_import; | |
146 | int ok = 0; | |
147 | ||
148 | ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import); | |
149 | ||
150 | if (ecx_import != NULL) { | |
151 | ECX_KEY *ecxkey; | |
152 | ||
153 | if ((ecxkey = ecx_new(ctx->provctx)) != NULL | |
154 | && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params) | |
155 | && ecx_priv_der(ctx, ecxkey, out, cb, cbarg)) | |
156 | ok = 1; | |
157 | ecx_free(ecxkey); | |
158 | } | |
159 | return ok; | |
160 | } | |
161 | ||
d40b42ab | 162 | static int ecx_priv_der(void *vctx, void *vecxkey, OSSL_CORE_BIO *cout, |
8efc4a9c MC |
163 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) |
164 | { | |
165 | struct ecx_priv_ctx_st *ctx = vctx; | |
166 | ECX_KEY *ecxkey = vecxkey; | |
167 | int ret; | |
244bc297 | 168 | int nid = KEYTYPE2NID(ctx->type); |
d40b42ab MC |
169 | BIO *out = bio_new_from_core_bio(ctx->provctx, cout); |
170 | ||
171 | if (out == NULL) | |
172 | return 0; | |
8efc4a9c MC |
173 | |
174 | ctx->sc.cb = cb; | |
175 | ctx->sc.cbarg = cbarg; | |
176 | ||
177 | ret = ossl_prov_write_priv_der_from_obj(out, ecxkey, | |
244bc297 | 178 | nid, |
8efc4a9c MC |
179 | NULL, |
180 | ossl_prov_ecx_priv_to_der, | |
181 | &ctx->sc); | |
d40b42ab | 182 | BIO_free(out); |
8efc4a9c MC |
183 | |
184 | return ret; | |
185 | } | |
186 | ||
187 | /* Private key : PEM */ | |
d40b42ab MC |
188 | static int ecx_priv_pem_data(void *vctx, const OSSL_PARAM params[], |
189 | OSSL_CORE_BIO *out, | |
8efc4a9c MC |
190 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) |
191 | { | |
192 | struct ecx_priv_ctx_st *ctx = vctx; | |
193 | OSSL_OP_keymgmt_new_fn *ecx_new; | |
194 | OSSL_OP_keymgmt_free_fn *ecx_free; | |
195 | OSSL_OP_keymgmt_import_fn *ecx_import; | |
196 | int ok = 0; | |
197 | ||
198 | ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import); | |
199 | ||
200 | if (ecx_import != NULL) { | |
201 | ECX_KEY *ecxkey; | |
202 | ||
203 | if ((ecxkey = ecx_new(ctx->provctx)) != NULL | |
204 | && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params) | |
205 | && ecx_priv_pem(ctx->provctx, ecxkey, out, cb, cbarg)) | |
206 | ok = 1; | |
207 | ecx_free(ecxkey); | |
208 | } | |
209 | return ok; | |
210 | } | |
211 | ||
d40b42ab | 212 | static int ecx_priv_pem(void *vctx, void *ecxkey, OSSL_CORE_BIO *cout, |
8efc4a9c MC |
213 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) |
214 | { | |
215 | struct ecx_priv_ctx_st *ctx = vctx; | |
216 | int ret; | |
244bc297 | 217 | int nid = KEYTYPE2NID(ctx->type); |
d40b42ab MC |
218 | BIO *out = bio_new_from_core_bio(ctx->provctx, cout); |
219 | ||
220 | if (out == NULL) | |
221 | return 0; | |
8efc4a9c MC |
222 | |
223 | ctx->sc.cb = cb; | |
224 | ctx->sc.cbarg = cbarg; | |
225 | ||
226 | ret = ossl_prov_write_priv_pem_from_obj(out, ecxkey, | |
244bc297 | 227 | nid, |
8efc4a9c MC |
228 | NULL, |
229 | ossl_prov_ecx_priv_to_der, | |
230 | &ctx->sc); | |
d40b42ab | 231 | BIO_free(out); |
8efc4a9c MC |
232 | |
233 | return ret; | |
234 | } | |
235 | ||
d40b42ab MC |
236 | static int ecx_priv_print_data(void *vctx, const OSSL_PARAM params[], |
237 | OSSL_CORE_BIO *out, | |
8efc4a9c MC |
238 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) |
239 | { | |
240 | struct ecx_priv_ctx_st *ctx = vctx; | |
241 | OSSL_OP_keymgmt_new_fn *ecx_new; | |
242 | OSSL_OP_keymgmt_free_fn *ecx_free; | |
243 | OSSL_OP_keymgmt_import_fn *ecx_import; | |
244 | int ok = 0; | |
245 | ||
246 | ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import); | |
247 | ||
248 | if (ecx_import != NULL) { | |
249 | ECX_KEY *ecxkey; | |
250 | ||
251 | if ((ecxkey = ecx_new(ctx->provctx)) != NULL | |
252 | && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params) | |
253 | && ecx_priv_print(ctx, ecxkey, out, cb, cbarg)) | |
254 | ok = 1; | |
255 | ecx_free(ecxkey); | |
256 | } | |
257 | return ok; | |
258 | } | |
259 | ||
d40b42ab | 260 | static int ecx_priv_print(void *vctx, void *ecxkey, OSSL_CORE_BIO *cout, |
8efc4a9c MC |
261 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) |
262 | { | |
d40b42ab MC |
263 | struct ecx_priv_ctx_st *ctx = vctx; |
264 | BIO *out = bio_new_from_core_bio(ctx->provctx, cout); | |
265 | int ret; | |
266 | ||
267 | if (out == NULL) | |
268 | return 0; | |
269 | ||
270 | ret = ossl_prov_print_ecx(out, ecxkey, ecx_print_priv); | |
271 | BIO_free(out); | |
272 | ||
273 | return ret; | |
8efc4a9c MC |
274 | } |
275 | ||
276 | #define MAKE_SERIALIZER_FUNCTIONS(alg, type) \ | |
277 | const OSSL_DISPATCH alg##_priv_##type##_serializer_functions[] = { \ | |
278 | { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \ | |
279 | { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \ | |
280 | { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, \ | |
281 | (void (*)(void))ecx_priv_set_ctx_params }, \ | |
282 | { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, \ | |
283 | (void (*)(void))ecx_priv_settable_ctx_params }, \ | |
284 | { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \ | |
285 | (void (*)(void))ecx_priv_##type##_data }, \ | |
286 | { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \ | |
287 | (void (*)(void))ecx_priv_##type }, \ | |
288 | { 0, NULL } \ | |
289 | }; | |
290 | ||
291 | #define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \ | |
292 | MAKE_SERIALIZER_FUNCTIONS(alg, der) \ | |
293 | MAKE_SERIALIZER_FUNCTIONS(alg, pem) \ | |
294 | const OSSL_DISPATCH alg##_priv_print_serializer_functions[] = { \ | |
295 | { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \ | |
296 | { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \ | |
297 | { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \ | |
298 | (void (*)(void))ecx_priv_print }, \ | |
299 | { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \ | |
300 | (void (*)(void))ecx_priv_print_data }, \ | |
301 | { 0, NULL } \ | |
302 | }; | |
303 | ||
304 | MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519) | |
305 | MAKE_SERIALIZER_FUNCTIONS_GROUP(x448) | |
244bc297 MC |
306 | MAKE_SERIALIZER_FUNCTIONS_GROUP(ed25519) |
307 | MAKE_SERIALIZER_FUNCTIONS_GROUP(ed448) |