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
)
48 data
->_
.expl_passphrase
.passphrase_len
= passphrase_len
;
52 int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st
*data
,
53 pem_password_cb
*cb
, void *cbarg
)
55 if (!ossl_assert(data
!= NULL
&& cb
!= NULL
)) {
56 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
59 ossl_pw_clear_passphrase_data(data
);
60 data
->type
= is_pem_password
;
61 data
->_
.pem_password
.password_cb
= cb
;
62 data
->_
.pem_password
.password_cbarg
= cbarg
;
66 int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st
*data
,
67 OSSL_PASSPHRASE_CALLBACK
*cb
, void *cbarg
)
69 if (!ossl_assert(data
!= NULL
&& cb
!= NULL
)) {
70 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
73 ossl_pw_clear_passphrase_data(data
);
74 data
->type
= is_ossl_passphrase
;
75 data
->_
.ossl_passphrase
.passphrase_cb
= cb
;
76 data
->_
.ossl_passphrase
.passphrase_cbarg
= cbarg
;
80 int ossl_pw_set_ui_method(struct ossl_passphrase_data_st
*data
,
81 const UI_METHOD
*ui_method
, void *ui_data
)
83 if (!ossl_assert(data
!= NULL
&& ui_method
!= NULL
)) {
84 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
87 ossl_pw_clear_passphrase_data(data
);
88 data
->type
= is_ui_method
;
89 data
->_
.ui_method
.ui_method
= ui_method
;
90 data
->_
.ui_method
.ui_method_data
= ui_data
;
94 int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st
*data
)
96 data
->flag_cache_passphrase
= 1;
100 int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st
*data
)
102 data
->flag_cache_passphrase
= 0;
108 * UI_METHOD processor. It differs from UI_UTIL_read_pw() like this:
110 * 1. It constructs a prompt on its own, based on |prompt_info|.
111 * 2. It allocates a buffer for password and verification on its own
112 * to compensate for NUL terminator in UI password strings.
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
, *ipass
= NULL
, *vpass
= NULL
;
121 int prompt_idx
= -1, verify_idx
= -1, res
;
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_UI_LIB
);
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_UI_LIB
);
148 /* Get a buffer for verification prompt */
149 ipass
= OPENSSL_zalloc(pass_size
+ 1);
153 prompt_idx
= UI_add_input_string(ui
, prompt
,
154 UI_INPUT_FLAG_DEFAULT_PWD
,
155 ipass
, 0, pass_size
) - 1;
156 if (prompt_idx
< 0) {
157 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
162 /* Get a buffer for verification prompt */
163 vpass
= OPENSSL_zalloc(pass_size
+ 1);
166 verify_idx
= UI_add_verify_string(ui
, prompt
,
167 UI_INPUT_FLAG_DEFAULT_PWD
,
170 if (verify_idx
< 0) {
171 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
176 switch (UI_process(ui
)) {
178 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_INTERRUPTED_OR_CANCELLED
);
181 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
184 res
= UI_get_result_length(ui
, prompt_idx
);
186 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
189 *pass_len
= (size_t)res
;
190 memcpy(pass
, ipass
, *pass_len
);
196 OPENSSL_clear_free(vpass
, pass_size
+ 1);
197 OPENSSL_clear_free(ipass
, pass_size
+ 1);
198 OPENSSL_free(prompt
);
203 /* Central pw prompting dispatcher */
204 int ossl_pw_get_passphrase(char *pass
, size_t pass_size
, size_t *pass_len
,
205 const OSSL_PARAM params
[], int verify
,
206 struct ossl_passphrase_data_st
*data
)
208 const char *source
= NULL
;
209 size_t source_len
= 0;
210 const char *prompt_info
= NULL
;
211 const UI_METHOD
*ui_method
= NULL
;
212 UI_METHOD
*allocated_ui_method
= NULL
;
213 void *ui_data
= NULL
;
214 const OSSL_PARAM
*p
= NULL
;
217 /* Handle explicit and cached passphrases */
219 if (data
->type
== is_expl_passphrase
) {
220 source
= data
->_
.expl_passphrase
.passphrase_copy
;
221 source_len
= data
->_
.expl_passphrase
.passphrase_len
;
222 } else if (data
->flag_cache_passphrase
&& data
->cached_passphrase
!= NULL
) {
223 source
= data
->cached_passphrase
;
224 source_len
= data
->cached_passphrase_len
;
227 if (source
!= NULL
) {
228 if (source_len
> pass_size
)
229 source_len
= pass_size
;
230 memcpy(pass
, source
, source_len
);
231 *pass_len
= source_len
;
235 /* Handle the is_ossl_passphrase case... that's pretty direct */
237 if (data
->type
== is_ossl_passphrase
) {
238 OSSL_PASSPHRASE_CALLBACK
*cb
= data
->_
.ossl_passphrase
.passphrase_cb
;
239 void *cbarg
= data
->_
.ossl_passphrase
.passphrase_cbarg
;
241 ret
= cb(pass
, pass_size
, pass_len
, params
, cbarg
);
245 /* Handle the is_pem_password and is_ui_method cases */
247 if ((p
= OSSL_PARAM_locate_const(params
,
248 OSSL_PASSPHRASE_PARAM_INFO
)) != NULL
) {
249 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
) {
250 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_PASSED_INVALID_ARGUMENT
,
251 "Prompt info data type incorrect");
254 prompt_info
= p
->data
;
257 if (data
->type
== is_pem_password
) {
258 /* We use a UI wrapper for PEM */
259 pem_password_cb
*cb
= data
->_
.pem_password
.password_cb
;
261 ui_method
= allocated_ui_method
=
262 UI_UTIL_wrap_read_pem_callback(cb
, verify
);
263 ui_data
= data
->_
.pem_password
.password_cbarg
;
265 if (ui_method
== NULL
) {
266 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_UI_LIB
);
269 } else if (data
->type
== is_ui_method
) {
270 ui_method
= data
->_
.ui_method
.ui_method
;
271 ui_data
= data
->_
.ui_method
.ui_method_data
;
274 if (ui_method
== NULL
) {
275 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_PASSED_INVALID_ARGUMENT
,
276 "No password method specified");
280 ret
= do_ui_passphrase(pass
, pass_size
, pass_len
, prompt_info
, verify
,
283 UI_destroy_method(allocated_ui_method
);
286 if (ret
&& data
->flag_cache_passphrase
) {
287 if (data
->cached_passphrase
== NULL
288 || *pass_len
> data
->cached_passphrase_len
) {
290 OPENSSL_clear_realloc(data
->cached_passphrase
,
291 data
->cached_passphrase_len
,
294 if (new_cache
== NULL
) {
295 OPENSSL_cleanse(pass
, *pass_len
);
298 data
->cached_passphrase
= new_cache
;
300 memcpy(data
->cached_passphrase
, pass
, *pass_len
);
301 data
->cached_passphrase
[*pass_len
] = '\0';
302 data
->cached_passphrase_len
= *pass_len
;
308 static int ossl_pw_get_password(char *buf
, int size
, int rwflag
,
309 void *userdata
, const char *info
)
311 size_t password_len
= 0;
312 OSSL_PARAM params
[] = {
313 OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO
, NULL
, 0),
317 params
[0].data
= (void *)info
;
318 if (ossl_pw_get_passphrase(buf
, (size_t)size
, &password_len
, params
,
320 return (int)password_len
;
324 int ossl_pw_pem_password(char *buf
, int size
, int rwflag
, void *userdata
)
326 return ossl_pw_get_password(buf
, size
, rwflag
, userdata
, "PEM");
329 int ossl_pw_pvk_password(char *buf
, int size
, int rwflag
, void *userdata
)
331 return ossl_pw_get_password(buf
, size
, rwflag
, userdata
, "PVK");
334 int ossl_pw_passphrase_callback_enc(char *pass
, size_t pass_size
,
336 const OSSL_PARAM params
[], void *arg
)
338 return ossl_pw_get_passphrase(pass
, pass_size
, pass_len
, params
, 1, arg
);
341 int ossl_pw_passphrase_callback_dec(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
, 0, arg
);