Merge branch 'mbedtls-1.3'
diff --git a/ChangeLog b/ChangeLog
index 3c7a423..6b69733 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,13 @@
= mbed TLS 1.3.x branch released xxxx-xx-xx
+Security
+ * Add checks to prevent signature forgeries for very large messages while
+ using RSA through the PK module in 64-bit systems. The issue was caused by
+ some data loss when casting a size_t to an unsigned int value in the
+ functions rsa_verify_wrap(), rsa_sign_wrap(), rsa_alt_sign_wrap() and
+ pk_sign(). Found by Jean-Philippe Aumasson.
+
Bugfix
* Fixed multiple buffer overreads in mbedtls_pem_read_buffer() when parsing
the input string in PEM format to extract the different components. Found
@@ -9,6 +16,9 @@
* Fix unused variable/function compilation warnings in pem.c and x509_csr.c
that are reported when building mbed TLS with a config.h that does not
define POLARSSL_PEM_PARSE_C. Found by omnium21. #562
+ * Fixed multiple buffer overreads in mbedtls_pem_read_buffer() when parsing
+ the input string in PEM format to extract the different components. Found
+ by Eyal Itkin.
* Fixed potential arithmetic overflow in mbedtls_ctr_drbg_reseed() that could
cause buffer bound checks to be bypassed. Found by Eyal Itkin.
* Fixed potential arithmetic overflows in mbedtls_cipher_update() that could
diff --git a/library/pk.c b/library/pk.c
index 4d78b57..fc036d2 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -30,6 +30,8 @@
#include "polarssl/pk.h"
#include "polarssl/pk_wrap.h"
+#include "polarssl/bignum.h"
+
#if defined(POLARSSL_RSA_C)
#include "polarssl/rsa.h"
#endif
@@ -40,6 +42,8 @@
#include "polarssl/ecdsa.h"
#endif
+#include <limits.h>
+
/* Implementation that should never be optimized out by the compiler */
static void polarssl_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
@@ -208,6 +212,11 @@
int ret;
const pk_rsassa_pss_options *pss_opts;
+#if defined(POLARSSL_HAVE_INT64)
+ if( md_alg == POLARSSL_MD_NONE && UINT_MAX < hash_len )
+ return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+#endif /* POLARSSL_HAVE_INT64 */
+
if( options == NULL )
return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
@@ -231,7 +240,7 @@
return( 0 );
#else
return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
-#endif
+#endif /* POLARSSL_RSA_C && POLARSSL_PKCS1_V21 */
}
/* General case: no options */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 6068605..ceaaad1 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -31,6 +31,7 @@
/* Even if RSA not activated, for the sake of RSA-alt */
#include "polarssl/rsa.h"
+#include "polarssl/bignum.h"
#include <string.h>
@@ -50,6 +51,8 @@
#define polarssl_free free
#endif
+#include <limits.h>
+
/* Implementation that should never be optimized out by the compiler */
static void polarssl_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
@@ -73,6 +76,11 @@
{
int ret;
+#if defined(POLARSSL_HAVE_INT64)
+ if( md_alg == POLARSSL_MD_NONE && UINT_MAX < hash_len )
+ return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+#endif /* POLARSSL_HAVE_INT64 */
+
if( sig_len < ((rsa_context *) ctx)->len )
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
@@ -92,6 +100,11 @@
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
+#if defined(POLARSSL_HAVE_INT64)
+ if( md_alg == POLARSSL_MD_NONE && UINT_MAX < hash_len )
+ return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+#endif /* POLARSSL_HAVE_INT64 */
+
*sig_len = ((rsa_context *) ctx)->len;
return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, RSA_PRIVATE,
@@ -411,6 +424,11 @@
{
rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+#if defined(POLARSSL_HAVE_INT64)
+ if( UINT_MAX < hash_len )
+ return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+#endif /* POLARSSL_HAVE_INT64 */
+
*sig_len = rsa_alt->key_len_func( rsa_alt->key );
return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, RSA_PRIVATE,
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 73694d2..7915be7 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -150,3 +150,6 @@
depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_RSA_C
pk_check_pair:"data_files/ec_256_pub.pem":"data_files/server1.key":POLARSSL_ERR_PK_TYPE_MISMATCH
+RSA hash_len overflow (size_t vs unsigned int)
+depends_on:POLARSSL_RSA_C:POLARSSL_HAVE_INT64
+pk_rsa_overflow:
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index cc378c4..435efb4 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -5,6 +5,9 @@
#include "polarssl/ecp.h"
#include "polarssl/rsa.h"
+/* For detecting 64-bit compilation */
+#include "polarssl/bignum.h"
+
static int rnd_std_rand( void *rng_state, unsigned char *output, size_t len );
#define RSA_KEY_SIZE 512
@@ -414,6 +417,33 @@
}
/* END_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C:POLARSSL_HAVE_INT64 */
+void pk_rsa_overflow( )
+{
+ pk_context pk;
+ size_t hash_len = (size_t)-1;
+
+ pk_init( &pk );
+
+ TEST_ASSERT( pk_init_ctx( &pk, pk_info_from_type( POLARSSL_PK_RSA ) ) == 0 );
+
+#if defined(POLARSSL_PKCS1_V21)
+ TEST_ASSERT( pk_verify_ext( POLARSSL_PK_RSASSA_PSS, NULL, &pk,
+ POLARSSL_MD_NONE, NULL, hash_len, NULL, 0 ) ==
+ POLARSSL_ERR_PK_BAD_INPUT_DATA );
+#endif /* POLARSSL_PKCS1_V21 */
+
+ TEST_ASSERT( pk_verify( &pk, POLARSSL_MD_NONE, NULL, hash_len,
+ NULL, 0 ) == POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+ TEST_ASSERT( pk_sign( &pk, POLARSSL_MD_NONE, NULL, hash_len, NULL, 0,
+ rnd_std_rand, NULL ) == POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+exit:
+ pk_free( &pk );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
void pk_rsa_alt( )
{
@@ -461,6 +491,11 @@
/* Test signature */
TEST_ASSERT( pk_sign( &alt, POLARSSL_MD_NONE, hash, sizeof hash,
sig, &sig_len, rnd_std_rand, NULL ) == 0 );
+#if defined(POLARSSL_HAVE_INT64)
+ TEST_ASSERT( pk_sign( &alt, POLARSSL_MD_NONE, hash, (size_t)-1,
+ NULL, NULL, rnd_std_rand, NULL ) ==
+ POLARSSL_ERR_PK_BAD_INPUT_DATA );
+#endif /* POLARSSL_HAVE_INT64 */
TEST_ASSERT( sig_len == RSA_KEY_LEN );
TEST_ASSERT( pk_verify( &rsa, POLARSSL_MD_NONE,
hash, sizeof hash, sig, sig_len ) == 0 );