PROV SERIALIZER: add support for writing RSA keys
[oweals/openssl.git] / providers / implementations / serializers / serializer_rsa_priv.c
1 /*
2  * Copyright 2019 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/rsa.h>
15 #include <openssl/types.h>
16 #include <openssl/params.h>
17 #include <openssl/safestack.h>
18 #include "prov/bio.h"
19 #include "prov/implementations.h"
20 #include "prov/providercommonerr.h"
21 #include "serializer_local.h"
22
23 static OSSL_OP_serializer_newctx_fn rsa_priv_newctx;
24 static OSSL_OP_serializer_freectx_fn rsa_priv_freectx;
25 static OSSL_OP_serializer_set_ctx_params_fn rsa_priv_set_ctx_params;
26 static OSSL_OP_serializer_settable_ctx_params_fn rsa_priv_settable_ctx_params;
27 static OSSL_OP_serializer_serialize_data_fn rsa_priv_der_data;
28 static OSSL_OP_serializer_serialize_object_fn rsa_priv_der;
29 static OSSL_OP_serializer_serialize_data_fn rsa_pem_priv_data;
30 static OSSL_OP_serializer_serialize_object_fn rsa_pem_priv;
31
32 static OSSL_OP_serializer_newctx_fn rsa_print_newctx;
33 static OSSL_OP_serializer_freectx_fn rsa_print_freectx;
34 static OSSL_OP_serializer_serialize_data_fn rsa_priv_print_data;
35 static OSSL_OP_serializer_serialize_object_fn rsa_priv_print;
36
37  /*
38  * Context used for private key serialization.
39  */
40 struct rsa_priv_ctx_st {
41     void *provctx;
42
43     struct pkcs8_encrypt_ctx_st sc;
44 };
45
46 /* Helper functions to prepare RSA-PSS params for serialization */
47
48 static int prepare_rsa_params(const void *rsa, int nid,
49                               ASN1_STRING **pstr, int *pstrtype)
50 {
51     const RSA_PSS_PARAMS *pss = RSA_get0_pss_params(rsa);
52     *pstr = NULL;
53
54     /* If RSA it's just NULL type */
55     if (nid != EVP_PKEY_RSA_PSS) {
56         *pstrtype = V_ASN1_NULL;
57         return 1;
58     }
59     /* If no PSS parameters we omit parameters entirely */
60     if (pss == NULL) {
61         *pstrtype = V_ASN1_UNDEF;
62         return 1;
63     }
64     /* Encode PSS parameters */
65     if (ASN1_item_pack((void *)pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr)
66         == NULL)
67         return 0;
68
69     *pstrtype = V_ASN1_SEQUENCE;
70     return 1;
71 }
72
73 /* Private key : context */
74 static void *rsa_priv_newctx(void *provctx)
75 {
76     struct rsa_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
77
78     if (ctx != NULL) {
79         ctx->provctx = provctx;
80     }
81
82     /* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */
83     ctx->sc.pbe_nid = -1;
84
85     return ctx;
86 }
87
88 static void rsa_priv_freectx(void *vctx)
89 {
90     struct rsa_priv_ctx_st *ctx = vctx;
91
92     EVP_CIPHER_free(ctx->sc.cipher);
93     OPENSSL_free(ctx->sc.cipher_pass);
94     OPENSSL_free(ctx);
95 }
96
97 static const OSSL_PARAM *rsa_priv_settable_ctx_params(void)
98 {
99     static const OSSL_PARAM settables[] = {
100         OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0),
101         OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0),
102         OSSL_PARAM_END,
103     };
104
105     return settables;
106 }
107
108 static int rsa_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
109 {
110     struct rsa_priv_ctx_st *ctx = vctx;
111     const OSSL_PARAM *p;
112
113     if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER))
114         != NULL) {
115         const OSSL_PARAM *propsp =
116             OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES);
117         const char *props = NULL;
118
119         if (p->data_type != OSSL_PARAM_UTF8_STRING)
120             return 0;
121         if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING)
122             return 0;
123         props = (propsp != NULL ? propsp->data : NULL);
124
125         EVP_CIPHER_free(ctx->sc.cipher);
126         ctx->sc.cipher_intent = p->data != NULL;
127         if (p->data != NULL
128             && ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props))
129                 == NULL))
130             return 0;
131     }
132     if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS))
133         != NULL) {
134         OPENSSL_free(ctx->sc.cipher_pass);
135         ctx->sc.cipher_pass = NULL;
136         if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0,
137                                          &ctx->sc.cipher_pass_length))
138             return 0;
139     }
140     return 1;
141 }
142
143 /* Private key : DER */
144 static int rsa_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
145                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
146 {
147     struct rsa_priv_ctx_st *ctx = vctx;
148     OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
149         ossl_prov_get_rsa_importkey();
150     int ok = 0;
151
152     if (rsa_importkey != NULL) {
153         RSA *rsa = rsa_importkey(ctx->provctx, params);
154
155         ok = rsa_priv_der(vctx, rsa, out, cb, cbarg);
156         RSA_free(rsa);
157     }
158     return ok;
159 }
160
161 static int rsa_priv_der(void *vctx, void *rsa, BIO *out,
162                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
163 {
164     struct rsa_priv_ctx_st *ctx = vctx;
165     int ret;
166
167     ctx->sc.cb = cb;
168     ctx->sc.cbarg = cbarg;
169
170     ret = ossl_prov_write_priv_der_from_obj(out, rsa, EVP_PKEY_RSA,
171                                             prepare_rsa_params,
172                                             (i2d_of_void *)i2d_RSAPrivateKey,
173                                             &ctx->sc);
174
175     return ret;
176 }
177
178 /* Private key : PEM */
179 static int rsa_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out,
180                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
181 {
182     struct rsa_priv_ctx_st *ctx = vctx;
183     OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
184         ossl_prov_get_rsa_importkey();
185     int ok = 0;
186
187     if (rsa_importkey != NULL) {
188         RSA *rsa = rsa_importkey(ctx, params);
189
190         ok = rsa_pem_priv(vctx, rsa, out, cb, cbarg);
191         RSA_free(rsa);
192     }
193     return ok;
194 }
195
196 static int rsa_pem_priv(void *vctx, void *rsa, BIO *out,
197                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
198 {
199     struct rsa_priv_ctx_st *ctx = vctx;
200     int ret;
201
202     ctx->sc.cb = cb;
203     ctx->sc.cbarg = cbarg;
204
205     ret = ossl_prov_write_priv_pem_from_obj(out, rsa, EVP_PKEY_RSA,
206                                             prepare_rsa_params,
207                                             (i2d_of_void *)i2d_RSAPrivateKey,
208                                             &ctx->sc);
209
210     return ret;
211 }
212
213 /*
214  * There's no specific print context, so we use the provider context
215  */
216 static void *rsa_print_newctx(void *provctx)
217 {
218     return provctx;
219 }
220
221 static void rsa_print_freectx(void *ctx)
222 {
223 }
224
225 static int rsa_priv_print_data(void *provctx, const OSSL_PARAM params[],
226                                BIO *out,
227                                OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
228 {
229     OSSL_OP_keymgmt_importkey_fn *rsa_importkey =
230         ossl_prov_get_rsa_importkey();
231     int ok = 0;
232
233     if (rsa_importkey != NULL) {
234         RSA *rsa = rsa_importkey(provctx, params); /* ctx == provctx */
235
236         ok = rsa_priv_print(provctx, rsa, out, cb, cbarg);
237         RSA_free(rsa);
238     }
239     return ok;
240 }
241
242 static int rsa_priv_print(void *ctx, void *rsa, BIO *out,
243                           OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
244 {
245     return ossl_prov_print_rsa(out, rsa, 1);
246 }
247
248 const OSSL_DISPATCH rsa_priv_der_serializer_functions[] = {
249     { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_priv_newctx },
250     { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_priv_freectx },
251     { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS,
252       (void (*)(void))rsa_priv_set_ctx_params },
253     { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS,
254       (void (*)(void))rsa_priv_settable_ctx_params },
255     { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))rsa_priv_der_data },
256     { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_priv_der },
257     { 0, NULL }
258 };
259
260 const OSSL_DISPATCH rsa_priv_pem_serializer_functions[] = {
261     { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_priv_newctx },
262     { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_priv_freectx },
263     { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS,
264       (void (*)(void))rsa_priv_set_ctx_params },
265     { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS,
266       (void (*)(void))rsa_priv_settable_ctx_params },
267     { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))rsa_pem_priv_data },
268     { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_pem_priv },
269     { 0, NULL }
270 };
271
272 const OSSL_DISPATCH rsa_priv_text_serializer_functions[] = {
273     { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))rsa_print_newctx },
274     { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))rsa_print_freectx },
275     { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))rsa_priv_print },
276     { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA,
277       (void (*)(void))rsa_priv_print_data },
278     { 0, NULL }
279 };