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