diff options
Diffstat (limited to 'crypto/encode_decode/endecode_pass.c')
-rw-r--r-- | crypto/encode_decode/endecode_pass.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/crypto/encode_decode/endecode_pass.c b/crypto/encode_decode/endecode_pass.c new file mode 100644 index 0000000000..113f5eeb84 --- /dev/null +++ b/crypto/encode_decode/endecode_pass.c @@ -0,0 +1,162 @@ +/* + * 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; +} |