From: erbsland-dev Date: Fri, 30 Aug 2024 08:56:58 +0000 (+0200) Subject: Fix Edge Cases in Password Callback Handling X-Git-Tag: openssl-3.1.8~139 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=623b7761c75764eb03697acbe820a3e5913bd8f7;p=thirdparty%2Fopenssl.git 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) (cherry picked from commit 5387b71acb833f1f635ab4a20ced0863747ef5c1) --- diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c index 1592e351ede..6e84f0afd05 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 59b00b225ad..554bf798565 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)