2 * Copyright 2020-2021 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
= ossl_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
)
55 OSSL_LIB_CTX
*libctx
= PROV_LIBCTX_OF(ctx
->provctx
);
57 out
= ossl_bio_new_from_core_bio(ctx
->provctx
, cout
);
58 ret
= i2b_PVK_bio_ex(out
, pkey
, ctx
->pvk_encr_level
,
59 ossl_pw_pem_password
, &ctx
->pwdata
, libctx
, NULL
);
65 static OSSL_FUNC_encoder_freectx_fn key2ms_freectx
;
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
*key2pvk_settable_ctx_params(ossl_unused
void *provctx
)
89 static const OSSL_PARAM settables
[] = {
90 OSSL_PARAM_int(OSSL_ENCODER_PARAM_ENCRYPT_LEVEL
, NULL
),
97 static int key2pvk_set_ctx_params(void *vctx
, const OSSL_PARAM params
[])
99 struct key2ms_ctx_st
*ctx
= vctx
;
102 p
= OSSL_PARAM_locate_const(params
, OSSL_ENCODER_PARAM_ENCRYPT_LEVEL
);
103 if (p
!= NULL
&& !OSSL_PARAM_get_int(p
, &ctx
->pvk_encr_level
))
108 static int key2ms_does_selection(void *vctx
, int selection
)
110 return (selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) != 0;
114 * The real EVP_PKEY_set1_TYPE() functions take a non-const key, while the key
115 * pointer in the encode function is a const pointer. We violate the constness
116 * knowingly, since we know that the key comes from the same provider, is never
117 * actually const, and the implied reference count change is safe.
119 * EVP_PKEY_assign() can't be used, because there's no way to clear the internal
120 * key using that function without freeing the existing internal key.
122 typedef int evp_pkey_set1_fn(EVP_PKEY
*, const void *key
);
124 static int key2msblob_encode(void *vctx
, const void *key
, int selection
,
125 OSSL_CORE_BIO
*cout
, evp_pkey_set1_fn
*set1_key
,
126 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
128 struct key2ms_ctx_st
*ctx
= vctx
;
130 EVP_PKEY
*pkey
= NULL
;
133 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0)
135 else if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0)
138 return 0; /* Error */
140 if ((pkey
= EVP_PKEY_new()) != NULL
&& set1_key(pkey
, key
))
141 ok
= write_msblob(ctx
, cout
, pkey
, ispub
);
146 static int key2pvk_encode(void *vctx
, const void *key
, int selection
,
147 OSSL_CORE_BIO
*cout
, evp_pkey_set1_fn
*set1_key
,
148 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
150 struct key2ms_ctx_st
*ctx
= vctx
;
151 EVP_PKEY
*pkey
= NULL
;
154 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) == 0)
155 return 0; /* Error */
157 if ((pkey
= EVP_PKEY_new()) != NULL
&& set1_key(pkey
, key
))
158 ok
= write_pvk(ctx
, cout
, pkey
, pw_cb
, pw_cbarg
);
163 #define dsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_DSA
164 #define rsa_set1 (evp_pkey_set1_fn *)EVP_PKEY_set1_RSA
166 #define msblob_set_params
167 #define pvk_set_params \
168 { OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS, \
169 (void (*)(void))key2pvk_settable_ctx_params }, \
170 { OSSL_FUNC_ENCODER_SET_CTX_PARAMS, \
171 (void (*)(void))key2pvk_set_ctx_params },
173 #define MAKE_MS_ENCODER(impl, output, type) \
174 static OSSL_FUNC_encoder_import_object_fn \
175 impl##2##output##_import_object; \
176 static OSSL_FUNC_encoder_free_object_fn impl##2##output##_free_object; \
177 static OSSL_FUNC_encoder_encode_fn impl##2##output##_encode; \
180 impl##2##output##_import_object(void *ctx, int selection, \
181 const OSSL_PARAM params[]) \
183 return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
184 ctx, selection, params); \
186 static void impl##2##output##_free_object(void *key) \
188 ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
190 static int impl##2##output##_encode(void *vctx, OSSL_CORE_BIO *cout, \
192 const OSSL_PARAM key_abstract[], \
194 OSSL_PASSPHRASE_CALLBACK *cb, \
197 /* We don't deal with abstract objects */ \
198 if (key_abstract != NULL) { \
199 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
202 return key2##output##_encode(vctx, key, selection, cout, type##_set1, \
205 const OSSL_DISPATCH ossl_##impl##_to_##output##_encoder_functions[] = { \
206 { OSSL_FUNC_ENCODER_NEWCTX, \
207 (void (*)(void))key2ms_newctx }, \
208 { OSSL_FUNC_ENCODER_FREECTX, \
209 (void (*)(void))key2ms_freectx }, \
210 output##_set_params \
211 { OSSL_FUNC_ENCODER_DOES_SELECTION, \
212 (void (*)(void))key2ms_does_selection }, \
213 { OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
214 (void (*)(void))impl##2##output##_import_object }, \
215 { OSSL_FUNC_ENCODER_FREE_OBJECT, \
216 (void (*)(void))impl##2##output##_free_object }, \
217 { OSSL_FUNC_ENCODER_ENCODE, \
218 (void (*)(void))impl##2##output##_encode }, \
222 #ifndef OPENSSL_NO_DSA
223 MAKE_MS_ENCODER(dsa
, pvk
, dsa
);
224 MAKE_MS_ENCODER(dsa
, msblob
, dsa
);
227 MAKE_MS_ENCODER(rsa
, pvk
, rsa
);
228 MAKE_MS_ENCODER(rsa
, msblob
, rsa
);