From 7d4444969a0c7b3677be8d4f2e272d60b41a625f Mon Sep 17 00:00:00 2001 From: ShenYage Date: Mon, 15 Apr 2024 20:06:51 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20CVE-2023-6237=E3=80=81CVE-2024-2511?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ShenYage --- ...dd-a-test-for-session-cache-handling.patch | 133 ++++++++++++++ ..._resume-test-for-simultaneous-resump.patch | 160 ++++++++++++++++ ...ined-session-cache-growth-in-TLSv1.3.patch | 122 +++++++++++++ ...dening-around-not_resumable-sessions.patch | 39 ++++ ...dd-a-test-for-session-cache-overflow.patch | 172 ++++++++++++++++++ ...ecution-time-of-RSA-public-key-check.patch | 126 +++++++++++++ edk2.spec | 13 +- 7 files changed, 764 insertions(+), 1 deletion(-) create mode 100644 0040-Add-a-test-for-session-cache-handling.patch create mode 100644 0041-Extend-the-multi_resume-test-for-simultaneous-resump.patch create mode 100644 0042-Fix-unconstrained-session-cache-growth-in-TLSv1.3.patch create mode 100644 0043-Hardening-around-not_resumable-sessions.patch create mode 100644 0044-Add-a-test-for-session-cache-overflow.patch create mode 100644 0045-Limit-the-execution-time-of-RSA-public-key-check.patch diff --git a/0040-Add-a-test-for-session-cache-handling.patch b/0040-Add-a-test-for-session-cache-handling.patch new file mode 100644 index 0000000..b3627be --- /dev/null +++ b/0040-Add-a-test-for-session-cache-handling.patch @@ -0,0 +1,133 @@ +From 380d1ef504e3dae8f6b44a345f0fc800d783b9ac Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Mon, 4 Mar 2024 13:45:23 +0000 +Subject: [PATCH 1/5] Add a test for session cache handling + +Repeatedly create sessions to be added to the cache and ensure we never +exceed the expected size. + +Related to CVE-2024-2511 + +Reviewed-by: Neil Horman +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/24042) + +reference: https://github.com/openssl/openssl/pull/24042 +Signed-off-by: shenyage +--- + .../OpensslLib/openssl/test/sslapitest.c | 92 +++++++++++++++++++ + 1 file changed, 92 insertions(+) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c b/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c +index 3d57101..8ed3524 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c +@@ -10303,6 +10303,97 @@ end: + } + #endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) */ + ++/* ++ * Test multiple resumptions and cache size handling ++ * Test 0: TLSv1.3 (max_early_data set) ++ * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set) ++ * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set) ++ * Test 3: TLSv1.2 ++ */ ++static int test_multi_resume(int idx) ++{ ++ SSL_CTX *sctx = NULL, *cctx = NULL; ++ SSL *serverssl = NULL, *clientssl = NULL; ++ SSL_SESSION *sess = NULL; ++ int max_version = TLS1_3_VERSION; ++ int i, testresult = 0; ++ ++ if (idx == 3) ++ max_version = TLS1_2_VERSION; ++ ++ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), ++ TLS_client_method(), TLS1_VERSION, ++ max_version, &sctx, &cctx, cert, ++ privkey))) ++ goto end; ++ ++ /* ++ * TLSv1.3 only uses a session cache if either max_early_data > 0 (used for ++ * replay protection), or if SSL_OP_NO_TICKET is in use ++ */ ++ if (idx == 0 || idx == 2) { ++ if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024))) ++ goto end; ++ } ++ if (idx == 1 || idx == 2) ++ SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); ++ ++ SSL_CTX_sess_set_cache_size(sctx, 5); ++ ++ for (i = 0; i < 30; i++) { ++ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, ++ NULL, NULL)) ++ || !TEST_true(SSL_set_session(clientssl, sess))) ++ goto end; ++ ++ /* ++ * Recreate a bug where dynamically changing the max_early_data value ++ * can cause sessions in the session cache which cannot be deleted. ++ */ ++ if ((idx == 0 || idx == 2) && (i % 3) == 2) ++ SSL_set_max_early_data(serverssl, 0); ++ ++ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) ++ goto end; ++ ++ if (sess == NULL || (idx == 0 && (i % 3) == 2)) { ++ if (!TEST_false(SSL_session_reused(clientssl))) ++ goto end; ++ } else { ++ if (!TEST_true(SSL_session_reused(clientssl))) ++ goto end; ++ } ++ SSL_SESSION_free(sess); ++ ++ /* Do a full handshake, followed by two resumptions */ ++ if ((i % 3) == 2) { ++ sess = NULL; ++ } else { ++ if (!TEST_ptr((sess = SSL_get1_session(clientssl)))) ++ goto end; ++ } ++ ++ SSL_shutdown(clientssl); ++ SSL_shutdown(serverssl); ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ serverssl = clientssl = NULL; ++ } ++ ++ /* We should never exceed the session cache size limit */ ++ if (!TEST_long_le(SSL_CTX_sess_number(sctx), 5)) ++ goto end; ++ ++ testresult = 1; ++ end: ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ SSL_CTX_free(sctx); ++ SSL_CTX_free(cctx); ++ SSL_SESSION_free(sess); ++ return testresult; ++} ++ + OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n") + + int setup_tests(void) +@@ -10574,6 +10665,7 @@ int setup_tests(void) + #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) + ADD_ALL_TESTS(test_pipelining, 6); + #endif ++ ADD_ALL_TESTS(test_multi_resume, 4); + return 1; + + err: +-- +2.33.0 + diff --git a/0041-Extend-the-multi_resume-test-for-simultaneous-resump.patch b/0041-Extend-the-multi_resume-test-for-simultaneous-resump.patch new file mode 100644 index 0000000..d6a86f9 --- /dev/null +++ b/0041-Extend-the-multi_resume-test-for-simultaneous-resump.patch @@ -0,0 +1,160 @@ +From 4023a42e26e3c476c6989e2c5bf2db08937e0df8 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Tue, 5 Mar 2024 15:35:51 +0000 +Subject: [PATCH 2/5] Extend the multi_resume test for simultaneous resumptions + +Test what happens if the same session gets resumed multiple times at the +same time - and one of them gets marked as not_resumable. + +Related to CVE-2024-2511 + +Reviewed-by: Neil Horman +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/24042) + +reference: https://github.com/openssl/openssl/pull/24042 +Signed-off-by: shenyage +--- + .../OpensslLib/openssl/test/sslapitest.c | 88 ++++++++++++++++++- + 1 file changed, 84 insertions(+), 4 deletions(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c b/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c +index 8ed3524..0529793 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c +@@ -10303,12 +10303,62 @@ end: + } + #endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) */ + ++struct resume_servername_cb_data { ++ int i; ++ SSL_CTX *cctx; ++ SSL_CTX *sctx; ++ SSL_SESSION *sess; ++ int recurse; ++}; ++ ++/* ++ * Servername callback. We use it here to run another complete handshake using ++ * the same session - and mark the session as not_resuamble at the end ++ */ ++static int resume_servername_cb(SSL *s, int *ad, void *arg) ++{ ++ struct resume_servername_cb_data *cbdata = arg; ++ SSL *serverssl = NULL, *clientssl = NULL; ++ int ret = SSL_TLSEXT_ERR_ALERT_FATAL; ++ ++ if (cbdata->recurse) ++ return SSL_TLSEXT_ERR_ALERT_FATAL; ++ ++ if ((cbdata->i % 3) != 1) ++ return SSL_TLSEXT_ERR_OK; ++ ++ cbdata->recurse = 1; ++ ++ if (!TEST_true(create_ssl_objects(cbdata->sctx, cbdata->cctx, &serverssl, ++ &clientssl, NULL, NULL)) ++ || !TEST_true(SSL_set_session(clientssl, cbdata->sess))) ++ goto end; ++ ++ ERR_set_mark(); ++ /* ++ * We expect this to fail - because the servername cb will fail. This will ++ * mark the session as not_resumable. ++ */ ++ if (!TEST_false(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) { ++ ERR_clear_last_mark(); ++ goto end; ++ } ++ ERR_pop_to_mark(); ++ ++ ret = SSL_TLSEXT_ERR_OK; ++ end: ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ cbdata->recurse = 0; ++ return ret; ++} + /* + * Test multiple resumptions and cache size handling + * Test 0: TLSv1.3 (max_early_data set) + * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set) + * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set) +- * Test 3: TLSv1.2 ++ * Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes) ++ * Test 4: TLSv1.2 + */ + static int test_multi_resume(int idx) + { +@@ -10317,9 +10367,19 @@ static int test_multi_resume(int idx) + SSL_SESSION *sess = NULL; + int max_version = TLS1_3_VERSION; + int i, testresult = 0; ++ struct resume_servername_cb_data cbdata; + +- if (idx == 3) ++#if defined(OPENSSL_NO_TLS1_2) ++ if (idx == 4) ++ return TEST_skip("TLSv1.2 is disabled in this build"); ++#else ++ if (idx == 4) + max_version = TLS1_2_VERSION; ++#endif ++#if defined(OSSL_NO_USABLE_TLS1_3) ++ if (idx != 4) ++ return TEST_skip("No usable TLSv1.3 in this build"); ++#endif + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), + TLS_client_method(), TLS1_VERSION, +@@ -10335,17 +10395,37 @@ static int test_multi_resume(int idx) + if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024))) + goto end; + } +- if (idx == 1 || idx == 2) ++ if (idx == 1 || idx == 2 || idx == 3) + SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); + + SSL_CTX_sess_set_cache_size(sctx, 5); + ++ if (idx == 3) { ++ SSL_CTX_set_tlsext_servername_callback(sctx, resume_servername_cb); ++ SSL_CTX_set_tlsext_servername_arg(sctx, &cbdata); ++ cbdata.cctx = cctx; ++ cbdata.sctx = sctx; ++ cbdata.recurse = 0; ++ } ++ + for (i = 0; i < 30; i++) { + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, sess))) + goto end; + ++ /* ++ * Check simultaneous resumes. We pause the connection part way through ++ * the handshake by (mis)using the servername_cb. The pause occurs after ++ * session resumption has already occurred, but before any session ++ * tickets have been issued. While paused we run another complete ++ * handshake resuming the same session. ++ */ ++ if (idx == 3) { ++ cbdata.i = i; ++ cbdata.sess = sess; ++ } ++ + /* + * Recreate a bug where dynamically changing the max_early_data value + * can cause sessions in the session cache which cannot be deleted. +@@ -10665,7 +10745,7 @@ int setup_tests(void) + #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE) + ADD_ALL_TESTS(test_pipelining, 6); + #endif +- ADD_ALL_TESTS(test_multi_resume, 4); ++ ADD_ALL_TESTS(test_multi_resume, 5); + return 1; + + err: +-- +2.33.0 + diff --git a/0042-Fix-unconstrained-session-cache-growth-in-TLSv1.3.patch b/0042-Fix-unconstrained-session-cache-growth-in-TLSv1.3.patch new file mode 100644 index 0000000..8160d09 --- /dev/null +++ b/0042-Fix-unconstrained-session-cache-growth-in-TLSv1.3.patch @@ -0,0 +1,122 @@ +From ff3df21663344b334aa2a06a3e83cb3a2552f072 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Tue, 5 Mar 2024 15:43:53 +0000 +Subject: [PATCH 3/5] Fix unconstrained session cache growth in TLSv1.3 + +In TLSv1.3 we create a new session object for each ticket that we send. +We do this by duplicating the original session. If SSL_OP_NO_TICKET is in +use then the new session will be added to the session cache. However, if +early data is not in use (and therefore anti-replay protection is being +used), then multiple threads could be resuming from the same session +simultaneously. If this happens and a problem occurs on one of the threads, +then the original session object could be marked as not_resumable. When we +duplicate the session object this not_resumable status gets copied into the +new session object. The new session object is then added to the session +cache even though it is not_resumable. + +Subsequently, another bug means that the session_id_length is set to 0 for +sessions that are marked as not_resumable - even though that session is +still in the cache. Once this happens the session can never be removed from +the cache. When that object gets to be the session cache tail object the +cache never shrinks again and grows indefinitely. + +CVE-2024-2511 + +Reviewed-by: Neil Horman +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/24042) + +reference: https://github.com/openssl/openssl/pull/24042 +Signed-off-by: shenyage +--- + .../Library/OpensslLib/openssl/ssl/ssl_lib.c | 5 ++-- + .../Library/OpensslLib/openssl/ssl/ssl_sess.c | 28 +++++++++++++++---- + .../openssl/ssl/statem/statem_srvr.c | 5 ++-- + 3 files changed, 27 insertions(+), 11 deletions(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c +index 214884b..35420eb 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_lib.c +@@ -3717,9 +3717,10 @@ void ssl_update_cache(SSL *s, int mode) + + /* + * If the session_id_length is 0, we are not supposed to cache it, and it +- * would be rather hard to do anyway :-) ++ * would be rather hard to do anyway :-). Also if the session has already ++ * been marked as not_resumable we should not cache it for later reuse. + */ +- if (s->session->session_id_length == 0) ++ if (s->session->session_id_length == 0 || s->session->not_resumable) + return; + + /* +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c +index c322a11..8f2f37b 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c +@@ -152,16 +152,11 @@ SSL_SESSION *SSL_SESSION_new(void) + return ss; + } + +-SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src) +-{ +- return ssl_session_dup(src, 1); +-} +- + /* + * Create a new SSL_SESSION and duplicate the contents of |src| into it. If + * ticket == 0 then no ticket information is duplicated, otherwise it is. + */ +-SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) ++static SSL_SESSION *ssl_session_dup_intern(const SSL_SESSION *src, int ticket) + { + SSL_SESSION *dest; + +@@ -282,6 +277,27 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) + return NULL; + } + ++SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src) ++{ ++ return ssl_session_dup_intern(src, 1); ++} ++ ++/* ++ * Used internally when duplicating a session which might be already shared. ++ * We will have resumed the original session. Subsequently we might have marked ++ * it as non-resumable (e.g. in another thread) - but this copy should be ok to ++ * resume from. ++ */ ++SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) ++{ ++ SSL_SESSION *sess = ssl_session_dup_intern(src, ticket); ++ ++ if (sess != NULL) ++ sess->not_resumable = 0; ++ ++ return sess; ++} ++ + const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) + { + if (len) +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/statem/statem_srvr.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/statem/statem_srvr.c +index a9e67f9..70c1893 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/statem/statem_srvr.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/statem/statem_srvr.c +@@ -2338,9 +2338,8 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt) + * so the following won't overwrite an ID that we're supposed + * to send back. + */ +- if (s->session->not_resumable || +- (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) +- && !s->hit)) ++ if (!(SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER) ++ && !s->hit) + s->session->session_id_length = 0; + + if (usetls13) { +-- +2.33.0 + diff --git a/0043-Hardening-around-not_resumable-sessions.patch b/0043-Hardening-around-not_resumable-sessions.patch new file mode 100644 index 0000000..a2503bb --- /dev/null +++ b/0043-Hardening-around-not_resumable-sessions.patch @@ -0,0 +1,39 @@ +From c44d5f799061ed8d7174c58e0cef0e43bda185be Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Fri, 15 Mar 2024 17:58:42 +0000 +Subject: [PATCH 4/5] Hardening around not_resumable sessions + +Make sure we can't inadvertently use a not_resumable session + +Related to CVE-2024-2511 + +Reviewed-by: Neil Horman +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/24042) + +reference: https://github.com/openssl/openssl/pull/24042 +Signed-off-by: shenyage +--- + CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c +index 8f2f37b..46f4f75 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/ssl/ssl_sess.c +@@ -528,6 +528,12 @@ SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, + ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©); + + if (ret != NULL) { ++ if (ret->not_resumable) { ++ /* If its not resumable then ignore this session */ ++ if (!copy) ++ SSL_SESSION_free(ret); ++ return NULL; ++ } + ssl_tsan_counter(s->session_ctx, + &s->session_ctx->stats.sess_cb_hit); + +-- +2.33.0 + diff --git a/0044-Add-a-test-for-session-cache-overflow.patch b/0044-Add-a-test-for-session-cache-overflow.patch new file mode 100644 index 0000000..b921699 --- /dev/null +++ b/0044-Add-a-test-for-session-cache-overflow.patch @@ -0,0 +1,172 @@ +From 3ce388a7ea5c1e53dd10ea7d083f8de5c21adb54 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Fri, 15 Jul 2022 13:26:33 +0100 +Subject: [PATCH 5/5] Add a test for session cache overflow + +Test sessions behave as we expect even in the case that an overflow +occurs when adding a new session into the session cache. + +Related to CVE-2024-2511 + +Reviewed-by: Neil Horman +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/24042) + +reference: https://github.com/openssl/openssl/pull/24042 +Signed-off-by: shenyage +--- + .../OpensslLib/openssl/test/sslapitest.c | 124 +++++++++++++++++- + 1 file changed, 123 insertions(+), 1 deletion(-) + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c b/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c +index 0529793..a8eed30 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/test/sslapitest.c +@@ -2386,7 +2386,6 @@ static int test_session_wo_ca_names(void) + #endif + } + +- + #ifndef OSSL_NO_USABLE_TLS1_3 + static SSL_SESSION *sesscache[6]; + static int do_cache; +@@ -8938,6 +8937,126 @@ static int test_session_timeout(int test) + return testresult; + } + ++/* ++ * Test that a session cache overflow works as expected ++ * Test 0: TLSv1.3, timeout on new session later than old session ++ * Test 1: TLSv1.2, timeout on new session later than old session ++ * Test 2: TLSv1.3, timeout on new session earlier than old session ++ * Test 3: TLSv1.2, timeout on new session earlier than old session ++ */ ++#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) ++static int test_session_cache_overflow(int idx) ++{ ++ SSL_CTX *sctx = NULL, *cctx = NULL; ++ SSL *serverssl = NULL, *clientssl = NULL; ++ int testresult = 0; ++ SSL_SESSION *sess = NULL; ++ ++#ifdef OSSL_NO_USABLE_TLS1_3 ++ /* If no TLSv1.3 available then do nothing in this case */ ++ if (idx % 2 == 0) ++ return TEST_skip("No TLSv1.3 available"); ++#endif ++#ifdef OPENSSL_NO_TLS1_2 ++ /* If no TLSv1.2 available then do nothing in this case */ ++ if (idx % 2 == 1) ++ return TEST_skip("No TLSv1.2 available"); ++#endif ++ ++ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), ++ TLS_client_method(), TLS1_VERSION, ++ (idx % 2 == 0) ? TLS1_3_VERSION ++ : TLS1_2_VERSION, ++ &sctx, &cctx, cert, privkey)) ++ || !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET))) ++ goto end; ++ ++ SSL_CTX_sess_set_get_cb(sctx, get_session_cb); ++ get_sess_val = NULL; ++ ++ SSL_CTX_sess_set_cache_size(sctx, 1); ++ ++ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, ++ NULL, NULL))) ++ goto end; ++ ++ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) ++ goto end; ++ ++ if (idx > 1) { ++ sess = SSL_get_session(serverssl); ++ if (!TEST_ptr(sess)) ++ goto end; ++ ++ /* ++ * Cause this session to have a longer timeout than the next session to ++ * be added. ++ */ ++ if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX))) { ++ sess = NULL; ++ goto end; ++ } ++ sess = NULL; ++ } ++ ++ SSL_shutdown(serverssl); ++ SSL_shutdown(clientssl); ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ serverssl = clientssl = NULL; ++ ++ /* ++ * Session cache size is 1 and we already populated the cache with a session ++ * so the next connection should cause an overflow. ++ */ ++ ++ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, ++ NULL, NULL))) ++ goto end; ++ ++ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) ++ goto end; ++ ++ /* ++ * The session we just negotiated may have been already removed from the ++ * internal cache - but we will return it anyway from our external cache. ++ */ ++ get_sess_val = SSL_get_session(serverssl); ++ if (!TEST_ptr(get_sess_val)) ++ goto end; ++ sess = SSL_get1_session(clientssl); ++ if (!TEST_ptr(sess)) ++ goto end; ++ ++ SSL_shutdown(serverssl); ++ SSL_shutdown(clientssl); ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ serverssl = clientssl = NULL; ++ ++ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, ++ NULL, NULL))) ++ goto end; ++ ++ if (!TEST_true(SSL_set_session(clientssl, sess))) ++ goto end; ++ ++ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) ++ goto end; ++ ++ testresult = 1; ++ ++ end: ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ SSL_CTX_free(sctx); ++ SSL_CTX_free(cctx); ++ SSL_SESSION_free(sess); ++ ++ return testresult; ++} ++#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */ ++ + /* + * Test 0: Client sets servername and server acknowledges it (TLSv1.2) + * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2) +@@ -10738,6 +10857,9 @@ int setup_tests(void) + ADD_TEST(test_set_verify_cert_store_ssl_ctx); + ADD_TEST(test_set_verify_cert_store_ssl); + ADD_ALL_TESTS(test_session_timeout, 1); ++#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) ++ ADD_ALL_TESTS(test_session_cache_overflow, 4); ++#endif + ADD_TEST(test_load_dhfile); + #if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3) + ADD_ALL_TESTS(test_serverinfo_custom, 4); +-- +2.33.0 + diff --git a/0045-Limit-the-execution-time-of-RSA-public-key-check.patch b/0045-Limit-the-execution-time-of-RSA-public-key-check.patch new file mode 100644 index 0000000..f68f6df --- /dev/null +++ b/0045-Limit-the-execution-time-of-RSA-public-key-check.patch @@ -0,0 +1,126 @@ +From 02ec2aa154d26f078e9457998cd2e64b05b35b53 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Fri, 22 Dec 2023 16:25:56 +0100 +Subject: [PATCH] Limit the execution time of RSA public key check + +Fixes CVE-2023-6237 + +If a large and incorrect RSA public key is checked with +EVP_PKEY_public_check() the computation could take very long time +due to no limit being applied to the RSA public key size and +unnecessarily high number of Miller-Rabin algorithm rounds +used for non-primality check of the modulus. + +Now the keys larger than 16384 bits (OPENSSL_RSA_MAX_MODULUS_BITS) +will fail the check with RSA_R_MODULUS_TOO_LARGE error reason. +Also the number of Miller-Rabin rounds was set to 5. + +Reviewed-by: Neil Horman +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/23243) + +reference: https://github.com/openssl/openssl/pull/23243 +Signed-off-by: ShenYage +--- + .../openssl/crypto/rsa/rsa_sp800_56b_check.c | 8 +++- + .../openssl/test/recipes/91-test_pkey_check.t | 2 +- + .../91-test_pkey_check_data/rsapub_17k.pem | 48 +++++++++++++++++++ + 3 files changed, 56 insertions(+), 2 deletions(-) + create mode 100644 CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check_data/rsapub_17k.pem + +diff --git a/CryptoPkg/Library/OpensslLib/openssl/crypto/rsa/rsa_sp800_56b_check.c b/CryptoPkg/Library/OpensslLib/openssl/crypto/rsa/rsa_sp800_56b_check.c +index fc8f19b..bcbdd24 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/crypto/rsa/rsa_sp800_56b_check.c ++++ b/CryptoPkg/Library/OpensslLib/openssl/crypto/rsa/rsa_sp800_56b_check.c +@@ -289,6 +289,11 @@ int ossl_rsa_sp800_56b_check_public(const RSA *rsa) + return 0; + + nbits = BN_num_bits(rsa->n); ++ if (nbits > OPENSSL_RSA_MAX_MODULUS_BITS) { ++ ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE); ++ return 0; ++ } ++ + #ifdef FIPS_MODULE + /* + * (Step a): modulus must be 2048 or 3072 (caveat from SP800-56Br1) +@@ -324,7 +329,8 @@ int ossl_rsa_sp800_56b_check_public(const RSA *rsa) + goto err; + } + +- ret = ossl_bn_miller_rabin_is_prime(rsa->n, 0, ctx, NULL, 1, &status); ++ /* Highest number of MR rounds from FIPS 186-5 Section B.3 Table B.1 */ ++ ret = ossl_bn_miller_rabin_is_prime(rsa->n, 5, ctx, NULL, 1, &status); + #ifdef FIPS_MODULE + if (ret != 1 || status != BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME) { + #else +diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check.t b/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check.t +index dc7cc64..f8088df 100644 +--- a/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check.t ++++ b/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check.t +@@ -70,7 +70,7 @@ push(@positive_tests, ( + "dhpkey.pem" + )) unless disabled("dh"); + +-my @negative_pubtests = (); ++my @negative_pubtests = ("rsapub_17k.pem"); # Too big RSA public key + + push(@negative_pubtests, ( + "dsapub_noparam.der" +diff --git a/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check_data/rsapub_17k.pem b/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check_data/rsapub_17k.pem +new file mode 100644 +index 0000000..9a2eaed +--- /dev/null ++++ b/CryptoPkg/Library/OpensslLib/openssl/test/recipes/91-test_pkey_check_data/rsapub_17k.pem +@@ -0,0 +1,48 @@ ++-----BEGIN PUBLIC KEY----- ++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 ++AQAB ++-----END PUBLIC KEY----- +-- +2.33.0 + diff --git a/edk2.spec b/edk2.spec index ec38354..d88ac82 100644 --- a/edk2.spec +++ b/edk2.spec @@ -7,7 +7,7 @@ Name: edk2 Version: %{stable_date} -Release: 5 +Release: 6 Summary: EFI Development Kit II License: BSD-2-Clause-Patent and OpenSSL and MIT URL: https://github.com/tianocore/edk2 @@ -61,6 +61,14 @@ patch37: 0037-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch patch38: 0038-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch patch39: 0039-NetworkPkg-Updating-SecurityFixes.yaml.patch +# Fix CVE-2023-6237、CVE-2024-2511 +#patch40: 0040-Add-a-test-for-session-cache-handling.patch +#patch41: 0041-Extend-the-multi_resume-test-for-simultaneous-resump.patch +#patch42: 0042-Fix-unconstrained-session-cache-growth-in-TLSv1.3.patch +#patch43: 0043-Hardening-around-not_resumable-sessions.patch +#patch44: 0044-Add-a-test-for-session-cache-overflow.patch +#patch45: 0045-Limit-the-execution-time-of-RSA-public-key-check.patch + BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python3-unversioned-command isl %description @@ -297,6 +305,9 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys %endif %changelog +* Mon Apr 15 2024 shenyage - 202308-6 +- fix CVE-2023-6237、CVE-2024-2511 + * Thu Mar 7 2024 yexiao - 202308-5 - fix CVE-2023-45229、CVE-2023-45230、CVE-2023-45231、CVE-2023-45232、CVE-2023-45233、CVE-2023-45234、CVE-2023-45235 -- Gitee