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/dsa.h>
15#include <openssl/types.h>
16#include <openssl/params.h>
17#include "prov/bio.h"
18#include "prov/implementations.h"
19#include "serializer_local.h"
20
21static OSSL_OP_serializer_newctx_fn dsa_priv_newctx;
22static OSSL_OP_serializer_freectx_fn dsa_priv_freectx;
23static OSSL_OP_serializer_set_ctx_params_fn dsa_priv_set_ctx_params;
24static OSSL_OP_serializer_settable_ctx_params_fn dsa_priv_settable_ctx_params;
25static OSSL_OP_serializer_serialize_data_fn dsa_priv_der_data;
26static OSSL_OP_serializer_serialize_object_fn dsa_priv_der;
27static OSSL_OP_serializer_serialize_data_fn dsa_pem_priv_data;
28static OSSL_OP_serializer_serialize_object_fn dsa_pem_priv;
29
30static OSSL_OP_serializer_newctx_fn dsa_print_newctx;
31static OSSL_OP_serializer_freectx_fn dsa_print_freectx;
32static OSSL_OP_serializer_serialize_data_fn dsa_priv_print_data;
33static OSSL_OP_serializer_serialize_object_fn dsa_priv_print;
34
35 /*
36 * Context used for private key serialization.
37 */
38struct dsa_priv_ctx_st {
39 void *provctx;
40
41 struct pkcs8_encrypt_ctx_st sc;
42};
43
44/* Private key : context */
45static void *dsa_priv_newctx(void *provctx)
46{
47 struct dsa_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
48
49 if (ctx != NULL) {
50 ctx->provctx = provctx;
51 }
52
53 /* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */
54 ctx->sc.pbe_nid = -1;
55
56 return ctx;
57}
58
59static void dsa_priv_freectx(void *vctx)
60{
61 struct dsa_priv_ctx_st *ctx = vctx;
62
63 EVP_CIPHER_free(ctx->sc.cipher);
64 OPENSSL_free(ctx->sc.cipher_pass);
65 OPENSSL_free(ctx);
66}
67
68static const OSSL_PARAM *dsa_priv_settable_ctx_params(void)
69{
70 static const OSSL_PARAM settables[] = {
71 OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0),
72 OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0),
73 OSSL_PARAM_END,
74 };
75
76 return settables;
77}
78
79static int dsa_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
80{
81 struct dsa_priv_ctx_st *ctx = vctx;
82 const OSSL_PARAM *p;
83
84 if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER))
85 != NULL) {
86 const OSSL_PARAM *propsp =
87 OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES);
88 const char *props = NULL;
89
90 if (p->data_type != OSSL_PARAM_UTF8_STRING)
91 return 0;
92 if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING)
93 return 0;
94 props = (propsp != NULL ? propsp->data : NULL);
95
96 EVP_CIPHER_free(ctx->sc.cipher);
97 ctx->sc.cipher_intent = p->data != NULL;
98 if (p->data != NULL
99 && ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props))
100 == NULL))
101 return 0;
102 }
103 if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS))
104 != NULL) {
105 OPENSSL_free(ctx->sc.cipher_pass);
106 ctx->sc.cipher_pass = NULL;
107 if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0,
108 &ctx->sc.cipher_pass_length))
109 return 0;
110 }
111 return 1;
112}
113
114/* Private key : DER */
115static int dsa_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
116 OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
117{
118 struct dsa_priv_ctx_st *ctx = vctx;
119 OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
120 ossl_prov_get_dsa_importkey();
121 int ok = 0;
122
123 if (dsa_importkey != NULL) {
124 DSA *dsa = dsa_importkey(ctx->provctx, params);
125
126 ok = dsa_priv_der(ctx, dsa, out, cb, cbarg);
127 DSA_free(dsa);
128 }
129 return ok;
130}
131
132static int dsa_priv_der(void *vctx, void *dsa, BIO *out,
133 OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
134{
135 struct dsa_priv_ctx_st *ctx = vctx;
136
137 ctx->sc.cb = cb;
138 ctx->sc.cbarg = cbarg;
139
140 return ossl_prov_write_priv_der_from_obj(out, dsa, EVP_PKEY_DSA,
141 ossl_prov_prepare_dsa_params,
142 ossl_prov_dsa_priv_to_der,
143 &ctx->sc);
144}
145
146/* Private key : PEM */
147static int dsa_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out,
148 OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
149{
150 struct dsa_priv_ctx_st *ctx = vctx;
151 OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
152 ossl_prov_get_dsa_importkey();
153 int ok = 0;
154
155 if (dsa_importkey != NULL) {
156 DSA *dsa = dsa_importkey(ctx, params);
157
158 ok = dsa_pem_priv(ctx->provctx, dsa, out, cb, cbarg);
159 DSA_free(dsa);
160 }
161 return ok;
162}
163
164static int dsa_pem_priv(void *vctx, void *dsa, BIO *out,
165 OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
166{
167 struct dsa_priv_ctx_st *ctx = vctx;
168
169 ctx->sc.cb = cb;
170 ctx->sc.cbarg = cbarg;
171
172 return ossl_prov_write_priv_pem_from_obj(out, dsa, EVP_PKEY_DSA,
173 ossl_prov_prepare_dsa_params,
174 ossl_prov_dsa_priv_to_der,
175 &ctx->sc);
176}
177
178/*
179 * There's no specific print context, so we use the provider context
180 */
181static void *dsa_print_newctx(void *provctx)
182{
183 return provctx;
184}
185
186static void dsa_print_freectx(void *ctx)
187{
188}
189
190static int dsa_priv_print_data(void *provctx, const OSSL_PARAM params[],
191 BIO *out,
192 OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
193{
194 OSSL_OP_keymgmt_importkey_fn *dsa_importkey =
195 ossl_prov_get_dsa_importkey();
196 int ok = 0;
197
198 if (dsa_importkey != NULL) {
199 DSA *dsa = dsa_importkey(provctx, params); /* ctx == provctx */
200
201 ok = dsa_priv_print(provctx, dsa, out, cb, cbarg);
202 DSA_free(dsa);
203 }
204 return ok;
205}
206
207static int dsa_priv_print(void *ctx, void *dsa, BIO *out,
208 OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
209{
210 return ossl_prov_print_dsa(out, dsa, dsa_print_priv);
211}
212
213const OSSL_DISPATCH dsa_priv_der_serializer_functions[] = {
214 { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_priv_newctx },
215 { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_priv_freectx },
216 { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS,
217 (void (*)(void))dsa_priv_set_ctx_params },
218 { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS,
219 (void (*)(void))dsa_priv_settable_ctx_params },
220 { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_priv_der_data },
221 { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_priv_der },
222 { 0, NULL }
223};
224
225const OSSL_DISPATCH dsa_priv_pem_serializer_functions[] = {
226 { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_priv_newctx },
227 { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_priv_freectx },
228 { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS,
229 (void (*)(void))dsa_priv_set_ctx_params },
230 { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS,
231 (void (*)(void))dsa_priv_settable_ctx_params },
232 { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_pem_priv_data },
233 { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_pem_priv },
234 { 0, NULL }
235};
236
237const OSSL_DISPATCH dsa_priv_text_serializer_functions[] = {
238 { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_print_newctx },
239 { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_print_freectx },
240 { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_priv_print },
241 { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA,
242 (void (*)(void))dsa_priv_print_data },
243 { 0, NULL }
244};
245