openssl/crypto/encode_decode/endecode_pass.c

163 lines
4.9 KiB
C

/*
* 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;
}