Merge branch 'mbedtls-2.16' into mbedtls-2.16-restricted
* mbedtls-2.16: (21 commits)
Reword changelog - Test Resource Leak
Update changelog formatting - Missing Free Context
Fix fd range for select on Windows
Refactor file descriptor checks into a common function
Update changelog formatting - Missing Free Context
Update changelog formatting - Missing Free Context
Changelog entry for Free Context in test_suite_aes fix
Free context at the end of aes_crypt_xts_size()
Add changelog entry for non-uniform MPI random generation
ecp: Fix bias in the generation of blinding values
DHM: add test case with x_size < 0
DHM tests: add some explanations
DHM: add notes about leading zeros
dhm: Fix bias in private key generation and blinding
dhm_check_range: microoptimization
DHM refactoring: use dhm_random_below in dhm_make_common
DHM blinding: don't accept P-1 as a blinding value
DHM refactoring: unify mbedtls_dhm_make_{params,public}
Test mbedtls_dhm_make_params with different x_size
Repeat a few DH tests
...
diff --git a/ChangeLog.d/issue4176.txt b/ChangeLog.d/issue4176.txt
new file mode 100644
index 0000000..ddca37f
--- /dev/null
+++ b/ChangeLog.d/issue4176.txt
@@ -0,0 +1,3 @@
+Bugfix
+ * Fix a resource leak in a test suite with an alternative AES
+ implementation. Fixes #4176.
diff --git a/ChangeLog.d/random-range.txt b/ChangeLog.d/random-range.txt
new file mode 100644
index 0000000..dc35ec6
--- /dev/null
+++ b/ChangeLog.d/random-range.txt
@@ -0,0 +1,4 @@
+Security
+* Fix a bias in the generation of finite-field Diffie-Hellman-Merkle (DHM)
+ private keys and of blinding values for DHM and elliptic curves (ECP)
+ computations. Reported by FlorianF89 in #4245.
diff --git a/ChangeLog.d/winsock.txt b/ChangeLog.d/winsock.txt
new file mode 100644
index 0000000..0b42e69
--- /dev/null
+++ b/ChangeLog.d/winsock.txt
@@ -0,0 +1,4 @@
+Bugfix
+ * Fix mbedtls_net_poll() and mbedtls_net_recv_timeout() often failing with
+ MBEDTLS_ERR_NET_POLL_FAILED on Windows. Fixes #4465.
+
diff --git a/library/dhm.c b/library/dhm.c
index d652cf0..535b698 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -130,22 +130,21 @@
*/
static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
{
- mbedtls_mpi L, U;
+ mbedtls_mpi U;
int ret = 0;
- mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
+ mbedtls_mpi_init( &U );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
- if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
+ if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
{
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
cleanup:
- mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
+ mbedtls_mpi_free( &U );
return( ret );
}
@@ -181,38 +180,54 @@
}
/*
- * Setup and write the ServerKeyExchange parameters
+ * Pick a random R in the range [2, M-2] for blinding or key generation.
*/
-int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
- unsigned char *output, size_t *olen,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret, count = 0;
- size_t n1, n2, n3;
- unsigned char *p;
- DHM_VALIDATE_RET( ctx != NULL );
- DHM_VALIDATE_RET( output != NULL );
- DHM_VALIDATE_RET( olen != NULL );
- DHM_VALIDATE_RET( f_rng != NULL );
+ int ret, count;
+ size_t m_size = mbedtls_mpi_size( M );
+ size_t m_bitlen = mbedtls_mpi_bitlen( M );
+
+ count = 0;
+ do
+ {
+ if( count++ > 30 )
+ return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, m_size, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, ( m_size * 8 ) - m_bitlen ) );
+ }
+ while( dhm_check_range( R, M ) != 0 );
+
+cleanup:
+ return( ret );
+}
+
+static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret = 0;
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+ if( x_size < 0 )
+ return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
- /*
- * Generate X as large as possible ( < P )
- */
- do
+ if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
-
- if( count++ > 10 )
- return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
}
- while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+ else
+ {
+ /* Generate X as large as possible ( <= P - 2 ) */
+ ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
+ if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+ return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
+ if( ret != 0 )
+ return( ret );
+ }
/*
* Calculate GX = G^X mod P
@@ -223,8 +238,33 @@
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
return( ret );
+cleanup:
+ return( ret );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
+ unsigned char *output, size_t *olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ size_t n1, n2, n3;
+ unsigned char *p;
+ DHM_VALIDATE_RET( ctx != NULL );
+ DHM_VALIDATE_RET( output != NULL );
+ DHM_VALIDATE_RET( olen != NULL );
+ DHM_VALIDATE_RET( f_rng != NULL );
+
+ ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
+ if( ret != 0 )
+ goto cleanup;
+
/*
- * export P, G, GX
+ * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
+ * not required". We omit leading zeros for compactness.
*/
#define DHM_MPI_EXPORT( X, n ) \
do { \
@@ -250,11 +290,9 @@
ctx->len = n1;
cleanup:
-
- if( ret != 0 )
+ if( ret != 0 && ret > -128 )
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
-
- return( 0 );
+ return( ret );
}
/*
@@ -306,7 +344,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret, count = 0;
+ int ret;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( f_rng != NULL );
@@ -314,62 +352,18 @@
if( olen < 1 || olen > ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
- if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
- return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
-
- /*
- * generate X and calculate GX = G^X mod P
- */
- do
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
-
- if( count++ > 10 )
- return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
- }
- while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
-
- MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
- &ctx->P , &ctx->RP ) );
-
- if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
- return( ret );
+ ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
+ if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
+ return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
+ if( ret != 0 )
+ goto cleanup;
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
cleanup:
-
- if( ret != 0 )
+ if( ret != 0 && ret > -128 )
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
- return( 0 );
-}
-
-/*
- * Pick a random R in the range [2, M) for blinding purposes
- */
-static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
-{
- int ret, count;
-
- count = 0;
- do
- {
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
-
- if( count++ > 10 )
- return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
- }
- while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
-
-cleanup:
return( ret );
}
@@ -420,7 +414,7 @@
* We need to generate blinding values from scratch
*/
- /* Vi = random( 2, P-1 ) */
+ /* Vi = random( 2, P-2 ) */
MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
/* Vf = Vi^-X mod P
@@ -484,8 +478,9 @@
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
}
+ /* Output the secret without any leading zero byte. This is mandatory
+ * for TLS per RFC 5246 §8.1.2. */
*olen = mbedtls_mpi_size( &ctx->K );
-
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
cleanup:
diff --git a/library/ecp.c b/library/ecp.c
index 9db6988..285c363 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -1738,18 +1738,17 @@
/* Generate l such that 1 < l < p */
do
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
-
- if( count++ > 10 )
+ if( count++ > 30 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
}
- while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
+ while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
+ ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
/* Z = l * Z */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z );
@@ -2514,18 +2513,17 @@
/* Generate l such that 1 < l < p */
do
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
-
- while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
-
- if( count++ > 10 )
+ if( count++ > 30 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
}
- while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
+ while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
+ ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 3874783..1e701a5 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -167,6 +167,31 @@
}
/*
+ * Return 0 if the file descriptor is valid, an error otherwise.
+ * If for_select != 0, check whether the file descriptor is within the range
+ * allowed for fd_set used for the FD_xxx macros and the select() function.
+ */
+static int check_fd( int fd, int for_select )
+{
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+ !defined(EFI32)
+ (void) for_select;
+#else
+ /* A limitation of select() is that it only works with file descriptors
+ * that are strictly less than FD_SETSIZE. This is a limitation of the
+ * fd_set type. Error out early, because attempting to call FD_SET on a
+ * large file descriptor is a buffer overflow on typical platforms. */
+ if( for_select && fd >= FD_SETSIZE )
+ return( MBEDTLS_ERR_NET_POLL_FAILED );
+#endif
+
+ return( 0 );
+}
+
+/*
* Initialize a context
*/
void mbedtls_net_init( mbedtls_net_context *ctx )
@@ -497,15 +522,9 @@
int fd = ctx->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
-
- /* A limitation of select() is that it only works with file descriptors
- * that are strictly less than FD_SETSIZE. This is a limitation of the
- * fd_set type. Error out early, because attempting to call FD_SET on a
- * large file descriptor is a buffer overflow on typical platforms. */
- if( fd >= FD_SETSIZE )
- return( MBEDTLS_ERR_NET_POLL_FAILED );
+ ret = check_fd( fd, 1 );
+ if( ret != 0 )
+ return( ret );
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
@@ -584,8 +603,9 @@
int ret;
int fd = ((mbedtls_net_context *) ctx)->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ ret = check_fd( fd, 0 );
+ if( ret != 0 )
+ return( ret );
ret = (int) read( fd, buf, len );
@@ -623,15 +643,9 @@
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
-
- /* A limitation of select() is that it only works with file descriptors
- * that are strictly less than FD_SETSIZE. This is a limitation of the
- * fd_set type. Error out early, because attempting to call FD_SET on a
- * large file descriptor is a buffer overflow on typical platforms. */
- if( fd >= FD_SETSIZE )
- return( MBEDTLS_ERR_NET_POLL_FAILED );
+ ret = check_fd( fd, 1 );
+ if( ret != 0 )
+ return( ret );
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
@@ -671,8 +685,9 @@
int ret;
int fd = ((mbedtls_net_context *) ctx)->fd;
- if( fd < 0 )
- return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ ret = check_fd( fd, 0 );
+ if( ret != 0 )
+ return( ret );
ret = (int) write( fd, buf, len );
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index 23bf83d..1b7e5db 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -208,6 +208,8 @@
/* Valid pointers are passed for builds with MBEDTLS_CHECK_PARAMS, as
* otherwise we wouldn't get to the size check we're interested in. */
TEST_ASSERT( mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, length, data_unit, src, output ) == retval );
+exit:
+ mbedtls_aes_xts_free( &ctx );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index c4795b6..6802f54 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -1,26 +1,92 @@
+Diffie-Hellman full exchange: tiny x_size
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
Diffie-Hellman parameter validation
dhm_invalid_params:
-Diffie-Hellman full exchange #1
-dhm_do_dhm:10:"23":10:"5":0
+Diffie-Hellman full exchange: 5-bit, x_size=3
+dhm_do_dhm:10:"23":3:10:"5":0
-Diffie-Hellman full exchange #2
-dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622":0
+Diffie-Hellman full exchange: 5-bit, x_size=2
+dhm_do_dhm:10:"23":2:10:"5":0
-Diffie-Hellman full exchange #3
-dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271":0
+## Repeat this test case and a few similar ones several times. The RNG state
+## changes, so we get to exercise the code with a few different values.
+Diffie-Hellman full exchange: 5-bit #1
+dhm_do_dhm:10:"23":1:10:"5":0
+
+Diffie-Hellman full exchange: 5-bit #2
+dhm_do_dhm:10:"23":1:10:"5":0
+
+Diffie-Hellman full exchange: 5-bit #3
+dhm_do_dhm:10:"23":1:10:"5":0
+
+Diffie-Hellman full exchange: 5-bit #4
+dhm_do_dhm:10:"23":1:10:"5":0
+
+Diffie-Hellman full exchange: 5-bit #5
+dhm_do_dhm:10:"23":1:10:"5":0
+
+## This is x_size = P_size + 1. Arguably x_size > P_size makes no sense,
+## but it's the current undocumented behavior to treat it the same as when
+## x_size = P_size. If this behavior changes in the future, change the expected
+## return status from 0 to MBEDTLS_ERR_DHM_BAD_INPUT_DATA.
+Diffie-Hellman full exchange: 97-bit, x_size=14
+dhm_do_dhm:10:"93450983094850938450983409623":14:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #1
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #2
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #3
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #4
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #5
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=12
+dhm_do_dhm:10:"93450983094850938450983409623":12:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=11
+dhm_do_dhm:10:"93450983094850938450983409623":11:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #1
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #2
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #3
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #4
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #5
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 286-bit
+dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":36:10:"9345098309485093845098340962223981329819812792137312973297123912791271":0
Diffie-Hellman trivial subgroup #1
-dhm_do_dhm:10:"23":10:"1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+dhm_do_dhm:10:"23":1:10:"1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
Diffie-Hellman trivial subgroup #2
-dhm_do_dhm:10:"23":10:"-1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+dhm_do_dhm:10:"23":1:10:"-1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
Diffie-Hellman small modulus
-dhm_do_dhm:10:"3":10:"5":MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED
+dhm_do_dhm:10:"3":1:10:"5":MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED
Diffie-Hellman zero modulus
-dhm_do_dhm:10:"0":10:"5":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+dhm_do_dhm:10:"0":1:10:"5":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman: x_size < 0
+dhm_do_dhm:10:"93450983094850938450983409623":-1:10:"9345098304850938450983409622":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
Diffie-Hellman MPI_MAX_SIZE modulus
dhm_make_public:MBEDTLS_MPI_MAX_SIZE:10:"5":0
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index 6ec1e7e8..2e8644d 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -1,5 +1,66 @@
/* BEGIN_HEADER */
#include "mbedtls/dhm.h"
+
+/* Sanity checks on a Diffie-Hellman parameter: check the length-value
+ * syntax and check that the value is the expected one (taken from the
+ * DHM context by the caller). */
+static int check_dhm_param_output( const mbedtls_mpi *expected,
+ const unsigned char *buffer,
+ size_t size,
+ size_t *offset )
+{
+ size_t n;
+ mbedtls_mpi actual;
+ int ok = 0;
+ mbedtls_mpi_init( &actual );
+
+ TEST_ASSERT( size >= *offset + 2 );
+ n = ( buffer[*offset] << 8 ) | buffer[*offset + 1];
+ *offset += 2;
+ /* The DHM param output from Mbed TLS has leading zeros stripped, as
+ * permitted but not required by RFC 5246 \S4.4. */
+ TEST_EQUAL( n, mbedtls_mpi_size( expected ) );
+ TEST_ASSERT( size >= *offset + n );
+ TEST_EQUAL( 0, mbedtls_mpi_read_binary( &actual, buffer + *offset, n ) );
+ TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( expected, &actual ) );
+ *offset += n;
+
+ ok = 1;
+exit:
+ mbedtls_mpi_free( &actual );
+ return( ok );
+}
+
+/* Sanity checks on Diffie-Hellman parameters: syntax, range, and comparison
+ * against the context. */
+static int check_dhm_params( const mbedtls_dhm_context *ctx,
+ size_t x_size,
+ const unsigned char *ske, size_t ske_len )
+{
+ size_t offset = 0;
+
+ /* Check that ctx->X and ctx->GX are within range. */
+ TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->X, 1 ) > 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) < 0 );
+ TEST_ASSERT( mbedtls_mpi_size( &ctx->X ) <= x_size );
+ TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->GX, 1 ) > 0 );
+ TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->GX, &ctx->P ) < 0 );
+
+ /* Check ske: it must contain P, G and G^X, each prefixed with a
+ * 2-byte size. */
+ if( !check_dhm_param_output( &ctx->P, ske, ske_len, &offset ) )
+ goto exit;
+ if( !check_dhm_param_output( &ctx->G, ske, ske_len, &offset ) )
+ goto exit;
+ if( !check_dhm_param_output( &ctx->GX, ske, ske_len, &offset ) )
+ goto exit;
+ TEST_EQUAL( offset, ske_len );
+
+ return( 1 );
+exit:
+ return( 0 );
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -115,7 +176,7 @@
/* END_CASE */
/* BEGIN_CASE */
-void dhm_do_dhm( int radix_P, char *input_P,
+void dhm_do_dhm( int radix_P, char *input_P, int x_size,
int radix_G, char *input_G, int result )
{
mbedtls_dhm_context ctx_srv;
@@ -129,7 +190,7 @@
size_t pub_cli_len = 0;
size_t sec_srv_len;
size_t sec_cli_len;
- int x_size, i;
+ int i;
rnd_pseudo_info rnd_info;
mbedtls_dhm_init( &ctx_srv );
@@ -145,15 +206,18 @@
*/
TEST_ASSERT( mbedtls_mpi_read_string( &ctx_srv.P, radix_P, input_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx_srv.G, radix_G, input_G ) == 0 );
- x_size = mbedtls_mpi_size( &ctx_srv.P );
- pub_cli_len = x_size;
+ pub_cli_len = mbedtls_mpi_size( &ctx_srv.P );
/*
* First key exchange
*/
- TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == result );
+ TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len,
+ &rnd_pseudo_rand,
+ &rnd_info ) == result );
if ( result != 0 )
goto exit;
+ if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) )
+ goto exit;
ske[ske_len++] = 0;
ske[ske_len++] = 0;
@@ -185,7 +249,11 @@
*/
p = ske;
- TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+ TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len,
+ &rnd_pseudo_rand,
+ &rnd_info ) == 0 );
+ if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) )
+ goto exit;
ske[ske_len++] = 0;
ske[ske_len++] = 0;
TEST_ASSERT( mbedtls_dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );