Merge pull request #781 from mpg/cipher-auth-crypt-restricted

Fix buffer overflow with NIST-KW in cipher layer
diff --git a/ChangeLog.d/limit_size_of_diffie_hellman_calculations.txt b/ChangeLog.d/limit_size_of_diffie_hellman_calculations.txt
new file mode 100644
index 0000000..2ba98d5
--- /dev/null
+++ b/ChangeLog.d/limit_size_of_diffie_hellman_calculations.txt
@@ -0,0 +1,4 @@
+Security
+   * Limit the size of calculations performed by mbedtls_mpi_exp_mod to
+     MBEDTLS_MPI_MAX_SIZE to prevent a potential denial of service when
+     generating Diffie-Hellman key pairs. Credit to OSS-Fuzz.
diff --git a/ChangeLog.d/missing-debug-message-arguments_mbedtls_ssl_decrypt_buf.txt b/ChangeLog.d/missing-debug-message-arguments_mbedtls_ssl_decrypt_buf.txt
new file mode 100644
index 0000000..e03178f
--- /dev/null
+++ b/ChangeLog.d/missing-debug-message-arguments_mbedtls_ssl_decrypt_buf.txt
@@ -0,0 +1,2 @@
+Bugfix
+  * Add missing arguments of debug message in mbedtls_ssl_decrypt_buf.
diff --git a/ChangeLog.d/x509-add-tag-check-to-algorithm-params b/ChangeLog.d/x509-add-tag-check-to-algorithm-params
new file mode 100644
index 0000000..f2c72b0
--- /dev/null
+++ b/ChangeLog.d/x509-add-tag-check-to-algorithm-params
@@ -0,0 +1,11 @@
+Security
+   * Fix a compliance issue whereby we were not checking the tag on the
+     algorithm parameters (only the size) when comparing the signature in the
+     description part of the cert to the real signature. This meant that a
+     NULL algorithm parameters entry would look identical to an array of REAL
+     (size zero) to the library and thus the certificate would be considered
+     valid. However, if the parameters do not match in *any* way then the
+     certificate should be considered invalid, and indeed OpenSSL marks these
+     certs as invalid when mbedtls did not.
+     Many thanks to guidovranken who found this issue via differential fuzzing
+     and reported it in #3629.
diff --git a/library/bignum.c b/library/bignum.c
index d5b644f..6ac9fed 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -2115,6 +2115,10 @@
     if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
 
