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
14 #include "internal/deprecated.h"
16 #include <openssl/core_dispatch.h>
17 #include <openssl/core_names.h>
18 #include <openssl/crypto.h>
19 #include <openssl/params.h>
20 #include <openssl/x509.h>
21 #include "internal/pem.h" /* For PVK and "blob" PEM headers */
23 #include "prov/implementations.h"
24 #include "serializer_local.h"
26 static OSSL_FUNC_deserializer_freectx_fn ms2key_freectx;
27 static OSSL_FUNC_deserializer_gettable_params_fn ms2key_gettable_params;
28 static OSSL_FUNC_deserializer_get_params_fn msblob2key_get_params;
29 #ifndef OPENSSL_NO_RC4
30 static OSSL_FUNC_deserializer_get_params_fn pvk2key_get_params;
32 static OSSL_FUNC_deserializer_deserialize_fn msblob2key_deserialize;
33 #ifndef OPENSSL_NO_RC4
34 static OSSL_FUNC_deserializer_deserialize_fn pvk2key_deserialize;
36 static OSSL_FUNC_deserializer_export_object_fn ms2key_export_object;
38 typedef void *(extract_key_fn)(EVP_PKEY *);
39 typedef void (free_key_fn)(void *);
40 struct keytype_desc_st {
41 int type; /* EVP key type */
42 const char *name; /* Keytype */
43 const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
46 * These must be the correct EVP_PKEY_get1_{TYPE}() and {TYPE}_free()
47 * function for the key.
49 extract_key_fn *extract_key;
50 free_key_fn *free_key;
54 * Context used for DER to key deserialization.
56 struct ms2key_ctx_st {
58 const struct keytype_desc_st *desc;
61 static struct ms2key_ctx_st *
62 ms2key_newctx(void *provctx, const struct keytype_desc_st *desc)
64 struct ms2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
67 ctx->provctx = provctx;
73 static void ms2key_freectx(void *vctx)
75 struct ms2key_ctx_st *ctx = vctx;
80 static const OSSL_PARAM *ms2key_gettable_params(ossl_unused void *provctx)
82 static const OSSL_PARAM gettables[] = {
83 { OSSL_DESERIALIZER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 },
90 static int msblob2key_get_params(OSSL_PARAM params[])
94 p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
95 if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "MSBLOB"))
101 #ifndef OPENSSL_NO_RC4
102 static int pvk2key_get_params(OSSL_PARAM params[])
106 p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
107 if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "PVK"))
114 static int ms2key_post(struct ms2key_ctx_st *ctx, EVP_PKEY *pkey,
115 OSSL_CALLBACK *data_cb, void *data_cbarg)
122 * Tear out the low-level key pointer from the pkey,
123 * but only if it matches the expected key type.
125 * TODO(3.0): The check should be done with EVP_PKEY_is_a(), but
126 * as long as we still have #legacy internal keys, it's safer to
127 * use the type numbers in side the provider.
129 if (EVP_PKEY_id(pkey) == ctx->desc->type)
130 key = ctx->desc->extract_key(pkey);
134 OSSL_PARAM params[3];
137 OSSL_PARAM_construct_utf8_string(OSSL_DESERIALIZER_PARAM_DATA_TYPE,
138 (char *)ctx->desc->name, 0);
139 /* The address of the key becomes the octet string */
141 OSSL_PARAM_construct_octet_string(OSSL_DESERIALIZER_PARAM_REFERENCE,
143 params[2] = OSSL_PARAM_construct_end();
145 ok = data_cb(params, data_cbarg);
147 ctx->desc->free_key(key);
152 static int msblob2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
153 OSSL_CALLBACK *data_cb, void *data_cbarg,
154 OSSL_PASSPHRASE_CALLBACK *pw_cb,
157 struct ms2key_ctx_st *ctx = vctx;
159 EVP_PKEY *pkey = ossl_prov_read_msblob(ctx->provctx, cin, &ispub);
160 int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
166 #ifndef OPENSSL_NO_RC4
167 static int pvk2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
168 OSSL_CALLBACK *data_cb, void *data_cbarg,
169 OSSL_PASSPHRASE_CALLBACK *pw_cb,
172 struct ms2key_ctx_st *ctx = vctx;
173 EVP_PKEY *pkey = ossl_prov_read_pvk(ctx->provctx, cin, pw_cb, pw_cbarg);
174 int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
181 static int ms2key_export_object(void *vctx,
182 const void *reference, size_t reference_sz,
183 OSSL_CALLBACK *export_cb, void *export_cbarg)
185 struct ms2key_ctx_st *ctx = vctx;
186 OSSL_FUNC_keymgmt_export_fn *export =
187 ossl_prov_get_keymgmt_export(ctx->desc->fns);
190 if (reference_sz == sizeof(keydata) && export != NULL) {
191 /* The contents of the reference is the address to our object */
192 keydata = *(void **)reference;
194 return export(keydata, OSSL_KEYMGMT_SELECT_ALL,
195 export_cb, export_cbarg);
200 #define IMPLEMENT_TYPE(KEYTYPEstr, KEYTYPE, keytype, extract, free) \
201 static const struct keytype_desc_st keytype##_desc; \
202 static OSSL_FUNC_deserializer_newctx_fn ms2##keytype##_newctx; \
203 static void *ms2##keytype##_newctx(void *provctx) \
205 return ms2key_newctx(provctx, &keytype##_desc); \
207 static const struct keytype_desc_st keytype##_desc = \
208 { EVP_PKEY_##KEYTYPE, KEYTYPEstr, keytype##_keymgmt_functions, \
209 (extract_key_fn *)extract, \
210 (free_key_fn *)free }
212 #define IMPLEMENT_MS(mstype, keytype) \
213 const OSSL_DISPATCH \
214 mstype##_to_##keytype##_deserializer_functions[] = { \
215 { OSSL_FUNC_DESERIALIZER_NEWCTX, \
216 (void (*)(void))ms2##keytype##_newctx }, \
217 { OSSL_FUNC_DESERIALIZER_FREECTX, \
218 (void (*)(void))ms2key_freectx }, \
219 { OSSL_FUNC_DESERIALIZER_GETTABLE_PARAMS, \
220 (void (*)(void))ms2key_gettable_params }, \
221 { OSSL_FUNC_DESERIALIZER_GET_PARAMS, \
222 (void (*)(void))mstype##2key_get_params }, \
223 { OSSL_FUNC_DESERIALIZER_DESERIALIZE, \
224 (void (*)(void))mstype##2key_deserialize }, \
225 { OSSL_FUNC_DESERIALIZER_EXPORT_OBJECT, \
226 (void (*)(void))ms2key_export_object }, \
230 #ifndef OPENSSL_NO_DSA
231 IMPLEMENT_TYPE("DSA", DSA, dsa, EVP_PKEY_get1_DSA, DSA_free);
232 IMPLEMENT_MS(msblob, dsa);
233 # ifndef OPENSSL_NO_RC4
234 IMPLEMENT_MS(pvk, dsa);
237 IMPLEMENT_TYPE("RSA", RSA, rsa, EVP_PKEY_get1_RSA, RSA_free);
238 IMPLEMENT_MS(msblob, rsa);
239 #ifndef OPENSSL_NO_RC4
240 IMPLEMENT_MS(pvk, rsa);