diff --git a/BRANCHES.md b/BRANCHES.md index c085b1616..b71247f3e 100644 --- a/BRANCHES.md +++ b/BRANCHES.md @@ -106,6 +106,6 @@ The following branches are currently maintained: - [`development`](https://github.com/Mbed-TLS/mbedtls/) - [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28) maintained until at least the end of 2024, see - . + . Users are urged to always use the latest version of a maintained branch. diff --git a/CMakeLists.txt b/CMakeLists.txt index ad056466a..78599d9f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,7 +381,7 @@ if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL) write_basic_package_version_file( "cmake/MbedTLSConfigVersion.cmake" COMPATIBILITY SameMajorVersion - VERSION 3.5.1) + VERSION 3.5.2) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake" diff --git a/ChangeLog b/ChangeLog index 28c45f718..28f2654b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ Mbed TLS ChangeLog (Sorted per branch, date) += Mbed TLS 3.5.2 branch released 2024-01-26 + +Security + * Fix a timing side channel in private key RSA operations. This side channel + could be sufficient for an attacker to recover the plaintext. A local + attacker or a remote attacker who is close to the victim on the network + might have precise enough timing measurements to exploit this. It requires + the attacker to send a large number of messages for decryption. For + details, see "Everlasting ROBOT: the Marvin Attack", Hubert Kario. Reported + by Hubert Kario, Red Hat. + * Fix a failure to validate input when writing x509 extensions lengths which + could result in an integer overflow, causing a zero-length buffer to be + allocated to hold the extension. The extension would then be copied into + the buffer, causing a heap buffer overflow. + = Mbed TLS 3.5.1 branch released 2023-11-06 Changes diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h index c391c59ce..17762d726 100644 --- a/doxygen/input/doc_mainpage.h +++ b/doxygen/input/doc_mainpage.h @@ -10,7 +10,7 @@ */ /** - * @mainpage Mbed TLS v3.5.1 API Documentation + * @mainpage Mbed TLS v3.5.2 API Documentation * * This documentation describes the internal structure of Mbed TLS. It was * automatically generated from specially formatted comment blocks in diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile index 89048f221..cbbb7597f 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -1,4 +1,4 @@ -PROJECT_NAME = "Mbed TLS v3.5.1" +PROJECT_NAME = "Mbed TLS v3.5.2" OUTPUT_DIRECTORY = ../apidoc/ FULL_PATH_NAMES = NO OPTIMIZE_OUTPUT_FOR_C = YES diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h index c0b724c83..2f336ba21 100644 --- a/include/mbedtls/build_info.h +++ b/include/mbedtls/build_info.h @@ -26,16 +26,16 @@ */ #define MBEDTLS_VERSION_MAJOR 3 #define MBEDTLS_VERSION_MINOR 5 -#define MBEDTLS_VERSION_PATCH 1 +#define MBEDTLS_VERSION_PATCH 2 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x03050100 -#define MBEDTLS_VERSION_STRING "3.5.1" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.5.1" +#define MBEDTLS_VERSION_NUMBER 0x03050200 +#define MBEDTLS_VERSION_STRING "3.5.2" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.5.2" /* Macros for build-time platform detection */ diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h index e5e172f9c..9136375c1 100644 --- a/include/mbedtls/rsa.h +++ b/include/mbedtls/rsa.h @@ -684,6 +684,10 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, * It is the generic wrapper for performing a PKCS#1 decryption * operation. * + * \warning When \p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15, + * mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an + * inherently dangerous function (CWE-242). + * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N (for example, * 128 Bytes if RSA-1024 is used) to be able to hold an @@ -720,6 +724,11 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 decryption * operation (RSAES-PKCS1-v1_5-DECRYPT). * + * \warning This is an inherently dangerous function (CWE-242). Unless + * it is used in a side channel free and safe way (eg. + * implementing the TLS protocol as per 7.4.7.1 of RFC 5246), + * the calling code is vulnerable. + * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for example, * 128 Bytes if RSA-1024 is used, to be able to hold an diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 90d98fdb7..f311acb1d 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1756,6 +1756,13 @@ 0) /** RSA PKCS#1 v1.5 encryption. + * + * \warning Calling psa_asymmetric_decrypt() with this algorithm as a + * parameter is considered an inherently dangerous function + * (CWE-242). Unless it is used in a side channel free and safe + * way (eg. implementing the TLS protocol as per 7.4.7.1 of + * RFC 5246), the calling code is vulnerable. + * */ #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t) 0x07000200) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 5c297e0a1..b6ea73e90 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -297,7 +297,7 @@ endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}) add_library(${mbedcrypto_target} SHARED ${src_crypto}) - set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.5.1 SOVERSION 15) + set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.5.2 SOVERSION 15) target_link_libraries(${mbedcrypto_target} PUBLIC ${libs}) if(TARGET ${everest_target}) @@ -309,11 +309,11 @@ if(USE_SHARED_MBEDTLS_LIBRARY) endif() add_library(${mbedx509_target} SHARED ${src_x509}) - set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.5.1 SOVERSION 6) + set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.5.2 SOVERSION 6) target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target}) add_library(${mbedtls_target} SHARED ${src_tls}) - set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.5.1 SOVERSION 20) + set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.5.2 SOVERSION 20) target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target}) endif(USE_SHARED_MBEDTLS_LIBRARY) diff --git a/library/rsa.c b/library/rsa.c index 2b9f85b73..a90b83adf 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -28,6 +28,7 @@ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" +#include "bignum_core.h" #include "rsa_alt_helpers.h" #include "rsa_internal.h" #include "mbedtls/oid.h" @@ -970,6 +971,45 @@ cleanup: return ret; } +/* + * Unblind + * T = T * Vf mod N + */ +static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); + const size_t nlimbs = N->n; + const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs); + mbedtls_mpi RR, M_T; + + mbedtls_mpi_init(&RR); + mbedtls_mpi_init(&M_T); + + MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs)); + + /* T = T * Vf mod N + * Reminder: montmul(A, B, N) = A * B * R^-1 mod N + * Usually both operands are multiplied by R mod N beforehand (by calling + * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka + * "in the Montgomery domain"). Here we only multiply one operand by R mod + * N, so the result is directly what we want - no need to call + * `from_mont_rep()` on it. */ + mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p); + mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p); + +cleanup: + + mbedtls_mpi_free(&RR); + mbedtls_mpi_free(&M_T); + + return ret; +} + /* * Exponent blinding supposed to prevent side-channel attacks using multiple * traces of measurements to recover the RSA key. The more collisions are there, @@ -1017,23 +1057,14 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, /* Temporaries holding the blinded exponents for * the mod p resp. mod q computation (if used). */ mbedtls_mpi DP_blind, DQ_blind; - - /* Pointers to actual exponents to be used - either the unblinded - * or the blinded ones, depending on the presence of a PRNG. */ - mbedtls_mpi *DP = &ctx->DP; - mbedtls_mpi *DQ = &ctx->DQ; #else /* Temporary holding the blinded exponent (if used). */ mbedtls_mpi D_blind; - - /* Pointer to actual exponent to be used - either the unblinded - * or the blinded one, depending on the presence of a PRNG. */ - mbedtls_mpi *D = &ctx->D; #endif /* MBEDTLS_RSA_NO_CRT */ /* Temporaries holding the initial input and the double * checked result; should be the same in the end. */ - mbedtls_mpi I, C; + mbedtls_mpi input_blinded, check_result_blinded; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; @@ -1068,8 +1099,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ); #endif - mbedtls_mpi_init(&I); - mbedtls_mpi_init(&C); + mbedtls_mpi_init(&input_blinded); + mbedtls_mpi_init(&check_result_blinded); /* End of MPI initialization */ @@ -1079,8 +1110,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, goto cleanup; } - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&I, &T)); - /* * Blinding * T = T * Vi mod N @@ -1089,6 +1118,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T)); + /* * Exponent blinding */ @@ -1104,8 +1135,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D)); - - D = &D_blind; #else /* * DP_blind = ( P - 1 ) * R + DP @@ -1116,8 +1145,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind, &ctx->DP)); - DP = &DP_blind; - /* * DQ_blind = ( Q - 1 ) * R + DQ */ @@ -1126,12 +1153,10 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind, &ctx->DQ)); - - DQ = &DQ_blind; #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, D, &ctx->N, &ctx->RN)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN)); #else /* * Faster decryption using the CRT @@ -1140,8 +1165,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, * TQ = input ^ dQ mod Q */ - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, DP, &ctx->P, &ctx->RP)); - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, DQ, &ctx->Q, &ctx->RQ)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ)); /* * T = (TP - TQ) * (Q^-1 mod P) mod P @@ -1157,20 +1182,19 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP)); #endif /* MBEDTLS_RSA_NO_CRT */ + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E, + &ctx->N, &ctx->RN)); + if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + /* * Unblind * T = T * Vf mod N */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vf)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); - - /* Verify the result to prevent glitching attacks. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&C, &T, &ctx->E, - &ctx->N, &ctx->RN)); - if (mbedtls_mpi_cmp_mpi(&C, &I) != 0) { - ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; - goto cleanup; - } + MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N)); olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); @@ -1199,8 +1223,8 @@ cleanup: mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ); #endif - mbedtls_mpi_free(&C); - mbedtls_mpi_free(&I); + mbedtls_mpi_free(&check_result_blinded); + mbedtls_mpi_free(&input_blinded); if (ret != 0 && ret >= -0x007f) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret); diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index faa31662a..6290331c1 100644 --- a/tests/suites/test_suite_version.data +++ b/tests/suites/test_suite_version.data @@ -1,8 +1,8 @@ Check compile time library version -check_compiletime_version:"3.5.1" +check_compiletime_version:"3.5.2" Check runtime library version -check_runtime_version:"3.5.1" +check_runtime_version:"3.5.2" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0