|
@@ -0,0 +1,159 @@
|
|
|
+/*
|
|
|
+ * 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 "serializer_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;
|
|
|
+ }
|
|
|
+
|
|
|
+ UI_set_method(ui, ui_method);
|
|
|
+ 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;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Serializers typically want to get an outgoing passphrase, while
|
|
|
+ * deserializers typically want to get en incoming passphrase.
|
|
|
+ */
|
|
|
+int ossl_serializer_passphrase_out_cb(char *pass, size_t pass_size,
|
|
|
+ size_t *pass_len,
|
|
|
+ const OSSL_PARAM params[], void *arg)
|
|
|
+{
|
|
|
+ OSSL_SERIALIZER_CTX *ctx = arg;
|
|
|
+
|
|
|
+ if (!ossl_assert(ctx != NULL)) {
|
|
|
+ ERR_raise(ERR_LIB_OSSL_SERIALIZER, 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_SERIALIZER);
|
|
|
+}
|
|
|
+
|
|
|
+int ossl_deserializer_passphrase_in_cb(char *pass, size_t pass_size,
|
|
|
+ size_t *pass_len,
|
|
|
+ const OSSL_PARAM params[], void *arg)
|
|
|
+{
|
|
|
+ OSSL_DESERIALIZER_CTX *ctx = arg;
|
|
|
+
|
|
|
+ if (!ossl_assert(ctx != NULL)) {
|
|
|
+ ERR_raise(ERR_LIB_OSSL_DESERIALIZER, 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_DESERIALIZER, 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_DESERIALIZER)) {
|
|
|
+ memcpy(ctx->cached_passphrase, pass, *pass_len);
|
|
|
+ ctx->cached_passphrase_len = *pass_len;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|