From 5387b71acb833f1f635ab4a20ced0863747ef5c1 Mon Sep 17 00:00:00 2001 From: erbsland-dev Date: Fri, 30 Aug 2024 10:56:58 +0200 Subject: [PATCH] Fix Edge Cases in Password Callback Handling 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 Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/25330) --- crypto/pem/pem_pk8.c | 4 ++-- crypto/ui/ui_util.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c index 1592e351ed..6e84f0afd0 100644 --- a/crypto/pem/pem_pk8.c +++ b/crypto/pem/pem_pk8.c @@ -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; diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c index 59b00b225a..554bf79856 100644 --- a/crypto/ui/ui_util.c +++ b/crypto/ui/ui_util.c @@ -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)