]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix Edge Cases in Password Callback Handling
authorerbsland-dev <github@erbsland.dev>
Fri, 30 Aug 2024 08:56:58 +0000 (10:56 +0200)
committerTomas Mraz <tomas@openssl.org>
Mon, 9 Sep 2024 06:58:03 +0000 (08:58 +0200)
Fixes #8441: Modify the password callback handling to reserve one byte in the buffer for a null terminator, ensuring compatibility with legacy behavior that puts a terminating null byte at the end.

Additionally, validate the length returned by the callback to ensure it does not exceed the given buffer size. If the returned length is too large, the process now stops gracefully with an appropriate error, enhancing robustness by preventing crashes from out-of-bounds access.

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25330)

crypto/pem/pem_pk8.c
crypto/ui/ui_util.c

index 1592e351edef1654470e6b01e65a59dd158fb3e3..6e84f0afd05d0318538b025c46f0a0bed87bab9c 100644 (file)
@@ -173,7 +173,7 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
     X509_SIG *p8 = NULL;
     int klen;
     EVP_PKEY *ret;
-    char psbuf[PEM_BUFSIZE];
+    char psbuf[PEM_BUFSIZE + 1]; /* reserve one byte at the end */
 
     p8 = d2i_PKCS8_bio(bp, NULL);
     if (p8 == NULL)
@@ -182,7 +182,7 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
         klen = cb(psbuf, PEM_BUFSIZE, 0, u);
     else
         klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
-    if (klen < 0) {
+    if (klen < 0 || klen > PEM_BUFSIZE) {
         ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ);
         X509_SIG_free(p8);
         return NULL;
index 59b00b225adfa2c17bbb37eb113887f77344401d..554bf7985659edbdbabf087e2e712f7619a638a7 100644 (file)
@@ -105,14 +105,18 @@ static int ui_read(UI *ui, UI_STRING *uis)
     switch (UI_get_string_type(uis)) {
     case UIT_PROMPT:
         {
-            char result[PEM_BUFSIZE + 1];
+            int len;
+            char result[PEM_BUFSIZE + 1]; /* reserve one byte at the end */
             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 (maxsize > PEM_BUFSIZE)
+                maxsize = PEM_BUFSIZE;
+            len = data->cb(result, maxsize, data->rwflag,
+                           UI_get0_user_data(ui));
+            if (len > maxsize)
+                return -1;
             if (len >= 0)
                 result[len] = '\0';
             if (len < 0)