Compensate for UI method always adding NUL termination
authorTomas Mraz <tomas@openssl.org>
Tue, 21 Dec 2021 11:26:05 +0000 (12:26 +0100)
committerTomas Mraz <tomas@openssl.org>
Mon, 3 Jan 2022 09:35:36 +0000 (10:35 +0100)
The UI method always adds NUL termination and we need to
compensate for that when using it from a pem_password_cb
because the buffer used in pem_password_cb does not account
for that and the returned password should be able fill the
whole buffer.

Fixes #16601

Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/17320)

crypto/passphrase.c

index d61e2494405ac402f4e6b25f81d868f96c134ca6..cb1bc66958235252f484ce5786d2a77a60726395 100644 (file)
@@ -109,7 +109,8 @@ int ossl_pw_disable_passphrase_caching(struct ossl_passphrase_data_st *data)
  * 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.
+ * 2.  It allocates a buffer for password and verification on its own
+ *     to compensate for NUL terminator in UI password strings.
  * 3.  It raises errors.
  * 4.  It reports back the length of the prompted pass phrase.
  */
@@ -117,8 +118,8 @@ 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;
+    char *prompt = NULL, *ipass = NULL, *vpass = NULL;
+    int prompt_idx = -1, verify_idx = -1, res;
     UI *ui = NULL;
     int ret = 0;
 
@@ -145,9 +146,16 @@ static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len,
         goto end;
     }
 
+    /* Get a buffer for verification prompt */
+    ipass = OPENSSL_zalloc(pass_size + 1);
+    if (ipass == 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;
+                                     ipass, 0, pass_size) - 1;
     if (prompt_idx < 0) {
         ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
         goto end;
@@ -155,15 +163,15 @@ static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len,
 
     if (verify) {
         /* Get a buffer for verification prompt */
-        vpass = OPENSSL_zalloc(pass_size);
+        vpass = OPENSSL_zalloc(pass_size + 1);
         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;
+                                          vpass, 0, pass_size,
+                                          ipass) - 1;
         if (verify_idx < 0) {
             ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
             goto end;
@@ -178,13 +186,20 @@ static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len,
         ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
         break;
     default:
-        *pass_len = (size_t)UI_get_result_length(ui, prompt_idx);
+        res = UI_get_result_length(ui, prompt_idx);
+        if (res < 0) {
+            ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB);
+            break;
+        }
+        *pass_len = (size_t)res;
+        memcpy(pass, ipass, *pass_len);
         ret = 1;
         break;
     }
 
  end:
-    OPENSSL_free(vpass);
+    OPENSSL_clear_free(vpass, pass_size + 1);
+    OPENSSL_clear_free(ipass, pass_size + 1);
     OPENSSL_free(prompt);
     UI_free(ui);
     return ret;