Rename OSSL_SERIALIZER / OSSL_DESERIALIZER to OSSL_ENCODE / OSSL_DECODE
[openssl.git] / providers / implementations / serializers / deserialize_ms2key.c
1 /*
2  * Copyright 2020 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
12  * internal use.
13  */
14 #include "internal/deprecated.h"
15
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 */
22 #include "prov/bio.h"
23 #include "prov/implementations.h"
24 #include "serializer_local.h"
25
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;
31 #endif
32 static OSSL_FUNC_deserializer_deserialize_fn msblob2key_deserialize;
33 #ifndef OPENSSL_NO_RC4
34 static OSSL_FUNC_deserializer_deserialize_fn pvk2key_deserialize;
35 #endif
36 static OSSL_FUNC_deserializer_export_object_fn ms2key_export_object;
37
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) */
44
45     /*
46      * These must be the correct EVP_PKEY_get1_{TYPE}() and {TYPE}_free()
47      * function for the key.
48      */
49     extract_key_fn *extract_key;
50     free_key_fn *free_key;
51 };
52
53 /*
54  * Context used for DER to key deserialization.
55  */
56 struct ms2key_ctx_st {
57     PROV_CTX *provctx;
58     const struct keytype_desc_st *desc;
59 };
60
61 static struct ms2key_ctx_st *
62 ms2key_newctx(void *provctx, const struct keytype_desc_st *desc)
63 {
64     struct ms2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
65
66     if (ctx != NULL) {
67         ctx->provctx = provctx;
68         ctx->desc = desc;
69     }
70     return ctx;
71 }
72
73 static void ms2key_freectx(void *vctx)
74 {
75     struct ms2key_ctx_st *ctx = vctx;
76
77     OPENSSL_free(ctx);
78 }
79
80 static const OSSL_PARAM *ms2key_gettable_params(ossl_unused void *provctx)
81 {
82     static const OSSL_PARAM gettables[] = {
83         { OSSL_DESERIALIZER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 },
84         OSSL_PARAM_END,
85     };
86
87     return gettables;
88 }
89
90 static int msblob2key_get_params(OSSL_PARAM params[])
91 {
92     OSSL_PARAM *p;
93
94     p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
95     if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "MSBLOB"))
96         return 0;
97
98     return 1;
99 }
100
101 #ifndef OPENSSL_NO_RC4
102 static int pvk2key_get_params(OSSL_PARAM params[])
103 {
104     OSSL_PARAM *p;
105
106     p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
107     if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "PVK"))
108         return 0;
109
110     return 1;
111 }
112 #endif
113
114 static int ms2key_post(struct ms2key_ctx_st *ctx, EVP_PKEY *pkey,
115                        OSSL_CALLBACK *data_cb, void *data_cbarg)
116 {
117     void *key = NULL;
118     int ok = 0;
119
120     if (pkey != NULL) {
121         /*
122          * Tear out the low-level key pointer from the pkey,
123          * but only if it matches the expected key type.
124          *
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.
128          */
129         if (EVP_PKEY_id(pkey) == ctx->desc->type)
130             key = ctx->desc->extract_key(pkey);
131     }
132
133     if (key != NULL) {
134         OSSL_PARAM params[3];
135
136         params[0] =
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 */
140         params[1] =
141             OSSL_PARAM_construct_octet_string(OSSL_DESERIALIZER_PARAM_REFERENCE,
142                                               &key, sizeof(key));
143         params[2] = OSSL_PARAM_construct_end();
144
145         ok = data_cb(params, data_cbarg);
146     }
147     ctx->desc->free_key(key);
148
149     return ok;
150 }
151
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,
155                                   void *pw_cbarg)
156 {
157     struct ms2key_ctx_st *ctx = vctx;
158     int ispub = -1;
159     EVP_PKEY *pkey = ossl_prov_read_msblob(ctx->provctx, cin, &ispub);
160     int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
161
162     EVP_PKEY_free(pkey);
163     return ok;
164 }
165
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,
170                                void *pw_cbarg)
171 {
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);
175
176     EVP_PKEY_free(pkey);
177     return ok;
178 }
179 #endif
180
181 static int ms2key_export_object(void *vctx,
182                                  const void *reference, size_t reference_sz,
183                                  OSSL_CALLBACK *export_cb, void *export_cbarg)
184 {
185     struct ms2key_ctx_st *ctx = vctx;
186     OSSL_FUNC_keymgmt_export_fn *export =
187         ossl_prov_get_keymgmt_export(ctx->desc->fns);
188     void *keydata;
189
190     if (reference_sz == sizeof(keydata) && export != NULL) {
191         /* The contents of the reference is the address to our object */
192         keydata = *(void **)reference;
193
194         return export(keydata, OSSL_KEYMGMT_SELECT_ALL,
195                       export_cb, export_cbarg);
196     }
197     return 0;
198 }
199
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)                   \
204     {                                                                   \
205         return ms2key_newctx(provctx, &keytype##_desc);                 \
206     }                                                                   \
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 }
211
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 },                       \
227         { 0, NULL }                                                     \
228     }
229
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);
235 # endif
236 #endif
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);
241 #endif