xref: /src/crypto/openssl/providers/implementations/encode_decode/encode_key2ms.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
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