cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \
ctype.c threads_pthread.c threads_win.c threads_none.c initthread.c \
context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM \
- param_build_set.c der_writer.c
+ param_build_set.c der_writer.c passphrase.c
$UTIL_DEFINE=$CPUIDDEF
SOURCE[../libcrypto]=$UTIL_COMMON \
-SOURCE[../../libcrypto]=endecode_pass.c
-
SOURCE[../../libcrypto]=encoder_meth.c encoder_lib.c encoder_pkey.c
-SOURCE[../../libcrypto]=decoder_meth.c decoder_lib.c \
- decoder_pkey.c
+SOURCE[../../libcrypto]=decoder_meth.c decoder_lib.c decoder_pkey.c
SOURCE[../../libcrypto]=encoder_err.c
SOURCE[../../libcrypto]=decoder_err.c
#include <openssl/bio.h>
#include <openssl/params.h>
#include <openssl/provider.h>
+#include "internal/passphrase.h"
#include "encoder_local.h"
#include "e_os.h"
data.ctx = ctx;
data.bio = in;
+ /* Enable passphrase caching */
+ (void)ossl_pw_enable_passphrase_caching(&ctx->pwdata);
+
ok = decoder_process(NULL, &data);
/* Clear any internally cached passphrase */
- if (!ctx->flag_user_passphrase) {
- OSSL_DECODER_CTX_set_passphrase(ctx, NULL, 0);
- ctx->flag_user_passphrase = 0;
- }
+ (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
+
return ok;
}
new_data.current_deser_inst_index = i;
ok = new_deser->decode(new_deser_inst->deserctx, (OSSL_CORE_BIO *)bio,
decoder_process, &new_data,
- ctx->passphrase_cb, new_data.ctx);
+ ossl_pw_passphrase_callback_dec,
+ &new_data.ctx->pwdata);
if (ok)
break;
}
return NULL;
}
- ctx->passphrase_cb = ossl_decoder_passphrase_in_cb;
return ctx;
}
ctx->cleanup(ctx->construct_data);
sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts,
OSSL_DECODER_INSTANCE_free);
- OSSL_DECODER_CTX_set_passphrase_ui(ctx, NULL, NULL);
- OSSL_DECODER_CTX_set_passphrase(ctx, NULL, 0);
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
OPENSSL_free(ctx);
}
}
const unsigned char *kstr,
size_t klen)
{
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- OPENSSL_clear_free(ctx->cached_passphrase, ctx->cached_passphrase_len);
- ctx->cached_passphrase = NULL;
- ctx->cached_passphrase_len = 0;
- if (kstr != NULL) {
- if (klen == 0) {
- ctx->cached_passphrase = OPENSSL_zalloc(1);
- ctx->cached_passphrase_len = 0;
- } else {
- ctx->cached_passphrase = OPENSSL_memdup(kstr, klen);
- ctx->cached_passphrase_len = klen;
- }
- if (ctx->cached_passphrase == NULL) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- }
- ctx->flag_user_passphrase = 1;
- return 1;
-}
-
-static void decoder_ctx_reset_passphrase_ui(OSSL_DECODER_CTX *ctx)
-{
- UI_destroy_method(ctx->allocated_ui_method);
- ctx->allocated_ui_method = NULL;
- ctx->ui_method = NULL;
- ctx->ui_data = NULL;
+ return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen);
}
int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data)
{
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- decoder_ctx_reset_passphrase_ui(ctx);
- ctx->ui_method = ui_method;
- ctx->ui_data = ui_data;
- return 1;
+ return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data);
}
int OSSL_DECODER_CTX_set_pem_password_cb(OSSL_DECODER_CTX *ctx,
pem_password_cb *cb, void *cbarg)
{
- UI_METHOD *ui_method = NULL;
-
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- /*
- * If |cb| is NULL, it means the caller wants to reset previous
- * password callback info. Otherwise, we only set the new data
- * if a new UI_METHOD could be created for this sort of callback.
- */
- if (cb == NULL
- || (ui_method = UI_UTIL_wrap_read_pem_callback(cb, 0)) != NULL) {
- decoder_ctx_reset_passphrase_ui(ctx);
- ctx->ui_method = ctx->allocated_ui_method = ui_method;
- ctx->ui_data = cbarg;
- ctx->passphrase_cb = ossl_decoder_passphrase_in_cb;
- return 1;
- }
-
- return 0;
+ return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg);
}
/*
#include <openssl/encoder.h>
#include <openssl/decoder.h>
#include "internal/cryptlib.h"
+#include "internal/passphrase.h"
#include "internal/refcount.h"
struct ossl_serdes_base_st {
int (*do_output)(OSSL_ENCODER_CTX *ctx, BIO *out);
/* For any function that needs a passphrase reader */
- const UI_METHOD *ui_method;
- void *ui_data;
- /*
- * if caller used OSSL_ENCODER_CTX_set_passphrase_cb(), we need
- * intermediary storage.
- */
- UI_METHOD *allocated_ui_method;
+ struct ossl_passphrase_data_st pwdata;
};
struct ossl_decoder_instance_st {
void *construct_data;
/* For any function that needs a passphrase reader */
- OSSL_PASSPHRASE_CALLBACK *passphrase_cb;
- const UI_METHOD *ui_method;
- void *ui_data;
- /*
- * if caller used OSSL_ENCODER_CTX_set_pem_password_cb(), we need
- * intermediary storage.
- */
- UI_METHOD *allocated_ui_method;
- /*
- * Because the same input may pass through more than one decoder,
- * we cache any passphrase passed to us. The desrializing processor
- * must clear this at the end of a run.
- */
- unsigned char *cached_passphrase;
- size_t cached_passphrase_len;
-
- /*
- * Flag section. Keep these together
- */
-
- /*
- * The passphrase was passed to us by the user. In that case, it
- * should only be freed when freeing this context.
- */
- unsigned int flag_user_passphrase:1;
+ struct ossl_passphrase_data_st pwdata;
};
-
-/* Passphrase callbacks, found in serdes_pass.c */
-
-/*
- * Encoders typically want to get an outgoing passphrase, while
- * decoders typically want to get en incoming passphrase.
- */
-OSSL_PASSPHRASE_CALLBACK ossl_encoder_passphrase_out_cb;
-OSSL_PASSPHRASE_CALLBACK ossl_decoder_passphrase_in_cb;
if (ctx->encoder != NULL && ctx->encoder->freectx != NULL)
ctx->encoder->freectx(ctx->serctx);
OSSL_ENCODER_free(ctx->encoder);
- UI_destroy_method(ctx->allocated_ui_method);
+ ossl_pw_clear_passphrase_data(&ctx->pwdata);
OPENSSL_free(ctx);
}
}
return OSSL_ENCODER_CTX_set_params(ctx, params);
}
-static void encoder_ctx_reset_passphrase_ui(OSSL_ENCODER_CTX *ctx)
-{
- UI_destroy_method(ctx->allocated_ui_method);
- ctx->allocated_ui_method = NULL;
- ctx->ui_method = NULL;
- ctx->ui_data = NULL;
-}
-
int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,
const UI_METHOD *ui_method,
void *ui_data)
{
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- encoder_ctx_reset_passphrase_ui(ctx);
- ctx->ui_method = ui_method;
- ctx->ui_data = ui_data;
- return 1;
+ return ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data);
}
int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
pem_password_cb *cb, void *cbarg)
{
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- encoder_ctx_reset_passphrase_ui(ctx);
- if (cb == NULL)
- return 1;
- ctx->ui_method =
- ctx->allocated_ui_method = UI_UTIL_wrap_read_pem_callback(cb, 1);
- ctx->ui_data = cbarg;
-
- return ctx->ui_method != NULL;
+ return ossl_pw_set_pem_password_cb(&ctx->pwdata, cb, cbarg);
}
/*
BIO *out = write_data->out;
return ctx->encoder->encode_data(ctx->serctx, params, (OSSL_CORE_BIO *)out,
- ossl_encoder_passphrase_out_cb, ctx);
+ ossl_pw_passphrase_callback_enc,
+ &ctx->pwdata);
}
/*
return ctx->encoder->encode_object(ctx->serctx, keydata,
(OSSL_CORE_BIO *)out,
- ossl_encoder_passphrase_out_cb, ctx);
+ ossl_pw_passphrase_callback_enc,
+ &ctx->pwdata);
}
/*
+++ /dev/null
-/*
- * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/err.h>
-#include <openssl/ui.h>
-#include <openssl/core_names.h>
-#include "internal/cryptlib.h"
-#include "encoder_local.h"
-
-/* Passphrase callbacks for any who need it */
-
-/*
- * First, define the generic passphrase function that supports both
- * outgoing (with passphrase verify) and incoming (without passphrase
- * verify) passphrase reading.
- */
-static int do_passphrase(char *pass, size_t pass_size, size_t *pass_len,
- const OSSL_PARAM params[], void *arg, int verify,
- const UI_METHOD *ui_method, void *ui_data, int errlib)
-{
- const OSSL_PARAM *p;
- const char *prompt_info = NULL;
- char *prompt = NULL, *vpass = NULL;
- int prompt_idx = -1, verify_idx = -1;
- UI *ui = NULL;
- int ret = 0;
-
- if (!ossl_assert(pass != NULL && pass_size != 0 && pass_len != NULL)) {
- ERR_raise(errlib, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- if ((p = OSSL_PARAM_locate_const(params,
- OSSL_PASSPHRASE_PARAM_INFO)) != NULL) {
- if (p->data_type != OSSL_PARAM_UTF8_STRING)
- return 0;
- prompt_info = p->data;
- }
-
- if ((ui = UI_new()) == NULL) {
- ERR_raise(errlib, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- if (ui_method != NULL) {
- UI_set_method(ui, ui_method);
- if (ui_data != NULL)
- UI_add_user_data(ui, ui_data);
- }
-
- /* Get an application constructed prompt */
- prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
- if (prompt == NULL) {
- ERR_raise(errlib, ERR_R_MALLOC_FAILURE);
- goto end;
- }
-
- prompt_idx = UI_add_input_string(ui, prompt,
- UI_INPUT_FLAG_DEFAULT_PWD,
- pass, 0, pass_size - 1) - 1;
- if (prompt_idx < 0) {
- ERR_raise(errlib, ERR_R_UI_LIB);
- goto end;
- }
-
- if (verify) {
- /* Get a buffer for verification prompt */
- vpass = OPENSSL_zalloc(pass_size);
- if (vpass == NULL) {
- ERR_raise(errlib, ERR_R_MALLOC_FAILURE);
- goto end;
- }
- verify_idx = UI_add_verify_string(ui, prompt,
- UI_INPUT_FLAG_DEFAULT_PWD,
- vpass, 0, pass_size - 1,
- pass) - 1;
- if (verify_idx < 0) {
- ERR_raise(errlib, ERR_R_UI_LIB);
- goto end;
- }
- }
-
- switch (UI_process(ui)) {
- case -2:
- ERR_raise(errlib, ERR_R_INTERRUPTED_OR_CANCELLED);
- break;
- case -1:
- ERR_raise(errlib, ERR_R_UI_LIB);
- break;
- default:
- *pass_len = (size_t)UI_get_result_length(ui, prompt_idx);
- ret = 1;
- break;
- }
-
- end:
- OPENSSL_free(vpass);
- OPENSSL_free(prompt);
- UI_free(ui);
- return ret;
-}
-
-/*
- * Encoders typically want to get an outgoing passphrase, while
- * decoders typically want to get en incoming passphrase.
- */
-int ossl_encoder_passphrase_out_cb(char *pass, size_t pass_size,
- size_t *pass_len,
- const OSSL_PARAM params[], void *arg)
-{
- OSSL_ENCODER_CTX *ctx = arg;
-
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- return do_passphrase(pass, pass_size, pass_len, params, arg, 1,
- ctx->ui_method, ctx->ui_data,
- ERR_LIB_OSSL_ENCODER);
-}
-
-int ossl_decoder_passphrase_in_cb(char *pass, size_t pass_size,
- size_t *pass_len,
- const OSSL_PARAM params[], void *arg)
-{
- OSSL_DECODER_CTX *ctx = arg;
-
- if (!ossl_assert(ctx != NULL)) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- if (ctx->cached_passphrase != NULL) {
- size_t len = ctx->cached_passphrase_len;
-
- if (len > pass_size)
- len = pass_size;
- memcpy(pass, ctx->cached_passphrase, len);
- *pass_len = len;
- return 1;
- } else {
- if ((ctx->cached_passphrase = OPENSSL_zalloc(pass_size)) == NULL) {
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- }
- if (do_passphrase(pass, pass_size, pass_len, params, arg, 0,
- ctx->ui_method, ctx->ui_data,
- ERR_LIB_OSSL_DECODER)) {
- memcpy(ctx->cached_passphrase, pass, *pass_len);
- ctx->cached_passphrase_len = *pass_len;
- return 1;
- }
- return 0;
-}
--- /dev/null
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/ui.h>
+#include <openssl/core_names.h>
+#include "internal/cryptlib.h"
+#include "internal/passphrase.h"
+
+void ossl_pw_clear_passphrase_data(struct ossl_passphrase_data_st *data)
+{
+ if (data != NULL) {
+ if (data->type == is_expl_passphrase)
+ OPENSSL_clear_free(data->_.expl_passphrase.passphrase_copy,
+ data->_.expl_passphrase.passphrase_len);
+ ossl_pw_clear_passphrase_cache(data);
+ memset(data, 0, sizeof(*data));
+ }
+}
+
+void ossl_pw_clear_passphrase_cache(struct ossl_passphrase_data_st *data)
+{
+ OPENSSL_clear_free(data->cached_passphrase, data->cached_passphrase_len);
+ data->cached_passphrase = NULL;
+}
+
+int ossl_pw_set_passphrase(struct ossl_passphrase_data_st *data,
+ const unsigned char *passphrase,
+ size_t passphrase_len)
+{
+ if (!ossl_assert(data != NULL && passphrase != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_expl_passphrase;
+ data->_.expl_passphrase.passphrase_copy =
+ OPENSSL_memdup(passphrase, passphrase_len);
+ if (data->_.expl_passphrase.passphrase_copy == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ data->_.expl_passphrase.passphrase_len = passphrase_len;
+ return 1;
+}
+
+int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st *data,
+ pem_password_cb *cb, void *cbarg)
+{
+ if (!ossl_assert(data != NULL && cb != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_pem_password;
+ data->_.pem_password.password_cb = cb;
+ data->_.pem_password.password_cbarg = cbarg;
+ return 1;
+}
+
+int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st *data,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+ if (!ossl_assert(data != NULL && cb != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_ossl_passphrase;
+ data->_.ossl_passphrase.passphrase_cb = cb;
+ data->_.ossl_passphrase.passphrase_cbarg = cbarg;
+ return 1;
+}
+
+int ossl_pw_set_ui_method(struct ossl_passphrase_data_st *data,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ if (!ossl_assert(data != NULL && ui_method != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ ossl_pw_clear_passphrase_data(data);
+ data->type = is_ui_method;
+ data->_.ui_method.ui_method = ui_method;
+ data->_.ui_method.ui_method_data = ui_data;
+ return 1;
+}
+
+int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st *data)
+{
+ data->flag_cache_passphrase = 1;
+ return 1;
+}
+
+int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st *data)
+{
+ data->flag_cache_passphrase = 0;
+ return 1;
+}
+
+
+/*-
+ * UI_METHOD processor. It differs from UI_UTIL_read_pw() like this:
+ *
+ * 1. It constructs a prompt on its own, based on |prompt_info|.
+ * 2. It allocates a buffer for verification on its own.
+ * 3. It raises errors.
+ * 4. It reports back the length of the prompted pass phrase.
+ */
+static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len,
+ const char *prompt_info, int verify,
+ const UI_METHOD *ui_method, void *ui_data)
+{
+ char *prompt = NULL, *vpass = NULL;
+ int prompt_idx = -1, verify_idx = -1;
+ UI *ui = NULL;
+ int ret = 0;
+
+ if (!ossl_assert(pass != NULL && pass_size != 0 && pass_len != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if ((ui = UI_new()) == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ui_method != NULL) {
+ UI_set_method(ui, ui_method);
+ if (ui_data != NULL)
+ UI_add_user_data(ui, ui_data);
+ }
+
+ /* Get an application constructed prompt */
+ prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
+ if (prompt == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ prompt_idx = UI_add_input_string(ui, prompt,
+ UI_INPUT_FLAG_DEFAULT_PWD,
+ pass, 0, pass_size - 1) - 1;
+ if (prompt_idx < 0) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ goto end;
+ }
+
+ if (verify) {
+ /* Get a buffer for verification prompt */
+ vpass = OPENSSL_zalloc(pass_size);
+ if (vpass == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ verify_idx = UI_add_verify_string(ui, prompt,
+ UI_INPUT_FLAG_DEFAULT_PWD,
+ vpass, 0, pass_size - 1,
+ pass) - 1;
+ if (verify_idx < 0) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ goto end;
+ }
+ }
+
+ switch (UI_process(ui)) {
+ case -2:
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERRUPTED_OR_CANCELLED);
+ break;
+ case -1:
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+ break;
+ default:
+ *pass_len = (size_t)UI_get_result_length(ui, prompt_idx);
+ ret = 1;
+ break;
+ }
+
+ end:
+ OPENSSL_free(vpass);
+ OPENSSL_free(prompt);
+ UI_free(ui);
+ return ret;
+}
+
+/* Central pw prompting dispatcher */
+int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len,
+ const OSSL_PARAM params[], int verify,
+ struct ossl_passphrase_data_st *data)
+{
+ const char *source = NULL;
+ size_t source_len = 0;
+ const char *prompt_info = NULL;
+ const UI_METHOD *ui_method = NULL;
+ UI_METHOD *allocated_ui_method = NULL;
+ void *ui_data = NULL;
+ const OSSL_PARAM *p = NULL;
+ int ret;
+
+ /* Handle explicit and cached passphrases */
+
+ if (data->type == is_expl_passphrase) {
+ source = data->_.expl_passphrase.passphrase_copy;
+ source_len = data->_.expl_passphrase.passphrase_len;
+ } else if (data->flag_cache_passphrase && data->cached_passphrase != NULL) {
+ source = data->cached_passphrase;
+ source_len = data->cached_passphrase_len;
+ }
+
+ if (source != NULL) {
+ if (source_len > pass_size)
+ source_len = pass_size;
+ memcpy(pass, source, source_len);
+ *pass_len = source_len;
+ return 1;
+ }
+
+ /* Handle the is_ossl_passphrase case... that's pretty direct */
+
+ if (data->type == is_ossl_passphrase) {
+ OSSL_PASSPHRASE_CALLBACK *cb = data->_.ossl_passphrase.passphrase_cb;
+ void *cbarg = data->_.ossl_passphrase.passphrase_cbarg;
+
+ ret = cb(pass, pass_size, pass_len, params, cbarg);
+ goto do_cache;
+ }
+
+ /* Handle the is_pem_password and is_ui_method cases */
+
+ if ((p = OSSL_PARAM_locate_const(params,
+ OSSL_PASSPHRASE_PARAM_INFO)) != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING) {
+ ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
+ "Prompt info data type incorrect");
+ return 0;
+ }
+ prompt_info = p->data;
+ }
+
+ if (data->type == is_pem_password) {
+ /* We use a UI wrapper for PEM */
+ pem_password_cb *cb = data->_.pem_password.password_cb;
+
+ ui_method = allocated_ui_method =
+ UI_UTIL_wrap_read_pem_callback(cb, verify);
+ ui_data = data->_.pem_password.password_cbarg;
+
+ if (ui_method == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (data->type == is_ui_method) {
+ ui_method = data->_.ui_method.ui_method;
+ ui_data = data->_.ui_method.ui_method_data;
+ }
+
+ if (ui_method == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ret = do_ui_passphrase(pass, pass_size, pass_len, prompt_info, verify,
+ ui_method, ui_data);
+
+ UI_destroy_method(allocated_ui_method);
+
+ do_cache:
+ if (ret && data->flag_cache_passphrase) {
+ if (*pass_len > data->cached_passphrase_len) {
+ void *new_cache =
+ OPENSSL_clear_realloc(data->cached_passphrase,
+ data->cached_passphrase_len,
+ *pass_len + 1);
+
+ if (new_cache == NULL) {
+ OPENSSL_cleanse(pass, *pass_len);
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ data->cached_passphrase = new_cache;
+ }
+ memcpy(data->cached_passphrase, pass, *pass_len);
+ data->cached_passphrase[*pass_len] = '\0';
+ data->cached_passphrase_len = *pass_len;
+ }
+
+ return ret;
+}
+
+int ossl_pw_pem_password(char *buf, int size, int rwflag, void *userdata)
+{
+ size_t password_len = 0;
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO, NULL, 0),
+ OSSL_PARAM_END
+ };
+
+ params[0].data = "PEM";
+ if (ossl_pw_get_passphrase(buf, (size_t)size, &password_len, params,
+ rwflag, userdata))
+ return (int)password_len;
+ return -1;
+}
+
+int ossl_pw_passphrase_callback_enc(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[], void *arg)
+{
+ return ossl_pw_get_passphrase(pass, pass_size, pass_len, params, 1, arg);
+}
+
+int ossl_pw_passphrase_callback_dec(char *pass, size_t pass_size,
+ size_t *pass_len,
+ const OSSL_PARAM params[], void *arg)
+{
+ return ossl_pw_get_passphrase(pass, pass_size, pass_len, params, 0, arg);
+}
--- /dev/null
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_PASSPHRASE_H
+# define OSSL_INTERNAL_PASSPHRASE_H
+
+/*
+ * This is a passphrase reader bridge with bells and whistles.
+ *
+ * On one hand, an API may wish to offer all sorts of passphrase callback
+ * possibilities to users, or may have to do so for historical reasons.
+ * On the other hand, that same API may have demands from other interfaces,
+ * notably from the libcrypto <-> provider interface, which uses
+ * OSSL_PASSPHRASE_CALLBACK consistently.
+ *
+ * The structure and functions below are the fundaments for bridging one
+ * passphrase callback form to another.
+ *
+ * In addition, extra features are included (this may be a growing list):
+ *
+ * - password caching. This is to be used by APIs where it's likely
+ * that the same passphrase may be asked for more than once, but the
+ * user shouldn't get prompted more than once. For example, this is
+ * useful for OSSL_DECODER, which may have to use a passphrase while
+ * trying to find out what input it has.
+ */
+
+/*
+ * Structure to hold whatever the calling user may specify. This structure
+ * is intended to be integrated into API specific structures or to be used
+ * as a local on-stack variable type. Therefore, no functions to allocate
+ * or freed it on the heap is offered.
+ */
+struct ossl_passphrase_data_st {
+ enum {
+ is_expl_passphrase = 1, /* Explicit passphrase given by user */
+ is_pem_password, /* pem_password_cb given by user */
+ is_ossl_passphrase, /* OSSL_PASSPHRASE_CALLBACK given by user */
+ is_ui_method /* UI_METHOD given by user */
+ } type;
+ union {
+ struct {
+ char *passphrase_copy;
+ size_t passphrase_len;
+ } expl_passphrase;
+
+ struct {
+ pem_password_cb *password_cb;
+ void *password_cbarg;
+ } pem_password;
+
+ struct {
+ OSSL_PASSPHRASE_CALLBACK *passphrase_cb;
+ void *passphrase_cbarg;
+ } ossl_passphrase;
+
+ struct {
+ const UI_METHOD *ui_method;
+ void *ui_method_data;
+ } ui_method;
+ } _;
+
+ /*-
+ * Flags section
+ */
+
+ /* Set to indicate that caching should be done */
+ unsigned int flag_cache_passphrase:1;
+
+ /*-
+ * Misc section: caches and other
+ */
+
+ char *cached_passphrase;
+ size_t cached_passphrase_len;
+};
+
+/* Structure manipulation */
+
+void ossl_pw_clear_passphrase_data(struct ossl_passphrase_data_st *data);
+void ossl_pw_clear_passphrase_cache(struct ossl_passphrase_data_st *data);
+
+int ossl_pw_set_passphrase(struct ossl_passphrase_data_st *data,
+ const unsigned char *passphrase,
+ size_t passphrase_len);
+int ossl_pw_set_pem_password_cb(struct ossl_passphrase_data_st *data,
+ pem_password_cb *cb, void *cbarg);
+int ossl_pw_set_ossl_passphrase_cb(struct ossl_passphrase_data_st *data,
+ OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg);
+int ossl_pw_set_ui_method(struct ossl_passphrase_data_st *data,
+ const UI_METHOD *ui_method, void *ui_data);
+
+int ossl_pw_enable_passphrase_caching(struct ossl_passphrase_data_st *data);
+int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st *data);
+
+/* Central function for direct calls */
+
+int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len,
+ const OSSL_PARAM params[], int verify,
+ struct ossl_passphrase_data_st *data);
+
+/* Callback functions */
+
+/*
+ * All of these callback expect that the callback argument is a
+ * struct ossl_passphrase_data_st
+ */
+
+pem_password_cb ossl_pw_pem_password;
+/* One callback for encoding (verification prompt) and one for decoding */
+OSSL_PASSPHRASE_CALLBACK ossl_pw_passphrase_callback_enc;
+OSSL_PASSPHRASE_CALLBACK ossl_pw_passphrase_callback_dec;
+
+#endif
#include "internal/pem.h" /* For internal PVK and "blob" functions */
#include "internal/cryptlib.h"
#include "crypto/asn1.h"
+#include "internal/passphrase.h"
#include "prov/bio.h" /* ossl_prov_bio_printf() */
#include "prov/providercommonerr.h" /* PROV_R_READ_KEY */
#include "encoder_local.h"
return pkey;
}
-struct pwdata_st {
- OSSL_PASSPHRASE_CALLBACK *pw_cb;
- void *pw_cbarg;
-};
-
-pem_password_cb pw_pem_password_to_ossl_passhrase;
-int pw_pem_password_to_ossl_passhrase(char *buf, int size, int rwflag,
- void *userdata)
-{
- struct pwdata_st *data = userdata;
- size_t pw_len = 0;
- static char prompt_info[] = "pass phrase";
- OSSL_PARAM params[] = {
- OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO, prompt_info,
- sizeof(prompt_info) - 1),
- OSSL_PARAM_END
- };
- int ok = data->pw_cb(buf, (size_t)size, &pw_len, params, data->pw_cbarg);
-
- if (ok)
- return (int)pw_len;
- else
- return -1;
-}
-
# ifndef OPENSSL_NO_RC4
EVP_PKEY *ossl_prov_read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
- BIO *in = bio_new_from_core_bio(provctx, cin);
+ BIO *in = NULL;
EVP_PKEY *pkey = NULL;
- struct pwdata_st pwdata;
+ struct ossl_passphrase_data_st pwdata;
- pwdata.pw_cb = pw_cb;
- pwdata.pw_cbarg = pw_cbarg;
- pkey = b2i_PVK_bio(in, pw_pem_password_to_ossl_passhrase, &pwdata);
+ memset(&pwdata, 0, sizeof(pwdata));
+ if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
+ return NULL;
+ in = bio_new_from_core_bio(provctx, cin);
+ pkey = b2i_PVK_bio(in, ossl_pw_pem_password, &pwdata);
BIO_free(in);
+
return pkey;
}
# endif