Merge pull request #783 from chris-jones-arm/mbedtls-2.7-restricted
[Backport 2.7] Fix Diffie-Hellman large key size DoS
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/x509_crt.c b/library/x509_crt.c
index acda1f2..2334a35 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -929,6 +929,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 61edad1..d76aa5d 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -129,6 +129,14 @@
$(OPENSSL) x509 -req -extfile $(cli_crt_extensions_file) -extensions cli-rsa -CA test-ca-sha256.crt -CAkey $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 4 -days 3653 -sha256 -in cli-rsa.csr -out $@
all_final += cli-rsa-sha256.crt
+cli-rsa-sha256.crt.der: cli-rsa-sha256.crt
+ $(OPENSSL) x509 -in $< -out $@ -inform PEM -outform DER
+all_final += cli-rsa-sha256.crt.der
+
+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
+
server2-rsa.csr: server2.key
$(OPENSSL) req -new -key server2.key -passin "pass:$(test_ca_pwd_rsa)" -subj "/C=NL/O=PolarSSL/CN=localhost" -out $@
all_intermediate += server2-rsa.csr
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..be75255
--- /dev/null
+++ b/tests/data_files/cli-rsa-sha256-badalg.crt.der
Binary files differ
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index f625d73..07467cf 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -919,6 +919,48 @@
Test bit set (Invalid bit value)
mbedtls_mpi_set_bit:16:"00":5:2:16:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+Fill random: 0 bytes
+mpi_fill_random:0:0:0
+
+Fill random: 1 byte, good
+mpi_fill_random:1:1:0
+
+Fill random: 2 bytes, good, no leading zero
+mpi_fill_random:2:2:0
+
+Fill random: 2 bytes, good, 1 leading zero
+mpi_fill_random:2:256:0
+
+Fill random: MAX_SIZE - 7, good
+mpi_fill_random:MBEDTLS_MPI_MAX_SIZE - 7:MBEDTLS_MPI_MAX_SIZE - 7:0
+
+Fill random: MAX_SIZE, good
+mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE:0
+
+Fill random: 1 byte, RNG failure
+mpi_fill_random:1:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: 2 bytes, RNG failure after 1 byte
+mpi_fill_random:2:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: 4 bytes, RNG failure after 3 bytes
+mpi_fill_random:4:3:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: 8 bytes, RNG failure after 7 bytes
+mpi_fill_random:8:7:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: 16 bytes, RNG failure after 1 bytes
+mpi_fill_random:16:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: 16 bytes, RNG failure after 8 bytes
+mpi_fill_random:16:8:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: 16 bytes, RNG failure after 15 bytes
+mpi_fill_random:16:15:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+Fill random: MAX_SIZE bytes, RNG failure after MAX_SIZE-1 bytes
+mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE-1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
MPI Selftest
depends_on:MBEDTLS_SELF_TEST
mpi_selftest:
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 5bf4c27..a8146ed 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -1,5 +1,6 @@
/* BEGIN_HEADER */
#include "mbedtls/bignum.h"
+#include "mbedtls/entropy.h"
#if MBEDTLS_MPI_MAX_BITS > 792
#define MPI_MAX_BITS_LARGER_THAN_792
@@ -48,6 +49,22 @@
return( 0 );
}
+
+/* Random generator that is told how many bytes to return. */
+static int f_rng_bytes_left( void *state, unsigned char *buf, size_t len )
+{
+ size_t *bytes_left = state;
+ size_t i;
+ for( i = 0; i < len; i++ )
+ {
+ if( *bytes_left == 0 )
+ return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+ buf[i] = *bytes_left & 0xff;
+ --( *bytes_left );
+ }
+ return( 0 );
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -1075,6 +1092,37 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void mpi_fill_random( int wanted_bytes, int rng_bytes, int expected_ret )
+{
+ mbedtls_mpi X;
+ int ret;
+ size_t bytes_left = rng_bytes;
+ mbedtls_mpi_init( &X );
+
+ ret = mbedtls_mpi_fill_random( &X, wanted_bytes,
+ f_rng_bytes_left, &bytes_left );
+ TEST_ASSERT( ret == expected_ret );
+
+ if( expected_ret == 0 )
+ {
+ /* mbedtls_mpi_fill_random is documented to use bytes from the RNG
+ * as a big-endian representation of the number. We know when
+ * our RNG function returns null bytes, so we know how many
+ * leading zero bytes the number has. */
+ size_t leading_zeros = 0;
+ if( wanted_bytes > 0 && rng_bytes % 256 == 0 )
+ leading_zeros = 1;
+ TEST_ASSERT( mbedtls_mpi_size( &X ) + leading_zeros ==
+ (size_t) wanted_bytes );
+ TEST_ASSERT( (int) bytes_left == rng_bytes - wanted_bytes );
+ }
+
+exit:
+ mbedtls_mpi_free( &X );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void mpi_selftest()
{
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index b87859e..97eeac8 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1864,6 +1864,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