]>
Commit | Line | Data |
---|---|---|
8ae40cf5 RL |
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 | /* | |
11 | * Low level APIs are deprecated for public use, but still ok for internal use. | |
12 | */ | |
13 | #include "internal/deprecated.h" | |
14 | ||
15 | #include <openssl/core.h> | |
16 | #include <openssl/core_dispatch.h> | |
17 | #include <openssl/core_names.h> | |
18 | #include <openssl/crypto.h> | |
19 | #include <openssl/params.h> | |
20 | #include <openssl/asn1.h> | |
21 | #include <openssl/err.h> | |
22 | #include <openssl/pem.h> | |
23 | #include <openssl/x509.h> | |
24 | #include <openssl/pkcs12.h> /* PKCS8_encrypt() */ | |
25 | #include <openssl/dh.h> | |
26 | #include <openssl/dsa.h> | |
27 | #include <openssl/ec.h> | |
28 | #include "internal/passphrase.h" | |
29 | #include "internal/cryptlib.h" | |
30 | #include "crypto/ecx.h" | |
31 | #include "crypto/rsa.h" | |
32 | #include "prov/implementations.h" | |
33 | #include "prov/providercommonerr.h" | |
34 | #include "prov/bio.h" | |
35 | #include "prov/provider_ctx.h" | |
36 | #include "prov/der_rsa.h" | |
37 | #include "endecoder_local.h" | |
38 | ||
39 | struct key2any_ctx_st { | |
40 | PROV_CTX *provctx; | |
41 | ||
42 | /* Set to 1 if intending to encrypt/decrypt, otherwise 0 */ | |
43 | int cipher_intent; | |
44 | ||
45 | EVP_CIPHER *cipher; | |
46 | ||
47 | struct ossl_passphrase_data_st pwdata; | |
48 | }; | |
49 | ||
111dc4b0 | 50 | typedef int check_key_type_fn(const void *key, int nid); |
8ae40cf5 RL |
51 | typedef int key_to_paramstring_fn(const void *key, int nid, |
52 | void **str, int *strtype); | |
53 | typedef int key_to_der_fn(BIO *out, const void *key, int key_nid, | |
54 | key_to_paramstring_fn *p2s, i2d_of_void *k2d, | |
55 | struct key2any_ctx_st *ctx); | |
56 | typedef int write_bio_of_void_fn(BIO *bp, const void *x); | |
57 | ||
58 | static PKCS8_PRIV_KEY_INFO *key_to_p8info(const void *key, int key_nid, | |
59 | void *params, int params_type, | |
60 | i2d_of_void *k2d) | |
61 | { | |
62 | /* der, derlen store the key DER output and its length */ | |
63 | unsigned char *der = NULL; | |
64 | int derlen; | |
65 | /* The final PKCS#8 info */ | |
66 | PKCS8_PRIV_KEY_INFO *p8info = NULL; | |
67 | ||
68 | ||
69 | if ((p8info = PKCS8_PRIV_KEY_INFO_new()) == NULL | |
70 | || (derlen = k2d(key, &der)) <= 0 | |
71 | || !PKCS8_pkey_set0(p8info, OBJ_nid2obj(key_nid), 0, | |
72 | params_type, params, der, derlen)) { | |
73 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
74 | PKCS8_PRIV_KEY_INFO_free(p8info); | |
75 | OPENSSL_free(der); | |
76 | p8info = NULL; | |
77 | } | |
78 | ||
79 | return p8info; | |
80 | } | |
81 | ||
82 | static X509_SIG *p8info_to_encp8(PKCS8_PRIV_KEY_INFO *p8info, | |
83 | struct key2any_ctx_st *ctx) | |
84 | { | |
85 | X509_SIG *p8 = NULL; | |
86 | char kstr[PEM_BUFSIZE]; | |
87 | size_t klen = 0; | |
88 | ||
89 | if (ctx->cipher == NULL) | |
90 | return NULL; | |
91 | ||
92 | if (!ossl_pw_get_passphrase(kstr, sizeof(kstr), &klen, NULL, 1, | |
93 | &ctx->pwdata)) { | |
94 | ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY); | |
95 | return NULL; | |
96 | } | |
97 | /* First argument == -1 means "standard" */ | |
98 | p8 = PKCS8_encrypt(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info); | |
99 | OPENSSL_cleanse(kstr, klen); | |
100 | return p8; | |
101 | } | |
102 | ||
103 | static X509_SIG *key_to_encp8(const void *key, int key_nid, | |
104 | void *params, int params_type, | |
105 | i2d_of_void *k2d, struct key2any_ctx_st *ctx) | |
106 | { | |
107 | PKCS8_PRIV_KEY_INFO *p8info = | |
108 | key_to_p8info(key, key_nid, params, params_type, k2d); | |
109 | X509_SIG *p8 = p8info_to_encp8(p8info, ctx); | |
110 | ||
111 | PKCS8_PRIV_KEY_INFO_free(p8info); | |
112 | return p8; | |
113 | } | |
114 | ||
115 | static X509_PUBKEY *key_to_pubkey(const void *key, int key_nid, | |
116 | void *params, int params_type, | |
117 | i2d_of_void k2d) | |
118 | { | |
119 | /* der, derlen store the key DER output and its length */ | |
120 | unsigned char *der = NULL; | |
121 | int derlen; | |
122 | /* The final X509_PUBKEY */ | |
123 | X509_PUBKEY *xpk = NULL; | |
124 | ||
125 | ||
126 | if ((xpk = X509_PUBKEY_new()) == NULL | |
127 | || (derlen = k2d(key, &der)) <= 0 | |
128 | || !X509_PUBKEY_set0_param(xpk, OBJ_nid2obj(key_nid), | |
129 | params_type, params, der, derlen)) { | |
130 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
131 | X509_PUBKEY_free(xpk); | |
132 | OPENSSL_free(der); | |
133 | xpk = NULL; | |
134 | } | |
135 | ||
136 | return xpk; | |
137 | } | |
138 | ||
139 | static int key_to_der_pkcs8_bio(BIO *out, const void *key, int key_nid, | |
140 | key_to_paramstring_fn *p2s, i2d_of_void *k2d, | |
141 | struct key2any_ctx_st *ctx) | |
142 | { | |
143 | int ret = 0; | |
144 | void *str = NULL; | |
145 | int strtype = V_ASN1_UNDEF; | |
146 | ||
147 | if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) | |
148 | return 0; | |
149 | ||
150 | if (ctx->cipher_intent) { | |
151 | X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); | |
152 | ||
153 | if (p8 != NULL) | |
154 | ret = i2d_PKCS8_bio(out, p8); | |
155 | ||
156 | X509_SIG_free(p8); | |
157 | } else { | |
158 | PKCS8_PRIV_KEY_INFO *p8info = | |
159 | key_to_p8info(key, key_nid, str, strtype, k2d); | |
160 | ||
161 | if (p8info != NULL) | |
162 | ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info); | |
163 | ||
164 | PKCS8_PRIV_KEY_INFO_free(p8info); | |
165 | } | |
166 | ||
167 | return ret; | |
168 | } | |
169 | ||
170 | static int key_to_pem_pkcs8_bio(BIO *out, const void *key, int key_nid, | |
171 | key_to_paramstring_fn *p2s, i2d_of_void *k2d, | |
172 | struct key2any_ctx_st *ctx) | |
173 | { | |
174 | int ret = 0; | |
175 | void *str = NULL; | |
176 | int strtype = V_ASN1_UNDEF; | |
177 | ||
178 | if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) | |
179 | return 0; | |
180 | ||
181 | if (ctx->cipher_intent) { | |
182 | X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); | |
183 | ||
184 | if (p8 != NULL) | |
185 | ret = PEM_write_bio_PKCS8(out, p8); | |
186 | ||
187 | X509_SIG_free(p8); | |
188 | } else { | |
189 | PKCS8_PRIV_KEY_INFO *p8info = | |
190 | key_to_p8info(key, key_nid, str, strtype, k2d); | |
191 | ||
192 | if (p8info != NULL) | |
193 | ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info); | |
194 | ||
195 | PKCS8_PRIV_KEY_INFO_free(p8info); | |
196 | } | |
197 | ||
198 | return ret; | |
199 | } | |
200 | ||
201 | static int key_to_der_pubkey_bio(BIO *out, const void *key, int key_nid, | |
202 | key_to_paramstring_fn *p2s, i2d_of_void *k2d, | |
203 | struct key2any_ctx_st *ctx) | |
204 | { | |
205 | int ret = 0; | |
206 | void *str = NULL; | |
207 | int strtype = V_ASN1_UNDEF; | |
208 | X509_PUBKEY *xpk = NULL; | |
209 | ||
210 | if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) | |
211 | return 0; | |
212 | ||
213 | xpk = key_to_pubkey(key, key_nid, str, strtype, k2d); | |
214 | ||
215 | if (xpk != NULL) | |
216 | ret = i2d_X509_PUBKEY_bio(out, xpk); | |
217 | ||
218 | /* Also frees |str| */ | |
219 | X509_PUBKEY_free(xpk); | |
220 | return ret; | |
221 | } | |
222 | ||
223 | static int key_to_pem_pubkey_bio(BIO *out, const void *key, int key_nid, | |
224 | key_to_paramstring_fn *p2s, i2d_of_void *k2d, | |
225 | struct key2any_ctx_st *ctx) | |
226 | { | |
227 | int ret = 0; | |
228 | void *str = NULL; | |
229 | int strtype = V_ASN1_UNDEF; | |
230 | X509_PUBKEY *xpk = NULL; | |
231 | ||
232 | if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) | |
233 | return 0; | |
234 | ||
235 | xpk = key_to_pubkey(key, key_nid, str, strtype, k2d); | |
236 | ||
237 | if (xpk != NULL) | |
238 | ret = PEM_write_bio_X509_PUBKEY(out, xpk); | |
239 | ||
240 | /* Also frees |str| */ | |
241 | X509_PUBKEY_free(xpk); | |
242 | return ret; | |
243 | } | |
244 | ||
111dc4b0 RL |
245 | #define der_output_type "DER" |
246 | #define pem_output_type "PEM" | |
247 | ||
8ae40cf5 RL |
248 | /* ---------------------------------------------------------------------- */ |
249 | ||
250 | #ifndef OPENSSL_NO_DH | |
8ae40cf5 RL |
251 | static int prepare_dh_params(const void *dh, int nid, |
252 | void **pstr, int *pstrtype) | |
253 | { | |
254 | ASN1_STRING *params = ASN1_STRING_new(); | |
255 | ||
256 | if (params == NULL) { | |
257 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
258 | return 0; | |
259 | } | |
260 | ||
261 | if (nid == EVP_PKEY_DHX) | |
262 | params->length = i2d_DHxparams(dh, ¶ms->data); | |
263 | else | |
264 | params->length = i2d_DHparams(dh, ¶ms->data); | |
265 | ||
266 | if (params->length <= 0) { | |
267 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
268 | ASN1_STRING_free(params); | |
269 | return 0; | |
270 | } | |
271 | params->type = V_ASN1_SEQUENCE; | |
272 | ||
273 | *pstr = params; | |
274 | *pstrtype = V_ASN1_SEQUENCE; | |
275 | return 1; | |
276 | } | |
277 | ||
278 | static int dh_pub_to_der(const void *dh, unsigned char **pder) | |
279 | { | |
280 | const BIGNUM *bn = NULL; | |
281 | ASN1_INTEGER *pub_key = NULL; | |
282 | int ret; | |
283 | ||
284 | if ((bn = DH_get0_pub_key(dh)) == NULL) { | |
285 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY); | |
286 | return 0; | |
287 | } | |
288 | if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) { | |
289 | ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR); | |
290 | return 0; | |
291 | } | |
292 | ||
293 | ret = i2d_ASN1_INTEGER(pub_key, pder); | |
294 | ||
295 | ASN1_STRING_clear_free(pub_key); | |
296 | return ret; | |
297 | } | |
298 | ||
299 | static int dh_priv_to_der(const void *dh, unsigned char **pder) | |
300 | { | |
301 | const BIGNUM *bn = NULL; | |
302 | ASN1_INTEGER *priv_key = NULL; | |
303 | int ret; | |
304 | ||
305 | if ((bn = DH_get0_priv_key(dh)) == NULL) { | |
306 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); | |
307 | return 0; | |
308 | } | |
309 | if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) { | |
310 | ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR); | |
311 | return 0; | |
312 | } | |
313 | ||
314 | ret = i2d_ASN1_INTEGER(priv_key, pder); | |
315 | ||
316 | ASN1_STRING_clear_free(priv_key); | |
317 | return ret; | |
318 | } | |
319 | ||
320 | static int dh_params_to_der_bio(BIO *out, const void *key) | |
321 | { | |
322 | return i2d_DHparams_bio(out, key); | |
323 | } | |
324 | ||
325 | static int dh_params_to_pem_bio(BIO *out, const void *key) | |
326 | { | |
327 | return PEM_write_bio_DHparams(out, key); | |
328 | } | |
111dc4b0 RL |
329 | |
330 | static int dh_check_key_type(const void *key, int expected_type) | |
331 | { | |
332 | int type = | |
333 | DH_test_flags(key, DH_FLAG_TYPE_DHX) ? EVP_PKEY_DHX : EVP_PKEY_DH; | |
334 | ||
335 | return type == expected_type; | |
336 | } | |
337 | ||
338 | # define dh_evp_type EVP_PKEY_DH | |
339 | # define dhx_evp_type EVP_PKEY_DHX | |
340 | # define dh_input_type "DH" | |
341 | # define dhx_input_type "DHX" | |
8ae40cf5 RL |
342 | #endif |
343 | ||
344 | /* ---------------------------------------------------------------------- */ | |
345 | ||
346 | #ifndef OPENSSL_NO_DSA | |
8ae40cf5 RL |
347 | static int prepare_some_dsa_params(const void *dsa, int nid, |
348 | void **pstr, int *pstrtype) | |
349 | { | |
350 | ASN1_STRING *params = ASN1_STRING_new(); | |
351 | ||
352 | if (params == NULL) { | |
353 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
354 | return 0; | |
355 | } | |
356 | ||
357 | params->length = i2d_DSAparams(dsa, ¶ms->data); | |
358 | ||
359 | if (params->length <= 0) { | |
360 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
361 | ASN1_STRING_free(params); | |
362 | return 0; | |
363 | } | |
364 | ||
365 | *pstrtype = V_ASN1_SEQUENCE; | |
366 | *pstr = params; | |
367 | return 1; | |
368 | } | |
369 | ||
370 | static int prepare_all_dsa_params(const void *dsa, int nid, | |
371 | void **pstr, int *pstrtype) | |
372 | { | |
373 | const BIGNUM *p = DSA_get0_p(dsa); | |
374 | const BIGNUM *q = DSA_get0_q(dsa); | |
375 | const BIGNUM *g = DSA_get0_g(dsa); | |
376 | ||
377 | if (p != NULL && q != NULL && g != NULL) | |
378 | return prepare_some_dsa_params(dsa, nid, pstr, pstrtype); | |
379 | ||
380 | *pstr = NULL; | |
381 | *pstrtype = V_ASN1_UNDEF; | |
382 | return 1; | |
383 | } | |
384 | ||
385 | static int prepare_dsa_params(const void *dsa, int nid, | |
386 | void **pstr, int *pstrtype) | |
387 | { | |
388 | /* | |
389 | * TODO(v3.0) implement setting save_parameters, see dsa_pub_encode() | |
390 | * in crypto/dsa/dsa_ameth.c | |
391 | */ | |
392 | int save_parameters = 1; | |
393 | ||
394 | return save_parameters | |
395 | ? prepare_all_dsa_params(dsa, nid, pstr, pstrtype) | |
396 | : prepare_some_dsa_params(dsa, nid, pstr, pstrtype); | |
397 | } | |
398 | ||
399 | static int dsa_pub_to_der(const void *dsa, unsigned char **pder) | |
400 | { | |
401 | const BIGNUM *bn = NULL; | |
402 | ASN1_INTEGER *pub_key = NULL; | |
403 | int ret; | |
404 | ||
405 | if ((bn = DSA_get0_pub_key(dsa)) == NULL) { | |
406 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY); | |
407 | return 0; | |
408 | } | |
409 | if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) { | |
410 | ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR); | |
411 | return 0; | |
412 | } | |
413 | ||
414 | ret = i2d_ASN1_INTEGER(pub_key, pder); | |
415 | ||
416 | ASN1_STRING_clear_free(pub_key); | |
417 | return ret; | |
418 | } | |
419 | ||
420 | static int dsa_priv_to_der(const void *dsa, unsigned char **pder) | |
421 | { | |
422 | const BIGNUM *bn = NULL; | |
423 | ASN1_INTEGER *priv_key = NULL; | |
424 | int ret; | |
425 | ||
426 | if ((bn = DSA_get0_priv_key(dsa)) == NULL) { | |
427 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); | |
428 | return 0; | |
429 | } | |
430 | if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) { | |
431 | ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR); | |
432 | return 0; | |
433 | } | |
434 | ||
435 | ret = i2d_ASN1_INTEGER(priv_key, pder); | |
436 | ||
437 | ASN1_STRING_clear_free(priv_key); | |
438 | return ret; | |
439 | } | |
440 | ||
441 | static int dsa_params_to_der_bio(BIO *out, const void *key) | |
442 | { | |
443 | return i2d_DSAparams_bio(out, key); | |
444 | } | |
445 | ||
446 | static int dsa_params_to_pem_bio(BIO *out, const void *key) | |
447 | { | |
448 | return PEM_write_bio_DSAparams(out, key); | |
449 | } | |
111dc4b0 RL |
450 | |
451 | # define dsa_check_key_type NULL | |
452 | # define dsa_evp_type EVP_PKEY_DSA | |
453 | # define dsa_input_type "DSA" | |
8ae40cf5 RL |
454 | #endif |
455 | ||
456 | /* ---------------------------------------------------------------------- */ | |
457 | ||
458 | #ifndef OPENSSL_NO_EC | |
8ae40cf5 RL |
459 | static int prepare_ec_explicit_params(const void *eckey, |
460 | void **pstr, int *pstrtype) | |
461 | { | |
462 | ASN1_STRING *params = ASN1_STRING_new(); | |
463 | ||
464 | if (params == NULL) { | |
465 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
466 | return 0; | |
467 | } | |
468 | ||
469 | params->length = i2d_ECParameters(eckey, ¶ms->data); | |
470 | if (params->length <= 0) { | |
471 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
472 | ASN1_STRING_free(params); | |
473 | return 0; | |
474 | } | |
475 | ||
476 | *pstrtype = V_ASN1_SEQUENCE; | |
477 | *pstr = params; | |
478 | return 1; | |
479 | } | |
480 | ||
481 | static int prepare_ec_params(const void *eckey, int nid, | |
482 | void **pstr, int *pstrtype) | |
483 | { | |
484 | int curve_nid; | |
485 | const EC_GROUP *group = EC_KEY_get0_group(eckey); | |
486 | ASN1_OBJECT *params = NULL; | |
487 | ||
488 | if (group == NULL) | |
489 | return 0; | |
490 | curve_nid = EC_GROUP_get_curve_name(group); | |
491 | if (curve_nid != NID_undef) { | |
492 | params = OBJ_nid2obj(curve_nid); | |
493 | if (params == NULL) | |
494 | return 0; | |
495 | } | |
496 | ||
497 | if (curve_nid != NID_undef | |
498 | && (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE)) { | |
499 | if (OBJ_length(params) == 0) { | |
500 | /* Some curves might not have an associated OID */ | |
501 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_OID); | |
502 | ASN1_OBJECT_free(params); | |
503 | return 0; | |
504 | } | |
505 | *pstr = params; | |
506 | *pstrtype = V_ASN1_OBJECT; | |
507 | return 1; | |
508 | } else { | |
509 | return prepare_ec_explicit_params(eckey, pstr, pstrtype); | |
510 | } | |
511 | } | |
512 | ||
513 | static int ec_params_to_der_bio(BIO *out, const void *eckey) | |
514 | { | |
515 | return i2d_ECPKParameters_bio(out, EC_KEY_get0_group(eckey)); | |
516 | } | |
517 | ||
518 | static int ec_params_to_pem_bio(BIO *out, const void *eckey) | |
519 | { | |
520 | return PEM_write_bio_ECPKParameters(out, EC_KEY_get0_group(eckey)); | |
521 | } | |
522 | ||
523 | static int ec_pub_to_der(const void *eckey, unsigned char **pder) | |
524 | { | |
525 | return i2o_ECPublicKey(eckey, pder); | |
526 | } | |
527 | ||
528 | static int ec_priv_to_der(const void *veckey, unsigned char **pder) | |
529 | { | |
530 | EC_KEY *eckey = (EC_KEY *)veckey; | |
531 | unsigned int old_flags; | |
532 | int ret = 0; | |
533 | ||
534 | /* | |
535 | * For PKCS8 the curve name appears in the PKCS8_PRIV_KEY_INFO object | |
536 | * as the pkeyalg->parameter field. (For a named curve this is an OID) | |
537 | * The pkey field is an octet string that holds the encoded | |
538 | * ECPrivateKey SEQUENCE with the optional parameters field omitted. | |
539 | * We omit this by setting the EC_PKEY_NO_PARAMETERS flag. | |
540 | */ | |
541 | old_flags = EC_KEY_get_enc_flags(eckey); /* save old flags */ | |
542 | EC_KEY_set_enc_flags(eckey, old_flags | EC_PKEY_NO_PARAMETERS); | |
543 | ret = i2d_ECPrivateKey(eckey, pder); | |
544 | EC_KEY_set_enc_flags(eckey, old_flags); /* restore old flags */ | |
545 | return ret; /* return the length of the der encoded data */ | |
546 | } | |
111dc4b0 RL |
547 | |
548 | # define ec_check_key_type NULL | |
549 | # define ec_evp_type EVP_PKEY_EC | |
550 | # define ec_input_type "EC" | |
8ae40cf5 RL |
551 | #endif |
552 | ||
553 | /* ---------------------------------------------------------------------- */ | |
554 | ||
555 | #ifndef OPENSSL_NO_EC | |
8ae40cf5 RL |
556 | # define prepare_ecx_params NULL |
557 | ||
558 | static int ecx_pub_to_der(const void *vecxkey, unsigned char **pder) | |
559 | { | |
560 | const ECX_KEY *ecxkey = vecxkey; | |
561 | unsigned char *keyblob; | |
562 | ||
563 | if (ecxkey == NULL) { | |
564 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); | |
565 | return 0; | |
566 | } | |
567 | ||
568 | keyblob = OPENSSL_memdup(ecxkey->pubkey, ecxkey->keylen); | |
569 | if (keyblob == NULL) { | |
570 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
571 | return 0; | |
572 | } | |
573 | ||
574 | *pder = keyblob; | |
575 | return ecxkey->keylen; | |
576 | } | |
577 | ||
578 | static int ecx_priv_to_der(const void *vecxkey, unsigned char **pder) | |
579 | { | |
580 | const ECX_KEY *ecxkey = vecxkey; | |
581 | ASN1_OCTET_STRING oct; | |
582 | int keybloblen; | |
583 | ||
584 | if (ecxkey == NULL || ecxkey->privkey == NULL) { | |
585 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); | |
586 | return 0; | |
587 | } | |
588 | ||
589 | oct.data = ecxkey->privkey; | |
590 | oct.length = ecxkey->keylen; | |
591 | oct.flags = 0; | |
592 | ||
593 | keybloblen = i2d_ASN1_OCTET_STRING(&oct, pder); | |
594 | if (keybloblen < 0) { | |
595 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
596 | return 0; | |
597 | } | |
598 | ||
599 | return keybloblen; | |
600 | } | |
601 | ||
111dc4b0 RL |
602 | # define ecx_params_to_der_bio NULL |
603 | # define ecx_params_to_pem_bio NULL | |
604 | # define ecx_check_key_type NULL | |
605 | ||
606 | # define ed25519_evp_type EVP_PKEY_ED25519 | |
607 | # define ed448_evp_type EVP_PKEY_ED448 | |
608 | # define x25519_evp_type EVP_PKEY_X25519 | |
609 | # define x448_evp_type EVP_PKEY_X448 | |
610 | # define ed25519_input_type "ED25519" | |
611 | # define ed448_input_type "ED448" | |
612 | # define x25519_input_type "X25519" | |
613 | # define x448_input_type "X448" | |
8ae40cf5 RL |
614 | #endif |
615 | ||
616 | /* ---------------------------------------------------------------------- */ | |
617 | ||
8ae40cf5 RL |
618 | /* |
619 | * Helper functions to prepare RSA-PSS params for encoding. We would | |
620 | * have simply written the whole AlgorithmIdentifier, but existing libcrypto | |
621 | * functionality doesn't allow that. | |
622 | */ | |
623 | ||
624 | static int prepare_rsa_params(const void *rsa, int nid, | |
625 | void **pstr, int *pstrtype) | |
626 | { | |
23b2fc0b | 627 | const RSA_PSS_PARAMS_30 *pss = ossl_rsa_get0_pss_params_30((RSA *)rsa); |
8ae40cf5 RL |
628 | |
629 | *pstr = NULL; | |
630 | ||
631 | switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) { | |
632 | case RSA_FLAG_TYPE_RSA: | |
633 | /* If plain RSA, the parameters shall be NULL */ | |
634 | *pstrtype = V_ASN1_NULL; | |
635 | return 1; | |
636 | case RSA_FLAG_TYPE_RSASSAPSS: | |
23b2fc0b | 637 | if (ossl_rsa_pss_params_30_is_unrestricted(pss)) { |
8ae40cf5 RL |
638 | *pstrtype = V_ASN1_UNDEF; |
639 | return 1; | |
640 | } else { | |
641 | ASN1_STRING *astr = NULL; | |
642 | WPACKET pkt; | |
643 | unsigned char *str = NULL; | |
644 | size_t str_sz = 0; | |
645 | int i; | |
646 | ||
647 | for (i = 0; i < 2; i++) { | |
648 | switch (i) { | |
649 | case 0: | |
650 | if (!WPACKET_init_null_der(&pkt)) | |
651 | goto err; | |
652 | break; | |
653 | case 1: | |
654 | if ((str = OPENSSL_malloc(str_sz)) == NULL | |
655 | || !WPACKET_init_der(&pkt, str, str_sz)) { | |
656 | goto err; | |
657 | } | |
658 | break; | |
659 | } | |
a55b00bd | 660 | if (!ossl_DER_w_RSASSA_PSS_params(&pkt, -1, pss) |
8ae40cf5 RL |
661 | || !WPACKET_finish(&pkt) |
662 | || !WPACKET_get_total_written(&pkt, &str_sz)) | |
663 | goto err; | |
664 | WPACKET_cleanup(&pkt); | |
665 | ||
666 | /* | |
667 | * If no PSS parameters are going to be written, there's no | |
668 | * point going for another iteration. | |
669 | * This saves us from getting |str| allocated just to have it | |
670 | * immediately de-allocated. | |
671 | */ | |
672 | if (str_sz == 0) | |
673 | break; | |
674 | } | |
675 | ||
676 | if ((astr = ASN1_STRING_new()) == NULL) | |
677 | goto err; | |
678 | *pstrtype = V_ASN1_SEQUENCE; | |
679 | ASN1_STRING_set0(astr, str, (int)str_sz); | |
680 | *pstr = astr; | |
681 | ||
682 | return 1; | |
683 | err: | |
684 | OPENSSL_free(str); | |
685 | return 0; | |
686 | } | |
687 | } | |
688 | ||
689 | /* Currently unsupported RSA key type */ | |
690 | return 0; | |
691 | } | |
692 | ||
111dc4b0 RL |
693 | #define rsa_params_to_der_bio NULL |
694 | #define rsa_params_to_pem_bio NULL | |
695 | #define rsa_priv_to_der (i2d_of_void *)i2d_RSAPrivateKey | |
696 | #define rsa_pub_to_der (i2d_of_void *)i2d_RSAPublicKey | |
697 | ||
698 | static int rsa_check_key_type(const void *rsa, int expected_type) | |
699 | { | |
700 | switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) { | |
701 | case RSA_FLAG_TYPE_RSA: | |
702 | return expected_type == EVP_PKEY_RSA; | |
703 | case RSA_FLAG_TYPE_RSASSAPSS: | |
704 | return expected_type == EVP_PKEY_RSA_PSS; | |
705 | } | |
706 | ||
707 | /* Currently unsupported RSA key type */ | |
708 | return EVP_PKEY_NONE; | |
709 | } | |
710 | ||
711 | #define rsa_evp_type EVP_PKEY_RSA | |
712 | #define rsapss_evp_type EVP_PKEY_RSA_PSS | |
713 | #define rsa_input_type "RSA" | |
714 | #define rsapss_input_type "RSA-PSS" | |
8ae40cf5 RL |
715 | |
716 | /* ---------------------------------------------------------------------- */ | |
717 | ||
718 | static OSSL_FUNC_decoder_newctx_fn key2any_newctx; | |
719 | static OSSL_FUNC_decoder_freectx_fn key2any_freectx; | |
111dc4b0 | 720 | static OSSL_FUNC_decoder_gettable_params_fn key2any_gettable_params; |
8ae40cf5 RL |
721 | |
722 | static void *key2any_newctx(void *provctx) | |
723 | { | |
724 | struct key2any_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); | |
725 | ||
726 | if (ctx != NULL) | |
727 | ctx->provctx = provctx; | |
728 | ||
729 | return ctx; | |
730 | } | |
731 | ||
732 | static void key2any_freectx(void *vctx) | |
733 | { | |
734 | struct key2any_ctx_st *ctx = vctx; | |
735 | ||
736 | ossl_pw_clear_passphrase_data(&ctx->pwdata); | |
737 | EVP_CIPHER_free(ctx->cipher); | |
738 | OPENSSL_free(ctx); | |
739 | } | |
740 | ||
111dc4b0 RL |
741 | static const OSSL_PARAM *key2any_gettable_params(void *provctx) |
742 | { | |
743 | static const OSSL_PARAM gettables[] = { | |
744 | { OSSL_ENCODER_PARAM_OUTPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 }, | |
745 | OSSL_PARAM_END, | |
746 | }; | |
747 | ||
748 | return gettables; | |
749 | } | |
750 | ||
751 | static int key2any_get_params(OSSL_PARAM params[], const char *input_type, | |
752 | const char *output_type) | |
753 | { | |
754 | OSSL_PARAM *p; | |
755 | ||
756 | p = OSSL_PARAM_locate(params, OSSL_ENCODER_PARAM_INPUT_TYPE); | |
757 | if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, input_type)) | |
758 | return 0; | |
759 | ||
760 | p = OSSL_PARAM_locate(params, OSSL_ENCODER_PARAM_OUTPUT_TYPE); | |
761 | if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, output_type)) | |
762 | return 0; | |
763 | ||
764 | return 1; | |
765 | } | |
766 | ||
8ae40cf5 RL |
767 | static const OSSL_PARAM *key2any_settable_ctx_params(ossl_unused void *provctx) |
768 | { | |
769 | static const OSSL_PARAM settables[] = { | |
770 | OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_CIPHER, NULL, 0), | |
771 | OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES, NULL, 0), | |
772 | OSSL_PARAM_END, | |
773 | }; | |
774 | ||
775 | return settables; | |
776 | } | |
777 | ||
778 | static int key2any_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
779 | { | |
780 | struct key2any_ctx_st *ctx = vctx; | |
7d6766cb | 781 | OPENSSL_CTX *libctx = ossl_prov_ctx_get0_library_context(ctx->provctx); |
8ae40cf5 RL |
782 | const OSSL_PARAM *cipherp = |
783 | OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_CIPHER); | |
784 | const OSSL_PARAM *propsp = | |
785 | OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_PROPERTIES); | |
786 | ||
787 | if (cipherp != NULL) { | |
788 | const char *ciphername = NULL; | |
789 | const char *props = NULL; | |
790 | ||
791 | if (!OSSL_PARAM_get_utf8_string_ptr(cipherp, &ciphername)) | |
792 | return 0; | |
793 | if (propsp != NULL && !OSSL_PARAM_get_utf8_string_ptr(propsp, &props)) | |
794 | return 0; | |
795 | ||
796 | EVP_CIPHER_free(ctx->cipher); | |
797 | ctx->cipher_intent = ciphername != NULL; | |
798 | if (ciphername != NULL | |
799 | && ((ctx->cipher = | |
800 | EVP_CIPHER_fetch(libctx, ciphername, props)) == NULL)) | |
801 | return 0; | |
802 | } | |
803 | return 1; | |
804 | } | |
805 | ||
111dc4b0 | 806 | static int key2any_encode(struct key2any_ctx_st *ctx, OSSL_CORE_BIO *cout, |
8ae40cf5 | 807 | const void *key, int type, |
111dc4b0 RL |
808 | check_key_type_fn *checker, |
809 | key_to_der_fn *writer, | |
8ae40cf5 RL |
810 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg, |
811 | key_to_paramstring_fn *key2paramstring, | |
812 | i2d_of_void *key2der) | |
813 | { | |
8ae40cf5 RL |
814 | int ret = 0; |
815 | ||
111dc4b0 RL |
816 | if (key == NULL) { |
817 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); | |
818 | } else if (checker == NULL || checker(key, type)) { | |
819 | BIO *out = bio_new_from_core_bio(ctx->provctx, cout); | |
820 | ||
821 | if (out != NULL | |
822 | && writer != NULL | |
823 | && ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg)) | |
824 | ret = writer(out, key, type, key2paramstring, key2der, ctx); | |
8ae40cf5 | 825 | |
111dc4b0 RL |
826 | BIO_free(out); |
827 | } else { | |
828 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); | |
829 | } | |
8ae40cf5 RL |
830 | return ret; |
831 | } | |
832 | ||
111dc4b0 | 833 | static int key2any_encode_params(struct key2any_ctx_st *ctx, |
8ae40cf5 | 834 | OSSL_CORE_BIO *cout, |
111dc4b0 RL |
835 | const void *key, int type, |
836 | check_key_type_fn *checker, | |
8ae40cf5 RL |
837 | write_bio_of_void_fn *writer) |
838 | { | |
839 | int ret = 0; | |
8ae40cf5 | 840 | |
111dc4b0 RL |
841 | if (key == NULL) { |
842 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); | |
843 | } else if (checker == NULL || checker(key, type)) { | |
844 | BIO *out = bio_new_from_core_bio(ctx->provctx, cout); | |
845 | ||
846 | if (out != NULL && writer != NULL) | |
847 | ret = writer(out, key); | |
8ae40cf5 | 848 | |
111dc4b0 RL |
849 | BIO_free(out); |
850 | } else { | |
851 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); | |
852 | } | |
8ae40cf5 RL |
853 | |
854 | return ret; | |
855 | } | |
856 | ||
111dc4b0 RL |
857 | #define MAKE_ENCODER(impl, type, evp_type, output) \ |
858 | static OSSL_FUNC_encoder_get_params_fn \ | |
859 | impl##2##output##_get_params; \ | |
860 | static OSSL_FUNC_encoder_import_object_fn \ | |
861 | impl##2##output##_import_object; \ | |
862 | static OSSL_FUNC_encoder_free_object_fn \ | |
863 | impl##2##output##_free_object; \ | |
864 | static OSSL_FUNC_encoder_encode_fn impl##2##output##_encode; \ | |
865 | \ | |
866 | static int impl##2##output##_get_params(OSSL_PARAM params[]) \ | |
867 | { \ | |
868 | return key2any_get_params(params, impl##_input_type, \ | |
869 | output##_output_type); \ | |
870 | } \ | |
871 | static void * \ | |
872 | impl##2##output##_import_object(void *vctx, int selection, \ | |
873 | const OSSL_PARAM params[]) \ | |
874 | { \ | |
875 | struct key2any_ctx_st *ctx = vctx; \ | |
1be63951 | 876 | return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \ |
111dc4b0 RL |
877 | ctx->provctx, selection, params); \ |
878 | } \ | |
879 | static void impl##2##output##_free_object(void *key) \ | |
880 | { \ | |
1be63951 | 881 | ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \ |
111dc4b0 RL |
882 | } \ |
883 | static int \ | |
884 | impl##2##output##_encode(void *ctx, OSSL_CORE_BIO *cout, \ | |
885 | const void *key, \ | |
886 | const OSSL_PARAM key_abstract[], \ | |
887 | int selection, \ | |
888 | OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) \ | |
889 | { \ | |
890 | /* We don't deal with abstract objects */ \ | |
891 | if (key_abstract != NULL) { \ | |
892 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \ | |
893 | return 0; \ | |
894 | } \ | |
895 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) \ | |
896 | return key2any_encode(ctx, cout, key, impl##_evp_type, \ | |
897 | type##_check_key_type, \ | |
898 | key_to_##output##_pkcs8_bio, \ | |
899 | cb, cbarg, \ | |
900 | prepare_##type##_params, \ | |
901 | type##_priv_to_der); \ | |
902 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) \ | |
903 | return key2any_encode(ctx, cout, key, impl##_evp_type, \ | |
904 | type##_check_key_type, \ | |
905 | key_to_##output##_pubkey_bio, \ | |
906 | cb, cbarg, \ | |
907 | prepare_##type##_params, \ | |
908 | type##_pub_to_der); \ | |
909 | if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) \ | |
910 | return key2any_encode_params(ctx, cout, key, \ | |
911 | impl##_evp_type, \ | |
912 | type##_check_key_type, \ | |
913 | type##_params_to_##output##_bio); \ | |
914 | \ | |
915 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \ | |
916 | return 0; \ | |
917 | } \ | |
1be63951 | 918 | const OSSL_DISPATCH ossl_##impl##_to_##output##_encoder_functions[] = { \ |
111dc4b0 RL |
919 | { OSSL_FUNC_ENCODER_NEWCTX, \ |
920 | (void (*)(void))key2any_newctx }, \ | |
921 | { OSSL_FUNC_ENCODER_FREECTX, \ | |
922 | (void (*)(void))key2any_freectx }, \ | |
923 | { OSSL_FUNC_ENCODER_GETTABLE_PARAMS, \ | |
924 | (void (*)(void))key2any_gettable_params }, \ | |
925 | { OSSL_FUNC_ENCODER_GET_PARAMS, \ | |
926 | (void (*)(void))impl##2##output##_get_params }, \ | |
927 | { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \ | |
928 | (void (*)(void))key2any_settable_ctx_params }, \ | |
929 | { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \ | |
930 | (void (*)(void))key2any_set_ctx_params }, \ | |
931 | { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \ | |
932 | (void (*)(void))impl##2##output##_import_object }, \ | |
933 | { OSSL_FUNC_ENCODER_FREE_OBJECT, \ | |
934 | (void (*)(void))impl##2##output##_free_object }, \ | |
935 | { OSSL_FUNC_ENCODER_ENCODE, \ | |
936 | (void (*)(void))impl##2##output##_encode }, \ | |
937 | { 0, NULL } \ | |
8ae40cf5 RL |
938 | } |
939 | ||
8ae40cf5 RL |
940 | #ifndef OPENSSL_NO_DH |
941 | MAKE_ENCODER(dh, dh, EVP_PKEY_DH, der); | |
942 | MAKE_ENCODER(dh, dh, EVP_PKEY_DH, pem); | |
111dc4b0 RL |
943 | MAKE_ENCODER(dhx, dh, EVP_PKEY_DH, der); |
944 | MAKE_ENCODER(dhx, dh, EVP_PKEY_DH, pem); | |
8ae40cf5 RL |
945 | #endif |
946 | #ifndef OPENSSL_NO_DSA | |
947 | MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, der); | |
948 | MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, pem); | |
949 | #endif | |
950 | #ifndef OPENSSL_NO_EC | |
951 | MAKE_ENCODER(ec, ec, EVP_PKEY_EC, der); | |
952 | MAKE_ENCODER(ec, ec, EVP_PKEY_EC, pem); | |
111dc4b0 RL |
953 | MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, der); |
954 | MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, pem); | |
955 | MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, der); | |
956 | MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, pem); | |
957 | MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, der); | |
958 | MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, pem); | |
959 | MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, der); | |
960 | MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, pem); | |
8ae40cf5 | 961 | #endif |
111dc4b0 RL |
962 | MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, der); |
963 | MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, pem); | |
964 | MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA, der); | |
965 | MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA, pem); |