2 * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
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
11 * Low level APIs are deprecated for public use, but still ok for internal use.
13 #include "internal/deprecated.h"
16 #include <openssl/core.h>
17 #include <openssl/core_dispatch.h>
18 #include <openssl/core_names.h>
19 #include <openssl/params.h>
20 #include <openssl/err.h>
21 #include <openssl/pem.h> /* Functions for writing MSBLOB and PVK */
22 #include <openssl/dsa.h>
23 #include "internal/passphrase.h"
24 #include "crypto/rsa.h"
25 #include "prov/implementations.h"
27 #include "prov/provider_ctx.h"
28 #include "endecoder_local.h"
30 struct key2ms_ctx_st
{
35 struct ossl_passphrase_data_st pwdata
;
38 static int write_msblob(struct key2ms_ctx_st
*ctx
, OSSL_CORE_BIO
*cout
,
39 EVP_PKEY
*pkey
, int ispub
)
41 BIO
*out
= bio_new_from_core_bio(ctx
->provctx
, cout
);
43 ispub
? i2b_PublicKey_bio(out
, pkey
) : i2b_PrivateKey_bio(out
, pkey
);
49 static int write_pvk(struct key2ms_ctx_st
*ctx
, OSSL_CORE_BIO
*cout
,
51 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
56 out
= bio_new_from_core_bio(ctx
->provctx
, cout
);
57 ret
= i2b_PVK_bio(out
, pkey
, ctx
->pvk_encr_level
,
58 ossl_pw_pem_password
, &ctx
->pwdata
);
64 static OSSL_FUNC_encoder_freectx_fn key2ms_freectx
;
65 static OSSL_FUNC_encoder_gettable_params_fn key2ms_gettable_params
;
66 static OSSL_FUNC_encoder_does_selection_fn key2ms_does_selection
;
68 static struct key2ms_ctx_st
*key2ms_newctx(void *provctx
)
70 struct key2ms_ctx_st
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
73 ctx
->provctx
= provctx
;
74 /* This is the strongest encryption level */
75 ctx
->pvk_encr_level
= 2;
80 static void key2ms_freectx(void *vctx
)
82 struct key2ms_ctx_st
*ctx
= vctx
;
87 static const OSSL_PARAM
*key2ms_gettable_params(ossl_unused
void *provctx
)
89 static const OSSL_PARAM gettables
[] = {
90 { OSSL_ENCODER_PARAM_OUTPUT_TYPE
, OSSL_PARAM_UTF8_PTR
, NULL
, 0, 0 },
97 static int key2msblob_get_params(OSSL_PARAM params
[])
101 p
= OSSL_PARAM_locate(params
, OSSL_ENCODER_PARAM_OUTPUT_TYPE
);
102 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, "MSBLOB"))
108 static int key2pvk_get_params(OSSL_PARAM params
[])
112 p
= OSSL_PARAM_locate(params
, OSSL_ENCODER_PARAM_OUTPUT_TYPE
);
113 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, "PVK"))
119 static const OSSL_PARAM
*key2pvk_settable_ctx_params(ossl_unused
void *provctx
)
121 static const OSSL_PARAM settables
[] = {
122 OSSL_PARAM_int(OSSL_ENCODER_PARAM_ENCRYPT_LEVEL
, NULL
),
129 static int key2pvk_set_ctx_params(void *vctx
, const OSSL_PARAM params
[])
131 struct key2ms_ctx_st
*ctx
= vctx
;
134 p
= OSSL_PARAM_locate_const(params
, OSSL_ENCODER_PARAM_ENCRYPT_LEVEL
);
135 if (p
!= NULL
&& !OSSL_PARAM_get_int(p
, &ctx
->pvk_encr_level
))
140 static int key2ms_does_selection(void *vctx
, int selection
)
142 return (selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) != 0;
146 * The real EVP_PKEY_set1_TYPE() functions take a non-const key, while the key
147 * pointer in the encode function is a const pointer. We violate the constness
148 * knowingly, since we know that the key comes from the same provider, is never
149 * actually const, and the implied reference count change is safe.
151 * EVP_PKEY_assign() can't be used, because there's no way to clear the internal
152 * key using that function without freeing the existing internal key.
154 typedef int evp_pkey_set1_fn(EVP_PKEY
*, const void *key
);
156 static int key2msblob_encode(void *vctx
, const void *key
, int selection
,
157 OSSL_CORE_BIO
*cout
, evp_pkey_set1_fn
*set1_key
,
158 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
160 struct key2ms_ctx_st
*ctx
= vctx
;
162 EVP_PKEY
*pkey
= NULL
;
165 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0)
167 else if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0)
170 return 0; /* Error */
172 if ((pkey
= EVP_PKEY_new()) != NULL
&& set1_key(pkey
, key
))
173 ok
= write_msblob(ctx
, cout
, pkey
, ispub
);
178 static int key2pvk_encode(void *vctx
, const void *key
, int selection
,
179 OSSL_CORE_BIO
*cout
, evp_pkey_set1_fn
*set1_key
,
180 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
182 struct key2ms_ctx_st
*ctx
= vctx
;
183 EVP_PKEY
*pkey
= NULL
;
186 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) == 0)
187 return 0; /* Error */
189 if ((pkey
= EVP_PKEY_new()) != NULL
&& set1_key(pkey
, key
))
190 ok
= write_pvk(ctx
, cout
, pkey
, pw_cb
, pw_cbarg
);
195 #define dsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_DSA
196 #define rsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_RSA
198 #define msblob_set_params
199 #define pvk_set_params \
200 { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \
201 (void (*)(void))key2pvk_settable_ctx_params }, \
202 { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \
203 (void (*)(void))key2pvk_set_ctx_params },
205 #define MAKE_MS_ENCODER(impl, output, type) \
206 static OSSL_FUNC_encoder_import_object_fn \
207 impl##2##output##_import_object; \
208 static OSSL_FUNC_encoder_free_object_fn impl##2##output##_free_object; \
209 static OSSL_FUNC_encoder_encode_fn impl##2##output##_encode; \
212 impl##2##output##_import_object(void *ctx, int selection, \
213 const OSSL_PARAM params[]) \
215 return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
216 ctx, selection, params); \
218 static void impl##2##output##_free_object(void *key) \
220 ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
222 static int impl##2##output##_encode(void *vctx, OSSL_CORE_BIO *cout, \
224 const OSSL_PARAM key_abstract[], \
226 OSSL_PASSPHRASE_CALLBACK *cb, \
229 /* We don't deal with abstract objects */ \
230 if (key_abstract != NULL) { \
231 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
234 return key2##output##_encode(vctx, key, selection, cout, type##_set1, \
237 const OSSL_DISPATCH ossl_##impl##_to_##output##_encoder_functions[] = { \
238 { OSSL_FUNC_ENCODER_NEWCTX, \
239 (void (*)(void))key2ms_newctx }, \
240 { OSSL_FUNC_ENCODER_FREECTX, \
241 (void (*)(void))key2ms_freectx }, \
242 { OSSL_FUNC_ENCODER_GETTABLE_PARAMS, \
243 (void (*)(void))key2ms_gettable_params }, \
244 { OSSL_FUNC_ENCODER_GET_PARAMS, \
245 (void (*)(void))key2##output##_get_params }, \
246 output##_set_params \
247 { OSSL_FUNC_ENCODER_DOES_SELECTION, \
248 (void (*)(void))key2ms_does_selection }, \
249 { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
250 (void (*)(void))impl##2##output##_import_object }, \
251 { OSSL_FUNC_ENCODER_FREE_OBJECT, \
252 (void (*)(void))impl##2##output##_free_object }, \
253 { OSSL_FUNC_ENCODER_ENCODE, \
254 (void (*)(void))impl##2##output##_encode }, \
258 #ifndef OPENSSL_NO_DSA
259 MAKE_MS_ENCODER(dsa
, pvk
, dsa
);
260 MAKE_MS_ENCODER(dsa
, msblob
, dsa
);
263 MAKE_MS_ENCODER(rsa
, pvk
, rsa
);
264 MAKE_MS_ENCODER(rsa
, msblob
, rsa
);