Implement the ECX Serializers
[openssl.git] / providers / implementations / serializers / serializer_ecx_priv.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 #include <openssl/core_numbers.h>
11 #include <openssl/core_names.h>
12 #include <openssl/err.h>
13 #include <openssl/pem.h>
14 #include <openssl/types.h>
15 #include <openssl/params.h>
16 #include "prov/bio.h"
17 #include "prov/implementations.h"
18 #include "serializer_local.h"
19
20 static OSSL_OP_serializer_newctx_fn x25519_priv_newctx;
21 static OSSL_OP_serializer_newctx_fn x448_priv_newctx;
22 static OSSL_OP_serializer_freectx_fn ecx_priv_freectx;
23 static OSSL_OP_serializer_set_ctx_params_fn ecx_priv_set_ctx_params;
24 static OSSL_OP_serializer_settable_ctx_params_fn ecx_priv_settable_ctx_params;
25 static OSSL_OP_serializer_serialize_data_fn ecx_priv_der_data;
26 static OSSL_OP_serializer_serialize_object_fn ecx_priv_der;
27 static OSSL_OP_serializer_serialize_data_fn ecx_priv_pem_data;
28 static OSSL_OP_serializer_serialize_object_fn ecx_priv_pem;
29
30 static OSSL_OP_serializer_serialize_data_fn ecx_priv_print_data;
31 static OSSL_OP_serializer_serialize_object_fn ecx_priv_print;
32
33  /*
34  * Context used for private key serialization.
35  */
36 struct ecx_priv_ctx_st {
37     void *provctx;
38
39     struct pkcs8_encrypt_ctx_st sc;
40     ECX_KEY_TYPE type;
41 };
42
43 /* Private key : context */
44 static void *ecx_priv_newctx(void *provctx, ECX_KEY_TYPE type)
45 {
46     struct ecx_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
47
48     if (ctx != NULL) {
49         ctx->provctx = provctx;
50
51         /* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */
52         ctx->sc.pbe_nid = -1;
53         ctx->type = type;
54     }
55     return ctx;
56 }
57
58 static void *x25519_priv_newctx(void *provctx)
59 {
60     return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X25519);
61 }
62
63 static void *x448_priv_newctx(void *provctx)
64 {
65     return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X448);
66 }
67
68 static void ecx_priv_freectx(void *vctx)
69 {
70     struct ecx_priv_ctx_st *ctx = vctx;
71
72     EVP_CIPHER_free(ctx->sc.cipher);
73     OPENSSL_free(ctx->sc.cipher_pass);
74     OPENSSL_free(ctx);
75 }
76
77 static const OSSL_PARAM *ecx_priv_settable_ctx_params(void)
78 {
79     static const OSSL_PARAM settables[] = {
80         OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0),
81         OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0),
82         OSSL_PARAM_END,
83     };
84
85     return settables;
86 }
87
88 static int ecx_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
89 {
90     struct ecx_priv_ctx_st *ctx = vctx;
91     const OSSL_PARAM *p;
92
93     p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER);
94     if (p != NULL) {
95         const OSSL_PARAM *propsp =
96             OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES);
97         const char *props;
98
99         if (p->data_type != OSSL_PARAM_UTF8_STRING)
100             return 0;
101         if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING)
102             return 0;
103         props = (propsp != NULL ? propsp->data : NULL);
104
105         EVP_CIPHER_free(ctx->sc.cipher);
106         ctx->sc.cipher_intent = p->data != NULL;
107         if (p->data != NULL
108             && ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props))
109                 == NULL))
110             return 0;
111     }
112     p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS);
113     if (p != NULL) {
114         OPENSSL_free(ctx->sc.cipher_pass);
115         ctx->sc.cipher_pass = NULL;
116         if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0,
117                                          &ctx->sc.cipher_pass_length))
118             return 0;
119     }
120     return 1;
121 }
122
123 /* Private key : DER */
124 static int ecx_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
125                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
126 {
127     struct ecx_priv_ctx_st *ctx = vctx;
128     OSSL_OP_keymgmt_new_fn *ecx_new;
129     OSSL_OP_keymgmt_free_fn *ecx_free;
130     OSSL_OP_keymgmt_import_fn *ecx_import;
131     int ok = 0;
132
133     ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
134
135     if (ecx_import != NULL) {
136         ECX_KEY *ecxkey;
137
138         if ((ecxkey = ecx_new(ctx->provctx)) != NULL
139             && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
140             && ecx_priv_der(ctx, ecxkey, out, cb, cbarg))
141             ok = 1;
142         ecx_free(ecxkey);
143     }
144     return ok;
145 }
146
147 static int ecx_priv_der(void *vctx, void *vecxkey, BIO *out,
148                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
149 {
150     struct ecx_priv_ctx_st *ctx = vctx;
151     ECX_KEY *ecxkey = vecxkey;
152     int ret;
153     int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
154                                                   : EVP_PKEY_X448;
155
156     ctx->sc.cb = cb;
157     ctx->sc.cbarg = cbarg;
158
159     ret = ossl_prov_write_priv_der_from_obj(out, ecxkey,
160                                             type,
161                                             NULL,
162                                             ossl_prov_ecx_priv_to_der,
163                                             &ctx->sc);
164
165     return ret;
166 }
167
168 /* Private key : PEM */
169 static int ecx_priv_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
170                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
171 {
172     struct ecx_priv_ctx_st *ctx = vctx;
173     OSSL_OP_keymgmt_new_fn *ecx_new;
174     OSSL_OP_keymgmt_free_fn *ecx_free;
175     OSSL_OP_keymgmt_import_fn *ecx_import;
176     int ok = 0;
177
178     ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
179
180     if (ecx_import != NULL) {
181         ECX_KEY *ecxkey;
182
183         if ((ecxkey = ecx_new(ctx->provctx)) != NULL
184             && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
185             && ecx_priv_pem(ctx->provctx, ecxkey, out, cb, cbarg))
186             ok = 1;
187         ecx_free(ecxkey);
188     }
189     return ok;
190 }
191
192 static int ecx_priv_pem(void *vctx, void *ecxkey, BIO *out,
193                        OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
194 {
195     struct ecx_priv_ctx_st *ctx = vctx;
196     int ret;
197     int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
198                                                   : EVP_PKEY_X448;
199
200     ctx->sc.cb = cb;
201     ctx->sc.cbarg = cbarg;
202
203     ret = ossl_prov_write_priv_pem_from_obj(out, ecxkey,
204                                             type,
205                                             NULL,
206                                             ossl_prov_ecx_priv_to_der,
207                                             &ctx->sc);
208
209     return ret;
210 }
211
212 static int ecx_priv_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
213                                OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
214 {
215     struct ecx_priv_ctx_st *ctx = vctx;
216     OSSL_OP_keymgmt_new_fn *ecx_new;
217     OSSL_OP_keymgmt_free_fn *ecx_free;
218     OSSL_OP_keymgmt_import_fn *ecx_import;
219     int ok = 0;
220
221     ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
222
223     if (ecx_import != NULL) {
224         ECX_KEY *ecxkey;
225
226         if ((ecxkey = ecx_new(ctx->provctx)) != NULL
227             && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
228             && ecx_priv_print(ctx, ecxkey, out, cb, cbarg))
229             ok = 1;
230         ecx_free(ecxkey);
231     }
232     return ok;
233 }
234
235 static int ecx_priv_print(void *ctx, void *ecxkey, BIO *out,
236                          OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
237 {
238     return ossl_prov_print_ecx(out, ecxkey, ecx_print_priv);
239 }
240
241 #define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
242     const OSSL_DISPATCH alg##_priv_##type##_serializer_functions[] = { \
243         { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
244         { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
245         { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, \
246           (void (*)(void))ecx_priv_set_ctx_params }, \
247         { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, \
248           (void (*)(void))ecx_priv_settable_ctx_params }, \
249         { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
250           (void (*)(void))ecx_priv_##type##_data }, \
251         { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
252           (void (*)(void))ecx_priv_##type }, \
253         { 0, NULL } \
254     };
255
256 #define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
257     MAKE_SERIALIZER_FUNCTIONS(alg, der) \
258     MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
259     const OSSL_DISPATCH alg##_priv_print_serializer_functions[] = { \
260         { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
261         { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
262         { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
263           (void (*)(void))ecx_priv_print }, \
264         { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
265           (void (*)(void))ecx_priv_print_data }, \
266         { 0, NULL } \
267     };
268
269 MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
270 MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)