2 * Copyright 2020-2022 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 passphrase_len
!= 0 ? OPENSSL_memdup(passphrase
, passphrase_len
)
46 if (data
->_
.expl_passphrase
.passphrase_copy
== NULL
) {
47 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
50 data
->_
.expl_passphrase
.passphrase_len
= passphrase_len
;
54 int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st
*data
,
55 pem_password_cb
*cb
, void *cbarg
)
57 if (!ossl_assert(data
!= NULL
&& cb
!= NULL
)) {
58 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
61 ossl_pw_clear_passphrase_data(data
);
62 data
->type
= is_pem_password
;
63 data
->_
.pem_password
.password_cb
= cb
;
64 data
->_
.pem_password
.password_cbarg
= cbarg
;
68 int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st
*data
,
69 OSSL_PASSPHRASE_CALLBACK
*cb
, void *cbarg
)
71 if (!ossl_assert(data
!= NULL
&& cb
!= NULL
)) {
72 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
75 ossl_pw_clear_passphrase_data(data
);
76 data
->type
= is_ossl_passphrase
;
77 data
->_
.ossl_passphrase
.passphrase_cb
= cb
;
78 data
->_
.ossl_passphrase
.passphrase_cbarg
= cbarg
;
82 int ossl_pw_set_ui_method(struct ossl_passphrase_data_st
*data
,
83 const UI_METHOD
*ui_method
, void *ui_data
)
85 if (!ossl_assert(data
!= NULL
&& ui_method
!= NULL
)) {
86 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
89 ossl_pw_clear_passphrase_data(data
);
90 data
->type
= is_ui_method
;
91 data
->_
.ui_method
.ui_method
= ui_method
;
92 data
->_
.ui_method
.ui_method_data
= ui_data
;
96 int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st
*data
)
98 data
->flag_cache_passphrase
= 1;
102 int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st
*data
)
104 data
->flag_cache_passphrase
= 0;
110 * UI_METHOD processor. It differs from UI_UTIL_read_pw() like this:
112 * 1. It constructs a prompt on its own, based on |prompt_info|.
113 * 2. It allocates a buffer for password and verification on its own
114 * to compensate for NUL terminator in UI password strings.
115 * 3. It raises errors.
116 * 4. It reports back the length of the prompted pass phrase.
118 static int do_ui_passphrase(char *pass
, size_t pass_size
, size_t *pass_len
,
119 const char *prompt_info
, int verify
,
120 const UI_METHOD
*ui_method
, void *ui_data
)
122 char *prompt
= NULL
, *ipass
= NULL
, *vpass
= NULL
;
123 int prompt_idx
= -1, verify_idx
= -1, res
;
127 if (!ossl_assert(pass
!= NULL
&& pass_size
!= 0 && pass_len
!= NULL
)) {
128 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
132 if ((ui
= UI_new()) == NULL
) {
133 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
137 if (ui_method
!= NULL
) {
138 UI_set_method(ui
, ui_method
);
140 UI_add_user_data(ui
, ui_data
);
143 /* Get an application constructed prompt */
144 prompt
= UI_construct_prompt(ui
, "pass phrase", prompt_info
);
145 if (prompt
== NULL
) {
146 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
150 /* Get a buffer for verification prompt */
151 ipass
= OPENSSL_zalloc(pass_size
+ 1);
153 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
157 prompt_idx
= UI_add_input_string(ui
, prompt
,
158 UI_INPUT_FLAG_DEFAULT_PWD
,
159 ipass
, 0, pass_size
) - 1;
160 if (prompt_idx
< 0) {
161 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
166 /* Get a buffer for verification prompt */
167 vpass
= OPENSSL_zalloc(pass_size
+ 1);
169 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
172 verify_idx
= UI_add_verify_string(ui
, prompt
,
173 UI_INPUT_FLAG_DEFAULT_PWD
,
176 if (verify_idx
< 0) {
177 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
182 switch (UI_process(ui
)) {
184 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_INTERRUPTED_OR_CANCELLED
);
187 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
190 res
= UI_get_result_length(ui
, prompt_idx
);
192 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
195 *pass_len
= (size_t)res
;
196 memcpy(pass
, ipass
, *pass_len
);
202 OPENSSL_clear_free(vpass
, pass_size
+ 1);
203 OPENSSL_clear_free(ipass
, pass_size
+ 1);
204 OPENSSL_free(prompt
);
209 /* Central pw prompting dispatcher */
210 int ossl_pw_get_passphrase(char *pass
, size_t pass_size
, size_t *pass_len
,
211 const OSSL_PARAM params
[], int verify
,
212 struct ossl_passphrase_data_st
*data
)
214 const char *source
= NULL
;
215 size_t source_len
= 0;
216 const char *prompt_info
= NULL
;
217 const UI_METHOD
*ui_method
= NULL
;
218 UI_METHOD
*allocated_ui_method
= NULL
;
219 void *ui_data
= NULL
;
220 const OSSL_PARAM
*p
= NULL
;
223 /* Handle explicit and cached passphrases */
225 if (data
->type
== is_expl_passphrase
) {
226 source
= data
->_
.expl_passphrase
.passphrase_copy
;
227 source_len
= data
->_
.expl_passphrase
.passphrase_len
;
228 } else if (data
->flag_cache_passphrase
&& data
->cached_passphrase
!= NULL
) {
229 source
= data
->cached_passphrase
;
230 source_len
= data
->cached_passphrase_len
;
233 if (source
!= NULL
) {
234 if (source_len
> pass_size
)
235 source_len
= pass_size
;
236 memcpy(pass
, source
, source_len
);
237 *pass_len
= source_len
;
241 /* Handle the is_ossl_passphrase case... that's pretty direct */
243 if (data
->type
== is_ossl_passphrase
) {
244 OSSL_PASSPHRASE_CALLBACK
*cb
= data
->_
.ossl_passphrase
.passphrase_cb
;
245 void *cbarg
= data
->_
.ossl_passphrase
.passphrase_cbarg
;
247 ret
= cb(pass
, pass_size
, pass_len
, params
, cbarg
);
251 /* Handle the is_pem_password and is_ui_method cases */
253 if ((p
= OSSL_PARAM_locate_const(params
,
254 OSSL_PASSPHRASE_PARAM_INFO
)) != NULL
) {
255 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
) {
256 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_PASSED_INVALID_ARGUMENT
,
257 "Prompt info data type incorrect");
260 prompt_info
= p
->data
;
263 if (data
->type
== is_pem_password
) {
264 /* We use a UI wrapper for PEM */
265 pem_password_cb
*cb
= data
->_
.pem_password
.password_cb
;
267 ui_method
= allocated_ui_method
=
268 UI_UTIL_wrap_read_pem_callback(cb
, verify
);
269 ui_data
= data
->_
.pem_password
.password_cbarg
;
271 if (ui_method
== NULL
) {
272 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
275 } else if (data
->type
== is_ui_method
) {
276 ui_method
= data
->_
.ui_method
.ui_method
;
277 ui_data
= data
->_
.ui_method
.ui_method_data
;
280 if (ui_method
== NULL
) {
281 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_PASSED_INVALID_ARGUMENT
,
282 "No password method specified");
286 ret
= do_ui_passphrase(pass
, pass_size
, pass_len
, prompt_info
, verify
,
289 UI_destroy_method(allocated_ui_method
);
292 if (ret
&& data
->flag_cache_passphrase
) {
293 if (data
->cached_passphrase
== NULL
294 || *pass_len
> data
->cached_passphrase_len
) {
296 OPENSSL_clear_realloc(data
->cached_passphrase
,
297 data
->cached_passphrase_len
,
300 if (new_cache
== NULL
) {
301 OPENSSL_cleanse(pass
, *pass_len
);
302 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
305 data
->cached_passphrase
= new_cache
;
307 memcpy(data
->cached_passphrase
, pass
, *pass_len
);
308 data
->cached_passphrase
[*pass_len
] = '\0';
309 data
->cached_passphrase_len
= *pass_len
;
315 static int ossl_pw_get_password(char *buf
, int size
, int rwflag
,
316 void *userdata
, const char *info
)
318 size_t password_len
= 0;
319 OSSL_PARAM params
[] = {
320 OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO
, NULL
, 0),
324 params
[0].data
= (void *)info
;
325 if (ossl_pw_get_passphrase(buf
, (size_t)size
, &password_len
, params
,
327 return (int)password_len
;
331 int ossl_pw_pem_password(char *buf
, int size
, int rwflag
, void *userdata
)
333 return ossl_pw_get_password(buf
, size
, rwflag
, userdata
, "PEM");
336 int ossl_pw_pvk_password(char *buf
, int size
, int rwflag
, void *userdata
)
338 return ossl_pw_get_password(buf
, size
, rwflag
, userdata
, "PVK");
341 int ossl_pw_passphrase_callback_enc(char *pass
, size_t pass_size
,
343 const OSSL_PARAM params
[], void *arg
)
345 return ossl_pw_get_passphrase(pass
, pass_size
, pass_len
, params
, 1, arg
);
348 int ossl_pw_passphrase_callback_dec(char *pass
, size_t pass_size
,
350 const OSSL_PARAM params
[], void *arg
)
352 return ossl_pw_get_passphrase(pass
, pass_size
, pass_len
, params
, 0, arg
);