+    if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
+        mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
+        return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
     /*
      * Init temps and window size
      */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 597494e..72f09bb 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -1385,7 +1385,9 @@
         /* Check that there's space for the authentication tag. */
         if( rec->data_len < transform->taglen )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < taglen (%d) " ) );
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < taglen (%d) ",
+                                        rec->data_len,
+                                        transform->taglen ) );
             return( MBEDTLS_ERR_SSL_INVALID_MAC );
         }
         rec->data_len -= transform->taglen;
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 71e9cec..a623c57 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1304,6 +1304,7 @@
 
     if( crt->sig_oid.len != sig_oid2.len ||
         memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
+        sig_params1.tag != sig_params2.tag ||
         sig_params1.len != sig_params2.len ||
         ( sig_params1.len != 0 &&
           memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index bf2f538..b90ce74 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -208,7 +208,11 @@
 	$(OPENSSL) x509 -in $< -out $@ -inform PEM -outform DER
 all_final += cli-rsa-sha256.crt.der
 
- cli-rsa.key.der: $(cli_crt_key_file_rsa)
+cli-rsa-sha256-badalg.crt.der: cli-rsa-sha256.crt.der
+	hexdump -ve '1/1 "%.2X"' $< | sed "s/06092A864886F70D01010B0500/06092A864886F70D01010B0900/2" | xxd -r -p > $@
+all_final += cli-rsa-sha256-badalg.crt.der
+
+cli-rsa.key.der: $(cli_crt_key_file_rsa)
 	$(OPENSSL) pkey -in $< -out $@ -inform PEM -outform DER
 all_final += cli-rsa.key.der
 
diff --git a/tests/data_files/cli-rsa-sha256-badalg.crt.der b/tests/data_files/cli-rsa-sha256-badalg.crt.der
new file mode 100644
index 0000000..c40ba2a
--- /dev/null
+++ b/tests/data_files/cli-rsa-sha256-badalg.crt.der
Binary files differ
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index 4e884f4..c4795b6 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -22,6 +22,12 @@
 Diffie-Hellman zero modulus
 dhm_do_dhm:10:"0":10:"5":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
 
+Diffie-Hellman MPI_MAX_SIZE modulus
+dhm_make_public:MBEDTLS_MPI_MAX_SIZE:10:"5":0
+
+Diffie-Hellman MPI_MAX_SIZE + 1 modulus
+dhm_make_public:MBEDTLS_MPI_MAX_SIZE + 1:10:"5":MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED+MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
 Diffie-Hellman load parameters from file [#1]
 dhm_file:"data_files/dhparams.pem":"9e35f430443a09904f3a39a979797d070df53378e79c2438bef4e761f3c714553328589b041c809be1d6c6b5f1fc9f47d3a25443188253a992a56818b37ba9de5a40d362e56eff0be5417474c125c199272c8fe41dea733df6f662c92ae76556e755d10c64e6a50968f67fc6ea73d0dca8569be2ba204e23580d8bca2f4975b3":"02":128
 
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index 0a5c617..1726b9e 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -223,6 +223,36 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void dhm_make_public( int P_bytes, int radix_G, char *input_G, int result )
+{
+    mbedtls_mpi P, G;
+    mbedtls_dhm_context ctx;
+    unsigned char output[MBEDTLS_MPI_MAX_SIZE];
+
+    mbedtls_mpi_init( &P );
+    mbedtls_mpi_init( &G );
+    mbedtls_dhm_init( &ctx );
+
+    TEST_ASSERT( mbedtls_mpi_lset( &P, 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_shift_l( &P, ( P_bytes * 8 ) - 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_set_bit( &P, 0, 1 ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_read_string( &G, radix_G, input_G ) == 0 );
+
+    TEST_ASSERT( mbedtls_dhm_set_group( &ctx, &P, &G ) == 0 );
+    TEST_ASSERT( mbedtls_dhm_make_public( &ctx, (int) mbedtls_mpi_size( &P ),
+                                          output, sizeof(output),
+                                          &mbedtls_test_rnd_pseudo_rand,
+                                          NULL ) == result );
+
+exit:
+    mbedtls_mpi_free( &P );
+    mbedtls_mpi_free( &G );
+    mbedtls_dhm_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
 void dhm_file( char * filename, char * p, char * g, int len )
 {
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 3aebd6c..27c57b7 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -691,16 +691,36 @@
 Base test mbedtls_mpi_exp_mod #5 (Negative exponent)
 mbedtls_mpi_exp_mod:10:"23":10:"-13":10:"29":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
-Base test mbedtls_mpi_exp_mod #7 (Negative base + exponent)
+Base test mbedtls_mpi_exp_mod #6 (Negative base + exponent)
 mbedtls_mpi_exp_mod:10:"-23":10:"-13":10:"29":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
+Test mbedtls_mpi_exp_mod: MAX_SIZE exponent
+mbedtls_mpi_exp_mod_size:2:MBEDTLS_MPI_MAX_SIZE:10:10:"":0
+
+Test mbedtls_mpi_exp_mod: MAX_SIZE + 1 exponent
+mbedtls_mpi_exp_mod_size:2:MBEDTLS_MPI_MAX_SIZE + 1:10:10:"":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mbedtls_mpi_exp_mod: MAX_SIZE modulus
+mbedtls_mpi_exp_mod_size:2:2:MBEDTLS_MPI_MAX_SIZE:10:"":0
+
+Test mbedtls_mpi_exp_mod: MAX_SIZE + 1 modulus
+mbedtls_mpi_exp_mod_size:2:2:MBEDTLS_MPI_MAX_SIZE + 1:10:"":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mbedtls_mpi_exp_mod: MAX_SIZE exponent and modulus
+mbedtls_mpi_exp_mod_size:2:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE:10:"":0
+
+Test mbedtls_mpi_exp_mod: MAX_SIZE + 1 exponent and modulus
+mbedtls_mpi_exp_mod_size:2:MBEDTLS_MPI_MAX_SIZE + 1:MBEDTLS_MPI_MAX_SIZE + 1:10:"":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
 Test mbedtls_mpi_exp_mod #1
+depends_on:MPI_MAX_BITS_LARGER_THAN_792
 mbedtls_mpi_exp_mod:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"583137007797276923956891216216022144052044091311388601652961409557516421612874571554415606746479105795833145583959622117418531166391184939066520869800857530421873250114773204354963864729386957427276448683092491947566992077136553066273207777134303397724679138833126700957":10:"":10:"114597449276684355144920670007147953232659436380163461553186940113929777196018164149703566472936578890991049344459204199888254907113495794730452699842273939581048142004834330369483813876618772578869083248061616444392091693787039636316845512292127097865026290173004860736":0
 
 Test mbedtls_mpi_exp_mod (Negative base) [#1]
 mbedtls_mpi_exp_mod:10:"-10000000000":10:"10000000000":10:"99999":10:"":10:"1":0
 
 Test mbedtls_mpi_exp_mod (Negative base) [#2]
+depends_on:MPI_MAX_BITS_LARGER_THAN_792
 mbedtls_mpi_exp_mod:16:"-9f13012cd92aa72fb86ac8879d2fde4f7fd661aaae43a00971f081cc60ca277059d5c37e89652e2af2585d281d66ef6a9d38a117e9608e9e7574cd142dc55278838a2161dd56db9470d4c1da2d5df15a908ee2eb886aaa890f23be16de59386663a12f1afbb325431a3e835e3fd89b98b96a6f77382f458ef9a37e1f84a03045c8676ab55291a94c2228ea15448ee96b626b998":16:"40a54d1b9e86789f06d9607fb158672d64867665c73ee9abb545fc7a785634b354c7bae5b962ce8040cf45f2c1f3d3659b2ee5ede17534c8fc2ec85c815e8df1fe7048d12c90ee31b88a68a081f17f0d8ce5f4030521e9400083bcea73a429031d4ca7949c2000d597088e0c39a6014d8bf962b73bb2e8083bd0390a4e00b9b3":16:"eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3":16:"":16:"21acc7199e1b90f9b4844ffe12c19f00ec548c5d32b21c647d48b6015d8eb9ec9db05b4f3d44db4227a2b5659c1a7cceb9d5fa8fa60376047953ce7397d90aaeb7465e14e820734f84aa52ad0fc66701bcbb991d57715806a11531268e1e83dd48288c72b424a6287e9ce4e5cc4db0dd67614aecc23b0124a5776d36e5c89483":0
 
 Base test GCD #1
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 09c31cc..bdc1d9e 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -2,6 +2,10 @@
 #include "mbedtls/bignum.h"
 #include "mbedtls/entropy.h"
 
+#if MBEDTLS_MPI_MAX_BITS > 792
+#define MPI_MAX_BITS_LARGER_THAN_792
+#endif
+
 typedef struct mbedtls_test_mpi_random
 {
     data_t *data;
@@ -1182,6 +1186,40 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void mbedtls_mpi_exp_mod_size( int A_bytes, int E_bytes, int N_bytes,
+                               int radix_RR, char * input_RR, int exp_result )
+{
+    mbedtls_mpi A, E, N, RR, Z;
+    mbedtls_mpi_init( &A  ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N );
+    mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &Z );
+
+    /* Set A to 2^(A_bytes - 1) + 1 */
+    TEST_ASSERT( mbedtls_mpi_lset( &A, 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_shift_l( &A, ( A_bytes * 8 ) - 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_set_bit( &A, 0, 1 ) == 0 );
+
+    /* Set E to 2^(E_bytes - 1) + 1 */
+    TEST_ASSERT( mbedtls_mpi_lset( &E, 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_shift_l( &E, ( E_bytes * 8 ) - 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_set_bit( &E, 0, 1 ) == 0 );
+
+    /* Set N to 2^(N_bytes - 1) + 1 */
+    TEST_ASSERT( mbedtls_mpi_lset( &N, 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_shift_l( &N, ( N_bytes * 8 ) - 1 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_set_bit( &N, 0, 1 ) == 0 );
+
+    if( strlen( input_RR ) )
+        TEST_ASSERT( mbedtls_mpi_read_string( &RR, radix_RR, input_RR ) == 0 );
+
+    TEST_ASSERT( mbedtls_mpi_exp_mod( &Z, &A, &E, &N, &RR ) == exp_result );
+
+exit:
+    mbedtls_mpi_free( &A  ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N );
+    mbedtls_mpi_free( &RR ); mbedtls_mpi_free( &Z );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mbedtls_mpi_inv_mod( int radix_X, char * input_X, int radix_Y,
                           char * input_Y, int radix_A, char * input_A,
                           int div_result )
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index bfdbab2..3b84609 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -2652,6 +2652,10 @@
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
 x509parse_crt_file:"data_files/server7_trailing_space.crt":0
 
+X509 File parse (Algorithm Params Tag mismatch)
+depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+x509parse_crt_file:"data_files/cli-rsa-sha256-badalg.crt.der":MBEDTLS_ERR_X509_SIG_MISMATCH
+
 X509 Get time (UTC no issues)
 depends_on:MBEDTLS_X509_USE_C
 x509_get_time:MBEDTLS_ASN1_UTC_TIME:"500101000000Z":0:1950:1:1:0:0:0