From b8333d7c6f794b314a6ea09645aff4be6c32b6d9 Mon Sep 17 00:00:00 2001 From: Soumya Sambu Date: Fri, 26 Sep 2025 17:14:29 +0530 Subject: [PATCH] iperf3: Fix CVE-2024-26306 iPerf3 before 3.17, when used with OpenSSL before 3.2.0 as a server with RSA authentication, allows a timing side channel in RSA decryption operations. This side channel could be sufficient for an attacker to recover credential plaintext. It requires the attacker to send a large number of messages for decryption, as described in "Everlasting ROBOT: the Marvin Attack" by Hubert Kario. References: https://nvd.nist.gov/vuln/detail/CVE-2024-26306 https://security-tracker.debian.org/tracker/CVE-2024-26306 Upstream patch: https://github.com/esnet/iperf/commit/299b356df6939f71619bf45bf7a7d2222e17d840 Signed-off-by: Soumya Sambu Signed-off-by: Gyorgy Sarvari --- .../iperf3/iperf3/CVE-2024-26306.patch | 218 ++++++++++++++++++ .../recipes-benchmark/iperf3/iperf3_3.14.bb | 1 + 2 files changed, 219 insertions(+) create mode 100644 meta-oe/recipes-benchmark/iperf3/iperf3/CVE-2024-26306.patch diff --git a/meta-oe/recipes-benchmark/iperf3/iperf3/CVE-2024-26306.patch b/meta-oe/recipes-benchmark/iperf3/iperf3/CVE-2024-26306.patch new file mode 100644 index 0000000000..886f40ff4c --- /dev/null +++ b/meta-oe/recipes-benchmark/iperf3/iperf3/CVE-2024-26306.patch @@ -0,0 +1,218 @@ +From 299b356df6939f71619bf45bf7a7d2222e17d840 Mon Sep 17 00:00:00 2001 +From: Sarah Larsen +Date: Wed, 20 Mar 2024 17:02:31 -0700 +Subject: [PATCH] Using OAEP padding instead of PKCS1 padding for OpenSSL. Fix + for CVE-2024-26306. + +Special thanks to Hubert Kario at Red Hat for finding the vulnerability. + +CVE: CVE-2024-26306 + +Upstream-Status: Backport [https://github.com/esnet/iperf/commit/299b356df6939f71619bf45bf7a7d2222e17d840] + +Signed-off-by: Soumya Sambu +--- + src/iperf.h | 1 + + src/iperf_api.c | 8 ++++++-- + src/iperf_api.h | 1 + + src/iperf_auth.c | 26 ++++++++++++++++++-------- + src/iperf_auth.h | 4 ++-- + src/iperf_locale.c | 1 + + src/t_auth.c | 5 +++-- + 7 files changed, 32 insertions(+), 14 deletions(-) + +diff --git a/src/iperf.h b/src/iperf.h +index c3ce333..ae3feeb 100644 +--- a/src/iperf.h ++++ b/src/iperf.h +@@ -308,6 +308,7 @@ struct iperf_test + char *server_authorized_users; + EVP_PKEY *server_rsa_private_key; + int server_skew_threshold; ++ int use_pkcs1_padding; + #endif // HAVE_SSL + + /* boolean variables for Options */ +diff --git a/src/iperf_api.c b/src/iperf_api.c +index a95e024..3915884 100644 +--- a/src/iperf_api.c ++++ b/src/iperf_api.c +@@ -1097,6 +1097,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) + {"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY}, + {"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS}, + {"time-skew-threshold", required_argument, NULL, OPT_SERVER_SKEW_THRESHOLD}, ++ {"use-pkcs1-padding", no_argument, NULL, OPT_USE_PKCS1_PADDING}, + #endif /* HAVE_SSL */ + {"fq-rate", required_argument, NULL, OPT_FQ_RATE}, + {"pacing-timer", required_argument, NULL, OPT_PACING_TIMER}, +@@ -1585,6 +1586,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) + return -1; + } + break; ++ case OPT_USE_PKCS1_PADDING: ++ test->use_pkcs1_padding = 1; ++ break; + #endif /* HAVE_SSL */ + case OPT_PACING_TIMER: + test->settings->pacing_timer = unit_atoi(optarg); +@@ -2026,7 +2030,7 @@ int test_is_authorized(struct iperf_test *test){ + if (test->settings->authtoken){ + char *username = NULL, *password = NULL; + time_t ts; +- int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts); ++ int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts, test->use_pkcs1_padding); + if (rc) { + return -1; + } +@@ -2211,7 +2215,7 @@ send_parameters(struct iperf_test *test) + #if defined(HAVE_SSL) + /* Send authentication parameters */ + if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){ +- int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken); ++ int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken, test->use_pkcs1_padding); + + if (rc) { + cJSON_Delete(j); +diff --git a/src/iperf_api.h b/src/iperf_api.h +index 171006a..052bc96 100644 +--- a/src/iperf_api.h ++++ b/src/iperf_api.h +@@ -90,6 +90,7 @@ typedef uint64_t iperf_size_t; + #define OPT_DONT_FRAGMENT 26 + #define OPT_RCV_TIMEOUT 27 + #define OPT_SND_TIMEOUT 28 ++#define OPT_USE_PKCS1_PADDING 30 + + /* states */ + #define TEST_START 1 +diff --git a/src/iperf_auth.c b/src/iperf_auth.c +index 595f730..db48bbf 100644 +--- a/src/iperf_auth.c ++++ b/src/iperf_auth.c +@@ -226,7 +226,7 @@ int test_load_private_key_from_file(const char *file){ + return 0; + } + +-int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext) { ++int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext, int use_pkcs1_padding) { + RSA *rsa = NULL; + unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; + int keysize, encryptedtext_len, rsa_buffer_len; +@@ -239,7 +239,12 @@ int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned ch + + BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext)); + rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2); +- encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, pad); ++ ++ int padding = RSA_PKCS1_OAEP_PADDING; ++ if (use_pkcs1_padding){ ++ padding = RSA_PKCS1_PADDING; ++ } ++ encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, padding); + + RSA_free(rsa); + OPENSSL_free(rsa_buffer); +@@ -253,7 +258,7 @@ int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned ch + return encryptedtext_len; + } + +-int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext) { ++int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext, int use_pkcs1_padding) { + RSA *rsa = NULL; + unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; + int plaintext_len, rsa_buffer_len, keysize; +@@ -267,7 +272,12 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt + + BIO *bioBuff = BIO_new_mem_buf((void*)encryptedtext, encryptedtext_len); + rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2); +- plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, pad); ++ ++ int padding = RSA_PKCS1_OAEP_PADDING; ++ if (use_pkcs1_padding){ ++ padding = RSA_PKCS1_PADDING; ++ } ++ plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, padding); + + RSA_free(rsa); + OPENSSL_free(rsa_buffer); +@@ -281,7 +291,7 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt + return plaintext_len; + } + +-int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken){ ++int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken, int use_pkcs1_padding){ + time_t t = time(NULL); + time_t utc_seconds = mktime(localtime(&t)); + +@@ -298,7 +308,7 @@ int encode_auth_setting(const char *username, const char *password, EVP_PKEY *pu + + unsigned char *encrypted = NULL; + int encrypted_len; +- encrypted_len = encrypt_rsa_message(text, public_key, &encrypted); ++ encrypted_len = encrypt_rsa_message(text, public_key, &encrypted, use_pkcs1_padding); + free(text); + if (encrypted_len < 0) { + return -1; +@@ -309,7 +319,7 @@ int encode_auth_setting(const char *username, const char *password, EVP_PKEY *pu + return (0); //success + } + +-int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){ ++int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts, int use_pkcs1_padding){ + unsigned char *encrypted_b64 = NULL; + size_t encrypted_len_b64; + int64_t utc_seconds; +@@ -317,7 +327,7 @@ int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *priva + + unsigned char *plaintext = NULL; + int plaintext_len; +- plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext); ++ plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext, use_pkcs1_padding); + free(encrypted_b64); + if (plaintext_len <= 0) { + return -1; +diff --git a/src/iperf_auth.h b/src/iperf_auth.h +index ffadbf3..eedd45a 100644 +--- a/src/iperf_auth.h ++++ b/src/iperf_auth.h +@@ -35,7 +35,7 @@ EVP_PKEY *load_pubkey_from_file(const char *file); + EVP_PKEY *load_pubkey_from_base64(const char *buffer); + EVP_PKEY *load_privkey_from_file(const char *file); + EVP_PKEY *load_privkey_from_base64(const char *buffer); +-int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken); +-int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts); ++int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken, int use_pkcs1_padding); ++int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts, int use_pkcs1_padding); + int check_authentication(const char *username, const char *password, const time_t ts, const char *filename, int skew_threshold); + ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream); +diff --git a/src/iperf_locale.c b/src/iperf_locale.c +index 838086e..466f36a 100644 +--- a/src/iperf_locale.c ++++ b/src/iperf_locale.c +@@ -156,6 +156,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n" + " credentials\n" + " --time-skew-threshold time skew threshold (in seconds) between the server\n" + " and client during the authentication process\n" ++ " --use-pkcs1-padding use pkcs1 padding at your own risk\n" + #endif //HAVE_SSL + "Client specific:\n" + " -c, --client [%%] run in client mode, connecting to \n" +diff --git a/src/t_auth.c b/src/t_auth.c +index 22c78ae..5104855 100644 +--- a/src/t_auth.c ++++ b/src/t_auth.c +@@ -103,8 +103,9 @@ test_authtoken(const char *authUser, const char *authPassword, EVP_PKEY *pubkey, + char *decodePassword; + time_t decodeTime; + +- assert(encode_auth_setting(authUser, authPassword, pubkey, &authToken) == 0); +- assert(decode_auth_setting(0, authToken, privkey, &decodeUser, &decodePassword, &decodeTime) == 0); ++ int use_pkcs1_padding = 1; ++ assert(encode_auth_setting(authUser, authPassword, pubkey, &authToken, use_pkcs1_padding) == 0); ++ assert(decode_auth_setting(0, authToken, privkey, &decodeUser, &decodePassword, &decodeTime, use_pkcs1_padding) == 0); + + assert(strcmp(decodeUser, authUser) == 0); + assert(strcmp(decodePassword, authPassword) == 0); +-- +2.40.0 + diff --git a/meta-oe/recipes-benchmark/iperf3/iperf3_3.14.bb b/meta-oe/recipes-benchmark/iperf3/iperf3_3.14.bb index fe4b50abc1..e8848ccebe 100644 --- a/meta-oe/recipes-benchmark/iperf3/iperf3_3.14.bb +++ b/meta-oe/recipes-benchmark/iperf3/iperf3_3.14.bb @@ -19,6 +19,7 @@ SRC_URI = "git://github.com/esnet/iperf.git;branch=master;protocol=https \ file://CVE-2025-54350.patch \ file://CVE-2025-54349.patch \ file://CVE-2023-7250.patch \ + file://CVE-2024-26306.patch \ " SRCREV = "a0be85934144bc04712a6695b14ea6e45c379e1d"