Add a UI utility function with which to wrap pem_callback_cb in a UI_METHOD
authorRichard Levitte <levitte@openssl.org>
Tue, 6 Dec 2016 13:36:43 +0000 (14:36 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 11 Jan 2017 17:27:27 +0000 (18:27 +0100)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2204)

crypto/ui/ui_util.c
include/openssl/ui.h

index 3b51db9..70202a6 100644 (file)
@@ -49,3 +49,114 @@ int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
         ok = 0;
     return (ok);
 }
+
+/*
+ * Wrapper around pem_password_cb, a method to help older APIs use newer
+ * ones.
+ */
+struct pem_password_cb_data {
+    pem_password_cb *cb;
+    int rwflag;
+};
+
+static void ui_new_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+                               int idx, long argl, void *argp)
+{
+    /*
+     * Do nothing, the data is allocated externally and assigned later with
+     * CRYPTO_set_ex_data()
+     */
+}
+
+static int ui_dup_method_data(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
+                              void *from_d, int idx, long argl, void *argp)
+{
+    void **pptr = (void **)from_d;
+    if (*pptr != NULL)
+        *pptr = OPENSSL_memdup(*pptr, sizeof(struct pem_password_cb_data));
+    return 1;
+}
+
+static void ui_free_method_data(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+                                int idx, long argl, void *argp)
+{
+    OPENSSL_free(ptr);
+}
+
+static int ui_method_data_index()
+{
+    static int idx = -1;
+
+    if (idx == -1)
+        idx = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI_METHOD,
+                                      0, NULL,
+                                      ui_new_method_data,
+                                      ui_dup_method_data,
+                                      ui_free_method_data);
+
+    return idx;
+}
+
+static int ui_open(UI *ui)
+{
+    return 1;
+}
+static int ui_read(UI *ui, UI_STRING *uis)
+{
+    switch (UI_get_string_type(uis)) {
+    case UIT_PROMPT:
+        {
+            char result[PEM_BUFSIZE];
+            const struct pem_password_cb_data *data =
+                UI_method_get_ex_data(UI_get_method(ui),
+                                      ui_method_data_index());
+            int maxsize = UI_get_result_maxsize(uis);
+            int len = data->cb(result,
+                               maxsize > PEM_BUFSIZE ? PEM_BUFSIZE : maxsize,
+                               data->rwflag, UI_get0_user_data(ui));
+
+            if (len <= 0)
+                return len;
+            if (UI_set_result(ui, uis, result) >= 0)
+                return 1;
+            return 0;
+        }
+    case UIT_VERIFY:
+    case UIT_NONE:
+    case UIT_BOOLEAN:
+    case UIT_INFO:
+    case UIT_ERROR:
+        break;
+    }
+    return 1;
+}
+static int ui_write(UI *ui, UI_STRING *uis)
+{
+    return 1;
+}
+static int ui_close(UI *ui)
+{
+    return 1;
+}
+
+UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag)
+{
+    struct pem_password_cb_data *data = NULL;
+    UI_METHOD *ui_method = NULL;
+
+    if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
+        || (ui_method = UI_create_method("PEM password callback wrapper")) == NULL
+        || UI_method_set_opener(ui_method, ui_open) < 0
+        || UI_method_set_reader(ui_method, ui_read) < 0
+        || UI_method_set_writer(ui_method, ui_write) < 0
+        || UI_method_set_closer(ui_method, ui_close) < 0
+        || UI_method_set_ex_data(ui_method, ui_method_data_index(), data) < 0) {
+        UI_destroy_method(ui_method);
+        OPENSSL_free(data);
+        return NULL;
+    }
+    data->rwflag = rwflag;
+    data->cb = cb;
+
+    return ui_method;
+}
index ff25205..c5718d2 100644 (file)
@@ -18,6 +18,7 @@
 #   include <openssl/crypto.h>
 #  endif
 #  include <openssl/safestack.h>
+#  include <openssl/pem.h>
 #  include <openssl/ossl_typ.h>
 
 #ifdef  __cplusplus
@@ -328,6 +329,7 @@ int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
                            int verify);
 int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt,
                     int verify);
+    UI_METHOD *UI_UTIL_wrap_read_pem_callback(pem_password_cb *cb, int rwflag);
 
 /* BEGIN ERROR CODES */
 /*