2 * Copyright 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/core_names.h>
13 #include "internal/cryptlib.h"
14 #include "internal/passphrase.h"
16 void ossl_pw_clear_passphrase_data(struct ossl_passphrase_data_st
*data
)
19 if (data
->type
== is_expl_passphrase
)
20 OPENSSL_clear_free(data
->_
.expl_passphrase
.passphrase_copy
,
21 data
->_
.expl_passphrase
.passphrase_len
);
22 ossl_pw_clear_passphrase_cache(data
);
23 memset(data
, 0, sizeof(*data
));
27 void ossl_pw_clear_passphrase_cache(struct ossl_passphrase_data_st
*data
)
29 OPENSSL_clear_free(data
->cached_passphrase
, data
->cached_passphrase_len
);
30 data
->cached_passphrase
= NULL
;
33 int ossl_pw_set_passphrase(struct ossl_passphrase_data_st
*data
,
34 const unsigned char *passphrase
,
35 size_t passphrase_len
)
37 if (!ossl_assert(data
!= NULL
&& passphrase
!= NULL
)) {
38 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
41 ossl_pw_clear_passphrase_data(data
);
42 data
->type
= is_expl_passphrase
;
43 data
->_
.expl_passphrase
.passphrase_copy
=
44 OPENSSL_memdup(passphrase
, passphrase_len
);
45 if (data
->_
.expl_passphrase
.passphrase_copy
== NULL
) {
46 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
49 data
->_
.expl_passphrase
.passphrase_len
= passphrase_len
;
53 int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st
*data
,
54 pem_password_cb
*cb
, void *cbarg
)
56 if (!ossl_assert(data
!= NULL
&& cb
!= NULL
)) {
57 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
60 ossl_pw_clear_passphrase_data(data
);
61 data
->type
= is_pem_password
;
62 data
->_
.pem_password
.password_cb
= cb
;
63 data
->_
.pem_password
.password_cbarg
= cbarg
;
67 int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st
*data
,
68 OSSL_PASSPHRASE_CALLBACK
*cb
, void *cbarg
)
70 if (!ossl_assert(data
!= NULL
&& cb
!= NULL
)) {
71 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
74 ossl_pw_clear_passphrase_data(data
);
75 data
->type
= is_ossl_passphrase
;
76 data
->_
.ossl_passphrase
.passphrase_cb
= cb
;
77 data
->_
.ossl_passphrase
.passphrase_cbarg
= cbarg
;
81 int ossl_pw_set_ui_method(struct ossl_passphrase_data_st
*data
,
82 const UI_METHOD
*ui_method
, void *ui_data
)
84 if (!ossl_assert(data
!= NULL
&& ui_method
!= NULL
)) {
85 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
88 ossl_pw_clear_passphrase_data(data
);
89 data
->type
= is_ui_method
;
90 data
->_
.ui_method
.ui_method
= ui_method
;
91 data
->_
.ui_method
.ui_method_data
= ui_data
;
95 int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st
*data
)
97 data
->flag_cache_passphrase
= 1;
101 int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st
*data
)
103 data
->flag_cache_passphrase
= 0;
109 * UI_METHOD processor. It differs from UI_UTIL_read_pw() like this:
111 * 1. It constructs a prompt on its own, based on |prompt_info|.
112 * 2. It allocates a buffer for verification on its own.
113 * 3. It raises errors.
114 * 4. It reports back the length of the prompted pass phrase.
116 static int do_ui_passphrase(char *pass
, size_t pass_size
, size_t *pass_len
,
117 const char *prompt_info
, int verify
,
118 const UI_METHOD
*ui_method
, void *ui_data
)
120 char *prompt
= NULL
, *vpass
= NULL
;
121 int prompt_idx
= -1, verify_idx
= -1;
125 if (!ossl_assert(pass
!= NULL
&& pass_size
!= 0 && pass_len
!= NULL
)) {
126 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
130 if ((ui
= UI_new()) == NULL
) {
131 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
135 if (ui_method
!= NULL
) {
136 UI_set_method(ui
, ui_method
);
138 UI_add_user_data(ui
, ui_data
);
141 /* Get an application constructed prompt */
142 prompt
= UI_construct_prompt(ui
, "pass phrase", prompt_info
);
143 if (prompt
== NULL
) {
144 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
148 prompt_idx
= UI_add_input_string(ui
, prompt
,
149 UI_INPUT_FLAG_DEFAULT_PWD
,
150 pass
, 0, pass_size
- 1) - 1;
151 if (prompt_idx
< 0) {
152 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
157 /* Get a buffer for verification prompt */
158 vpass
= OPENSSL_zalloc(pass_size
);
160 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
163 verify_idx
= UI_add_verify_string(ui
, prompt
,
164 UI_INPUT_FLAG_DEFAULT_PWD
,
165 vpass
, 0, pass_size
- 1,
167 if (verify_idx
< 0) {
168 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
173 switch (UI_process(ui
)) {
175 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_INTERRUPTED_OR_CANCELLED
);
178 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
181 *pass_len
= (size_t)UI_get_result_length(ui
, prompt_idx
);
188 OPENSSL_free(prompt
);
193 /* Central pw prompting dispatcher */
194 int ossl_pw_get_passphrase(char *pass
, size_t pass_size
, size_t *pass_len
,
195 const OSSL_PARAM params
[], int verify
,
196 struct ossl_passphrase_data_st
*data
)
198 const char *source
= NULL
;
199 size_t source_len
= 0;
200 const char *prompt_info
= NULL
;
201 const UI_METHOD
*ui_method
= NULL
;
202 UI_METHOD
*allocated_ui_method
= NULL
;
203 void *ui_data
= NULL
;
204 const OSSL_PARAM
*p
= NULL
;
207 /* Handle explicit and cached passphrases */
209 if (data
->type
== is_expl_passphrase
) {
210 source
= data
->_
.expl_passphrase
.passphrase_copy
;
211 source_len
= data
->_
.expl_passphrase
.passphrase_len
;
212 } else if (data
->flag_cache_passphrase
&& data
->cached_passphrase
!= NULL
) {
213 source
= data
->cached_passphrase
;
214 source_len
= data
->cached_passphrase_len
;
217 if (source
!= NULL
) {
218 if (source_len
> pass_size
)
219 source_len
= pass_size
;
220 memcpy(pass
, source
, source_len
);
221 *pass_len
= source_len
;
225 /* Handle the is_ossl_passphrase case... that's pretty direct */
227 if (data
->type
== is_ossl_passphrase
) {
228 OSSL_PASSPHRASE_CALLBACK
*cb
= data
->_
.ossl_passphrase
.passphrase_cb
;
229 void *cbarg
= data
->_
.ossl_passphrase
.passphrase_cbarg
;
231 ret
= cb(pass
, pass_size
, pass_len
, params
, cbarg
);
235 /* Handle the is_pem_password and is_ui_method cases */
237 if ((p
= OSSL_PARAM_locate_const(params
,
238 OSSL_PASSPHRASE_PARAM_INFO
)) != NULL
) {
239 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
) {
240 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_PASSED_INVALID_ARGUMENT
,
241 "Prompt info data type incorrect");
244 prompt_info
= p
->data
;
247 if (data
->type
== is_pem_password
) {
248 /* We use a UI wrapper for PEM */
249 pem_password_cb
*cb
= data
->_
.pem_password
.password_cb
;
251 ui_method
= allocated_ui_method
=
252 UI_UTIL_wrap_read_pem_callback(cb
, verify
);
253 ui_data
= data
->_
.pem_password
.password_cbarg
;
255 if (ui_method
== NULL
) {
256 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
259 } else if (data
->type
== is_ui_method
) {
260 ui_method
= data
->_
.ui_method
.ui_method
;
261 ui_data
= data
->_
.ui_method
.ui_method_data
;
264 if (ui_method
== NULL
) {
265 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_INTERNAL_ERROR
);
269 ret
= do_ui_passphrase(pass
, pass_size
, pass_len
, prompt_info
, verify
,
272 UI_destroy_method(allocated_ui_method
);
275 if (ret
&& data
->flag_cache_passphrase
) {
276 if (data
->cached_passphrase
== NULL
277 || *pass_len
> data
->cached_passphrase_len
) {
279 OPENSSL_clear_realloc(data
->cached_passphrase
,
280 data
->cached_passphrase_len
,
283 if (new_cache
== NULL
) {
284 OPENSSL_cleanse(pass
, *pass_len
);
285 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
288 data
->cached_passphrase
= new_cache
;
290 memcpy(data
->cached_passphrase
, pass
, *pass_len
);
291 data
->cached_passphrase
[*pass_len
] = '\0';
292 data
->cached_passphrase_len
= *pass_len
;
298 int ossl_pw_pem_password(char *buf
, int size
, int rwflag
, void *userdata
)
300 size_t password_len
= 0;
301 OSSL_PARAM params
[] = {
302 OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO
, NULL
, 0),
306 params
[0].data
= "PEM";
307 if (ossl_pw_get_passphrase(buf
, (size_t)size
, &password_len
, params
,
309 return (int)password_len
;
313 int ossl_pw_passphrase_callback_enc(char *pass
, size_t pass_size
,
315 const OSSL_PARAM params
[], void *arg
)
317 return ossl_pw_get_passphrase(pass
, pass_size
, pass_len
, params
, 1, arg
);
320 int ossl_pw_passphrase_callback_dec(char *pass
, size_t pass_size
,
322 const OSSL_PARAM params
[], void *arg
)
324 return ossl_pw_get_passphrase(pass
, pass_size
, pass_len
, params
, 0, arg
);