]> git.ipfire.org Git - thirdparty/openssl.git/blame - providers/implementations/serializers/serializer_rsa_priv.c
PROV SERIALIZER: add support for writing RSA keys
[thirdparty/openssl.git] / providers / implementations / serializers / serializer_rsa_priv.c
CommitLineData
677add38
RL
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
23static OSSL_OP_serializer_newctx_fn rsa_priv_newctx;
24static OSSL_OP_serializer_freectx_fn rsa_priv_freectx;
25static OSSL_OP_serializer_set_ctx_params_fn rsa_priv_set_ctx_params;
26static OSSL_OP_serializer_settable_ctx_params_fn rsa_priv_settable_ctx_params;
27static OSSL_OP_serializer_serialize_data_fn rsa_priv_der_data;
28static OSSL_OP_serializer_serialize_object_fn rsa_priv_der;
29static OSSL_OP_serializer_serialize_data_fn rsa_pem_priv_data;
30static OSSL_OP_serializer_serialize_object_fn rsa_pem_priv;
31
32static OSSL_OP_serializer_newctx_fn rsa_print_newctx;
33static OSSL_OP_serializer_freectx_fn rsa_print_freectx;
34static OSSL_OP_serializer_serialize_data_fn rsa_priv_print_data;
35static OSSL_OP_serializer_serialize_object_fn rsa_priv_print;
36
37 /*
38 * Context used for private key serialization.
39 */
40struct 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
48static 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 */
74static 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
88static 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
97static 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
108static 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 */
144static 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
161static 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 */
179static 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
196static 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 */
216static void *rsa_print_newctx(void *provctx)
217{
218 return provctx;
219}
220
221static void rsa_print_freectx(void *ctx)
222{
223}
224
225static 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
242static 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
248const 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
260const 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
272const 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};