2 * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <openssl/err.h>
11 #include <openssl/ui.h>
12 #include <openssl/params.h>
13 #include <openssl/serializer.h>
14 #include <openssl/core_names.h>
15 #include "internal/provider.h"
16 #include "internal/property.h"
17 #include "crypto/evp.h"
18 #include "serializer_local.h"
20 int OSSL_SERIALIZER_CTX_set_cipher(OSSL_SERIALIZER_CTX
*ctx
,
21 const char *cipher_name
,
22 const char *propquery
)
24 OSSL_PARAM params
[] = { OSSL_PARAM_END
, OSSL_PARAM_END
, OSSL_PARAM_END
};
27 OSSL_PARAM_construct_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER
,
28 (void *)cipher_name
, 0);
30 OSSL_PARAM_construct_utf8_string(OSSL_SERIALIZER_PARAM_PROPERTIES
,
31 (void *)propquery
, 0);
33 return OSSL_SERIALIZER_CTX_set_params(ctx
, params
);
36 int OSSL_SERIALIZER_CTX_set_passphrase(OSSL_SERIALIZER_CTX
*ctx
,
37 const unsigned char *kstr
,
40 OSSL_PARAM params
[] = { OSSL_PARAM_END
, OSSL_PARAM_END
};
42 params
[0] = OSSL_PARAM_construct_octet_string(OSSL_SERIALIZER_PARAM_PASS
,
45 return OSSL_SERIALIZER_CTX_set_params(ctx
, params
);
48 static void serializer_ctx_reset_passphrase_ui(OSSL_SERIALIZER_CTX
*ctx
)
50 UI_destroy_method(ctx
->allocated_ui_method
);
51 ctx
->allocated_ui_method
= NULL
;
52 ctx
->ui_method
= NULL
;
56 int OSSL_SERIALIZER_CTX_set_passphrase_ui(OSSL_SERIALIZER_CTX
*ctx
,
57 const UI_METHOD
*ui_method
,
60 if (!ossl_assert(ctx
!= NULL
)) {
61 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_PASSED_NULL_PARAMETER
);
65 serializer_ctx_reset_passphrase_ui(ctx
);
66 ctx
->ui_method
= ui_method
;
67 ctx
->ui_data
= ui_data
;
71 int OSSL_SERIALIZER_CTX_set_passphrase_cb(OSSL_SERIALIZER_CTX
*ctx
, int enc
,
72 pem_password_cb
*cb
, void *cbarg
)
74 if (!ossl_assert(ctx
!= NULL
)) {
75 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_PASSED_NULL_PARAMETER
);
79 serializer_ctx_reset_passphrase_ui(ctx
);
83 ctx
->allocated_ui_method
= UI_UTIL_wrap_read_pem_callback(cb
, enc
);
86 return ctx
->ui_method
!= NULL
;
90 * Support for OSSL_SERIALIZER_CTX_new_by_TYPE:
91 * finding a suitable serializer
94 struct selected_serializer_st
{
96 const OSSL_PROVIDER
*desired_provider
;
97 const char *propquery
;
100 * Serializers offer two functions, one that handles object data in
101 * the form of a OSSL_PARAM array, and one that directly handles a
102 * provider side object. The latter requires that the serializer
103 * is offered by the same provider that holds that object, but is
104 * more desirable because it usually provides faster serialization.
106 * When looking up possible serializers, we save the first that can
107 * handle an OSSL_PARAM array in |first|, and the first that can
108 * handle a provider side object in |desired|.
110 OSSL_SERIALIZER
*first
;
111 OSSL_SERIALIZER
*desired
;
114 static void select_serializer(const char *name
, void *data
)
116 struct selected_serializer_st
*d
= data
;
117 OSSL_SERIALIZER
*s
= NULL
;
119 /* No need to look further if we already have the more desirable option */
120 if (d
->desired
!= NULL
)
123 if ((s
= OSSL_SERIALIZER_fetch(d
->libctx
, name
, d
->propquery
)) != NULL
) {
124 if (OSSL_SERIALIZER_provider(s
) == d
->desired_provider
125 && s
->serialize_object
!= NULL
) {
126 OSSL_SERIALIZER_free(d
->first
);
129 } else if (d
->first
== NULL
&& s
->serialize_data
!= NULL
) {
132 OSSL_SERIALIZER_free(s
);
138 * Support for OSSL_SERIALIZER_CTX_new_by_TYPE and OSSL_SERIALIZER_to_bio:
139 * Passphrase callbacks
143 * First, we define the generic passphrase function that supports both
144 * outgoing (with passphrase verify) and incoming (without passphrase verify)
145 * passphrase reading.
147 static int serializer_passphrase(char *pass
, size_t pass_size
,
148 size_t *pass_len
, int verify
,
149 const OSSL_PARAM params
[], void *arg
)
151 OSSL_SERIALIZER_CTX
*ctx
= arg
;
153 const char *prompt_info
= NULL
;
154 char *prompt
= NULL
, *vpass
= NULL
;
155 int prompt_idx
= -1, verify_idx
= -1;
159 if (!ossl_assert(ctx
!= NULL
&& pass
!= NULL
160 && pass_size
!= 0 && pass_len
!= NULL
)) {
161 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_PASSED_NULL_PARAMETER
);
165 if ((p
= OSSL_PARAM_locate_const(params
,
166 OSSL_PASSPHRASE_PARAM_INFO
)) != NULL
) {
167 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
)
169 prompt_info
= p
->data
;
172 if ((ui
= UI_new()) == NULL
) {
173 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_MALLOC_FAILURE
);
177 UI_set_method(ui
, ctx
->ui_method
);
178 UI_add_user_data(ui
, ctx
->ui_data
);
180 /* Get an application constructed prompt */
181 prompt
= UI_construct_prompt(ui
, "pass phrase", prompt_info
);
182 if (prompt
== NULL
) {
183 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_MALLOC_FAILURE
);
187 prompt_idx
= UI_add_input_string(ui
, prompt
,
188 UI_INPUT_FLAG_DEFAULT_PWD
,
189 pass
, 0, pass_size
- 1) - 1;
190 if (prompt_idx
< 0) {
191 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_UI_LIB
);
196 /* Get a buffer for verification prompt */
197 vpass
= OPENSSL_zalloc(pass_size
);
199 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_MALLOC_FAILURE
);
202 verify_idx
= UI_add_verify_string(ui
, prompt
,
203 UI_INPUT_FLAG_DEFAULT_PWD
,
204 vpass
, 0, pass_size
- 1,
206 if (verify_idx
< 0) {
207 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_UI_LIB
);
212 switch (UI_process(ui
)) {
214 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_INTERRUPTED_OR_CANCELLED
);
217 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_UI_LIB
);
220 *pass_len
= (size_t)UI_get_result_length(ui
, prompt_idx
);
227 OPENSSL_free(prompt
);
232 /* Ensure correct function definition for outgoing passphrase reader */
233 static OSSL_PASSPHRASE_CALLBACK serializer_passphrase_out_cb
;
234 static int serializer_passphrase_out_cb(char *pass
, size_t pass_size
,
236 const OSSL_PARAM params
[], void *arg
)
238 return serializer_passphrase(pass
, pass_size
, pass_len
, 1, params
, arg
);
242 * Support for OSSL_SERIALIZER_to_bio:
243 * writing callback for the OSSL_PARAM (the implementation doesn't have
244 * intimate knowledge of the provider side object)
247 struct serializer_write_data_st
{
248 OSSL_SERIALIZER_CTX
*ctx
;
252 static int serializer_write_cb(const OSSL_PARAM params
[], void *arg
)
254 struct serializer_write_data_st
*write_data
= arg
;
255 OSSL_SERIALIZER_CTX
*ctx
= write_data
->ctx
;
256 BIO
*out
= write_data
->out
;
258 return ctx
->ser
->serialize_data(ctx
->serctx
, params
, out
,
259 serializer_passphrase_out_cb
, ctx
);
263 * Support for OSSL_SERIALIZER_to_bio:
264 * Perform the actual output.
267 static int serializer_EVP_PKEY_to_bio(OSSL_SERIALIZER_CTX
*ctx
, BIO
*out
)
269 const EVP_PKEY
*pkey
= ctx
->object
;
270 void *keydata
= pkey
->keydata
;
271 EVP_KEYMGMT
*keymgmt
= pkey
->keymgmt
;
274 * OSSL_SERIALIZER_CTX_new() creates a context, even when the
275 * serializer it's given is NULL. Callers can detect the lack
276 * of serializer with OSSL_SERIALIZER_CTX_get_serializer() and
277 * should take precautions, possibly call a fallback instead of
278 * OSSL_SERIALIZER_to_bio() / OSSL_SERIALIZER_to_fp(). If it's
279 * come this far, we return an error.
281 if (ctx
->ser
== NULL
)
284 if (ctx
->ser
->serialize_object
== NULL
) {
285 struct serializer_write_data_st write_data
;
287 write_data
.ctx
= ctx
;
288 write_data
.out
= out
;
290 return evp_keymgmt_export(keymgmt
, keydata
, ctx
->selection
,
291 &serializer_write_cb
, &write_data
);
294 return ctx
->ser
->serialize_object(ctx
->serctx
, keydata
, out
,
295 serializer_passphrase_out_cb
, ctx
);
299 * OSSL_SERIALIZER_CTX_new_by_EVP_PKEY() returns a ctx with no serializer if
300 * it couldn't find a suitable serializer. This allows a caller to detect if
301 * a suitable serializer was found, with OSSL_SERIALIZER_CTX_get_serializer(),
302 * and to use fallback methods if the result is NULL.
304 OSSL_SERIALIZER_CTX
*OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(const EVP_PKEY
*pkey
,
305 const char *propquery
)
307 OSSL_SERIALIZER_CTX
*ctx
= NULL
;
308 OSSL_SERIALIZER
*ser
= NULL
;
309 EVP_KEYMGMT
*keymgmt
= pkey
->keymgmt
;
310 int selection
= OSSL_KEYMGMT_SELECT_ALL
;
312 if (!ossl_assert(pkey
!= NULL
&& propquery
!= NULL
)) {
313 ERR_raise(ERR_LIB_OSSL_SERIALIZER
, ERR_R_PASSED_NULL_PARAMETER
);
317 if (keymgmt
!= NULL
) {
318 const OSSL_PROVIDER
*desired_prov
= EVP_KEYMGMT_provider(keymgmt
);
319 OPENSSL_CTX
*libctx
= ossl_provider_library_context(desired_prov
);
320 struct selected_serializer_st sel_data
;
321 OSSL_PROPERTY_LIST
*check
=
322 ossl_parse_query(libctx
, "type=parameters");
323 OSSL_PROPERTY_LIST
*current_props
= NULL
;
325 memset(&sel_data
, 0, sizeof(sel_data
));
326 sel_data
.libctx
= libctx
;
327 sel_data
.desired_provider
= desired_prov
;
328 sel_data
.propquery
= propquery
;
329 EVP_KEYMGMT_names_do_all(keymgmt
, select_serializer
, &sel_data
);
331 if (sel_data
.desired
!= NULL
) {
332 ser
= sel_data
.desired
;
333 sel_data
.desired
= NULL
;
334 } else if (sel_data
.first
!= NULL
) {
335 ser
= sel_data
.first
;
336 sel_data
.first
= NULL
;
338 OSSL_SERIALIZER_free(sel_data
.first
);
339 OSSL_SERIALIZER_free(sel_data
.desired
);
343 ossl_parse_property(libctx
, OSSL_SERIALIZER_properties(ser
));
344 if (ossl_property_match_count(check
, current_props
) > 0)
345 selection
= OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
;
346 ossl_property_free(current_props
);
349 ossl_property_free(check
);
352 ctx
= OSSL_SERIALIZER_CTX_new(ser
); /* refcnt(ser)++ */
353 OSSL_SERIALIZER_free(ser
); /* refcnt(ser)-- */
356 /* Setup for OSSL_SERIALIZE_to_bio() */
357 ctx
->selection
= selection
;
359 ctx
->do_output
= serializer_EVP_PKEY_to_bio
;