1e4520c8bSEnji Cooper /*
229536654SEnji Cooper * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3e4520c8bSEnji Cooper *
4e4520c8bSEnji Cooper * Licensed under the Apache License 2.0 (the "License"). You may not use
5e4520c8bSEnji Cooper * this file except in compliance with the License. You can obtain a copy
6e4520c8bSEnji Cooper * in the file LICENSE in the source distribution or at
7e4520c8bSEnji Cooper * https://www.openssl.org/source/license.html
8e4520c8bSEnji Cooper */
9e4520c8bSEnji Cooper
10e4520c8bSEnji Cooper /*
11e4520c8bSEnji Cooper * Low level APIs are deprecated for public use, but still ok for internal use.
12e4520c8bSEnji Cooper */
13e4520c8bSEnji Cooper #include "internal/deprecated.h"
14e4520c8bSEnji Cooper
15e4520c8bSEnji Cooper #include <string.h>
16e4520c8bSEnji Cooper #include <openssl/core.h>
17e4520c8bSEnji Cooper #include <openssl/core_dispatch.h>
18e4520c8bSEnji Cooper #include <openssl/core_names.h>
19e4520c8bSEnji Cooper #include <openssl/params.h>
20e4520c8bSEnji Cooper #include <openssl/err.h>
21e4520c8bSEnji Cooper #include <openssl/pem.h> /* Functions for writing MSBLOB and PVK */
22e4520c8bSEnji Cooper #include <openssl/dsa.h>
23e4520c8bSEnji Cooper #include "internal/passphrase.h"
24e4520c8bSEnji Cooper #include "crypto/rsa.h"
25e4520c8bSEnji Cooper #include "prov/implementations.h"
26e4520c8bSEnji Cooper #include "prov/bio.h"
27e4520c8bSEnji Cooper #include "prov/provider_ctx.h"
28e4520c8bSEnji Cooper #include "endecoder_local.h"
29e4520c8bSEnji Cooper
30e4520c8bSEnji Cooper struct key2ms_ctx_st {
31e4520c8bSEnji Cooper PROV_CTX *provctx;
32e4520c8bSEnji Cooper
33e4520c8bSEnji Cooper int pvk_encr_level;
34e4520c8bSEnji Cooper
35e4520c8bSEnji Cooper struct ossl_passphrase_data_st pwdata;
36e4520c8bSEnji Cooper };
37e4520c8bSEnji Cooper
write_msblob(struct key2ms_ctx_st * ctx,OSSL_CORE_BIO * cout,EVP_PKEY * pkey,int ispub)38e4520c8bSEnji Cooper static int write_msblob(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout,
39e4520c8bSEnji Cooper EVP_PKEY *pkey, int ispub)
40e4520c8bSEnji Cooper {
41e4520c8bSEnji Cooper BIO *out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
42e4520c8bSEnji Cooper int ret;
43e4520c8bSEnji Cooper
44e4520c8bSEnji Cooper if (out == NULL)
45e4520c8bSEnji Cooper return 0;
46e4520c8bSEnji Cooper ret = ispub ? i2b_PublicKey_bio(out, pkey) : i2b_PrivateKey_bio(out, pkey);
47e4520c8bSEnji Cooper
48e4520c8bSEnji Cooper BIO_free(out);
49e4520c8bSEnji Cooper return ret;
50e4520c8bSEnji Cooper }
51e4520c8bSEnji Cooper
write_pvk(struct key2ms_ctx_st * ctx,OSSL_CORE_BIO * cout,EVP_PKEY * pkey)52e4520c8bSEnji Cooper static int write_pvk(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout,
53e4520c8bSEnji Cooper EVP_PKEY *pkey)
54e4520c8bSEnji Cooper {
55e4520c8bSEnji Cooper BIO *out = NULL;
56e4520c8bSEnji Cooper int ret;
57e4520c8bSEnji Cooper OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
58e4520c8bSEnji Cooper
59e4520c8bSEnji Cooper out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
60e4520c8bSEnji Cooper if (out == NULL)
61e4520c8bSEnji Cooper return 0;
62e4520c8bSEnji Cooper ret = i2b_PVK_bio_ex(out, pkey, ctx->pvk_encr_level,
63e4520c8bSEnji Cooper ossl_pw_pvk_password, &ctx->pwdata, libctx, NULL);
64e4520c8bSEnji Cooper BIO_free(out);
65e4520c8bSEnji Cooper return ret;
66e4520c8bSEnji Cooper }
67e4520c8bSEnji Cooper
68e4520c8bSEnji Cooper static OSSL_FUNC_encoder_freectx_fn key2ms_freectx;
69e4520c8bSEnji Cooper static OSSL_FUNC_encoder_does_selection_fn key2ms_does_selection;
70e4520c8bSEnji Cooper
key2ms_newctx(void * provctx)71e4520c8bSEnji Cooper static struct key2ms_ctx_st *key2ms_newctx(void *provctx)
72e4520c8bSEnji Cooper {
73e4520c8bSEnji Cooper struct key2ms_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
74e4520c8bSEnji Cooper
75e4520c8bSEnji Cooper if (ctx != NULL) {
76e4520c8bSEnji Cooper ctx->provctx = provctx;
77e4520c8bSEnji Cooper /* This is the strongest encryption level */
78e4520c8bSEnji Cooper ctx->pvk_encr_level = 2;
79e4520c8bSEnji Cooper }
80e4520c8bSEnji Cooper return ctx;
81e4520c8bSEnji Cooper }
82e4520c8bSEnji Cooper
key2ms_freectx(void * vctx)83e4520c8bSEnji Cooper static void key2ms_freectx(void *vctx)
84e4520c8bSEnji Cooper {
85e4520c8bSEnji Cooper struct key2ms_ctx_st *ctx = vctx;
86e4520c8bSEnji Cooper
87e4520c8bSEnji Cooper ossl_pw_clear_passphrase_data(&ctx->pwdata);
88e4520c8bSEnji Cooper OPENSSL_free(ctx);
89e4520c8bSEnji Cooper }
90e4520c8bSEnji Cooper
key2pvk_settable_ctx_params(ossl_unused void * provctx)91e4520c8bSEnji Cooper static const OSSL_PARAM *key2pvk_settable_ctx_params(ossl_unused void *provctx)
92e4520c8bSEnji Cooper {
93e4520c8bSEnji Cooper static const OSSL_PARAM settables[] = {
94e4520c8bSEnji Cooper OSSL_PARAM_int(OSSL_ENCODER_PARAM_ENCRYPT_LEVEL, NULL),
95e4520c8bSEnji Cooper OSSL_PARAM_END,
96e4520c8bSEnji Cooper };
97e4520c8bSEnji Cooper
98e4520c8bSEnji Cooper return settables;
99e4520c8bSEnji Cooper }
100e4520c8bSEnji Cooper
key2pvk_set_ctx_params(void * vctx,const OSSL_PARAM params[])101e4520c8bSEnji Cooper static int key2pvk_set_ctx_params(void *vctx, const OSSL_PARAM params[])
102e4520c8bSEnji Cooper {
103e4520c8bSEnji Cooper struct key2ms_ctx_st *ctx = vctx;
104e4520c8bSEnji Cooper const OSSL_PARAM *p;
105e4520c8bSEnji Cooper
106e4520c8bSEnji Cooper p = OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_ENCRYPT_LEVEL);
107e4520c8bSEnji Cooper if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->pvk_encr_level))
108e4520c8bSEnji Cooper return 0;
109e4520c8bSEnji Cooper return 1;
110e4520c8bSEnji Cooper }
111e4520c8bSEnji Cooper
key2ms_does_selection(void * vctx,int selection)112e4520c8bSEnji Cooper static int key2ms_does_selection(void *vctx, int selection)
113e4520c8bSEnji Cooper {
114e4520c8bSEnji Cooper return (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0;
115e4520c8bSEnji Cooper }
116e4520c8bSEnji Cooper
117e4520c8bSEnji Cooper /*
118e4520c8bSEnji Cooper * The real EVP_PKEY_set1_TYPE() functions take a non-const key, while the key
119e4520c8bSEnji Cooper * pointer in the encode function is a const pointer. We violate the constness
120e4520c8bSEnji Cooper * knowingly, since we know that the key comes from the same provider, is never
121e4520c8bSEnji Cooper * actually const, and the implied reference count change is safe.
122e4520c8bSEnji Cooper *
123e4520c8bSEnji Cooper * EVP_PKEY_assign() can't be used, because there's no way to clear the internal
124e4520c8bSEnji Cooper * key using that function without freeing the existing internal key.
125e4520c8bSEnji Cooper */
126e4520c8bSEnji Cooper typedef int evp_pkey_set1_fn(EVP_PKEY *, const void *key);
127e4520c8bSEnji Cooper
key2msblob_encode(void * vctx,const void * key,int selection,OSSL_CORE_BIO * cout,evp_pkey_set1_fn * set1_key,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)128e4520c8bSEnji Cooper static int key2msblob_encode(void *vctx, const void *key, int selection,
129e4520c8bSEnji Cooper OSSL_CORE_BIO *cout, evp_pkey_set1_fn *set1_key,
130e4520c8bSEnji Cooper OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
131e4520c8bSEnji Cooper {
132e4520c8bSEnji Cooper struct key2ms_ctx_st *ctx = vctx;
133e4520c8bSEnji Cooper int ispub = -1;
134e4520c8bSEnji Cooper EVP_PKEY *pkey = NULL;
135e4520c8bSEnji Cooper int ok = 0;
136e4520c8bSEnji Cooper
137e4520c8bSEnji Cooper if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
138e4520c8bSEnji Cooper ispub = 0;
139e4520c8bSEnji Cooper else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
140e4520c8bSEnji Cooper ispub = 1;
141e4520c8bSEnji Cooper else
142e4520c8bSEnji Cooper return 0; /* Error */
143e4520c8bSEnji Cooper
144e4520c8bSEnji Cooper if ((pkey = EVP_PKEY_new()) != NULL && set1_key(pkey, key))
145e4520c8bSEnji Cooper ok = write_msblob(ctx, cout, pkey, ispub);
146e4520c8bSEnji Cooper EVP_PKEY_free(pkey);
147e4520c8bSEnji Cooper return ok;
148e4520c8bSEnji Cooper }
149e4520c8bSEnji Cooper
key2pvk_encode(void * vctx,const void * key,int selection,OSSL_CORE_BIO * cout,evp_pkey_set1_fn * set1_key,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)150e4520c8bSEnji Cooper static int key2pvk_encode(void *vctx, const void *key, int selection,
151e4520c8bSEnji Cooper OSSL_CORE_BIO *cout, evp_pkey_set1_fn *set1_key,
152e4520c8bSEnji Cooper OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
153e4520c8bSEnji Cooper {
154e4520c8bSEnji Cooper struct key2ms_ctx_st *ctx = vctx;
155e4520c8bSEnji Cooper EVP_PKEY *pkey = NULL;
156e4520c8bSEnji Cooper int ok = 0;
157e4520c8bSEnji Cooper
158e4520c8bSEnji Cooper if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0)
159e4520c8bSEnji Cooper return 0; /* Error */
160e4520c8bSEnji Cooper
161e4520c8bSEnji Cooper if ((pkey = EVP_PKEY_new()) != NULL && set1_key(pkey, key)
162e4520c8bSEnji Cooper && (pw_cb == NULL
163e4520c8bSEnji Cooper || ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, pw_cb, pw_cbarg)))
164e4520c8bSEnji Cooper ok = write_pvk(ctx, cout, pkey);
165e4520c8bSEnji Cooper EVP_PKEY_free(pkey);
166e4520c8bSEnji Cooper return ok;
167e4520c8bSEnji Cooper }
168e4520c8bSEnji Cooper
169e4520c8bSEnji Cooper #define dsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_DSA
170e4520c8bSEnji Cooper #define rsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_RSA
171e4520c8bSEnji Cooper
172e4520c8bSEnji Cooper #define msblob_set_params
173e4520c8bSEnji Cooper #define pvk_set_params \
174e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \
175e4520c8bSEnji Cooper (void (*)(void))key2pvk_settable_ctx_params }, \
176e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \
177e4520c8bSEnji Cooper (void (*)(void))key2pvk_set_ctx_params },
178e4520c8bSEnji Cooper
179e4520c8bSEnji Cooper #define MAKE_MS_ENCODER(impl, output, type) \
180e4520c8bSEnji Cooper static OSSL_FUNC_encoder_import_object_fn \
181e4520c8bSEnji Cooper impl##2##output##_import_object; \
182e4520c8bSEnji Cooper static OSSL_FUNC_encoder_free_object_fn impl##2##output##_free_object; \
183e4520c8bSEnji Cooper static OSSL_FUNC_encoder_encode_fn impl##2##output##_encode; \
184e4520c8bSEnji Cooper \
185e4520c8bSEnji Cooper static void * \
186e4520c8bSEnji Cooper impl##2##output##_import_object(void *ctx, int selection, \
187e4520c8bSEnji Cooper const OSSL_PARAM params[]) \
188e4520c8bSEnji Cooper { \
189e4520c8bSEnji Cooper return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
190e4520c8bSEnji Cooper ctx, selection, params); \
191e4520c8bSEnji Cooper } \
192e4520c8bSEnji Cooper static void impl##2##output##_free_object(void *key) \
193e4520c8bSEnji Cooper { \
194e4520c8bSEnji Cooper ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
195e4520c8bSEnji Cooper } \
196e4520c8bSEnji Cooper static int impl##2##output##_encode(void *vctx, OSSL_CORE_BIO *cout, \
197e4520c8bSEnji Cooper const void *key, \
198e4520c8bSEnji Cooper const OSSL_PARAM key_abstract[], \
199e4520c8bSEnji Cooper int selection, \
200e4520c8bSEnji Cooper OSSL_PASSPHRASE_CALLBACK *cb, \
201e4520c8bSEnji Cooper void *cbarg) \
202e4520c8bSEnji Cooper { \
203e4520c8bSEnji Cooper /* We don't deal with abstract objects */ \
204e4520c8bSEnji Cooper if (key_abstract != NULL) { \
205e4520c8bSEnji Cooper ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
206e4520c8bSEnji Cooper return 0; \
207e4520c8bSEnji Cooper } \
208e4520c8bSEnji Cooper return key2##output##_encode(vctx, key, selection, cout, type##_set1, \
209e4520c8bSEnji Cooper cb, cbarg); \
210e4520c8bSEnji Cooper } \
211e4520c8bSEnji Cooper const OSSL_DISPATCH ossl_##impl##_to_##output##_encoder_functions[] = { \
212e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_NEWCTX, \
213e4520c8bSEnji Cooper (void (*)(void))key2ms_newctx }, \
214e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_FREECTX, \
215e4520c8bSEnji Cooper (void (*)(void))key2ms_freectx }, \
216808413daSEnji Cooper output##_set_params { OSSL_FUNC_ENCODER_DOES_SELECTION, \
217e4520c8bSEnji Cooper (void (*)(void))key2ms_does_selection }, \
218e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
219e4520c8bSEnji Cooper (void (*)(void))impl##2##output##_import_object }, \
220e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_FREE_OBJECT, \
221e4520c8bSEnji Cooper (void (*)(void))impl##2##output##_free_object }, \
222e4520c8bSEnji Cooper { OSSL_FUNC_ENCODER_ENCODE, \
223e4520c8bSEnji Cooper (void (*)(void))impl##2##output##_encode }, \
22429536654SEnji Cooper OSSL_DISPATCH_END \
225e4520c8bSEnji Cooper }
226e4520c8bSEnji Cooper
227e4520c8bSEnji Cooper #ifndef OPENSSL_NO_DSA
228e4520c8bSEnji Cooper MAKE_MS_ENCODER(dsa, pvk, dsa);
229e4520c8bSEnji Cooper MAKE_MS_ENCODER(dsa, msblob, dsa);
230e4520c8bSEnji Cooper #endif
231e4520c8bSEnji Cooper
232e4520c8bSEnji Cooper MAKE_MS_ENCODER(rsa, pvk, rsa);
233e4520c8bSEnji Cooper MAKE_MS_ENCODER(rsa, msblob, rsa);
234