diff --git a/ChangeLog b/ChangeLog index 6a32ba438..7824fc421 100644 --- a/ChangeLog +++ b/ChangeLog @@ -114,6 +114,9 @@ Bugfix curve picked by the server was actually allowed. Changes + * Remove bias in mpi_gen_prime (contributed by Pascal Junod). + * Remove potential sources of timing variations (some contributed by Pascal + Junod). * Options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 are deprecated. * Enabling POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated. * compat-1.2.h and openssl.h are deprecated. diff --git a/library/bignum.c b/library/bignum.c index 45f966760..07892c59e 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -223,8 +223,8 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned int ret = 0; size_t i; - /* make sure assign is 0 or 1 */ - assign = ( assign != 0 ); + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); @@ -255,8 +255,8 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char sw if( X == Y ) return( 0 ); - /* make sure swap is 0 or 1 */ - swap = ( swap != 0 ); + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); @@ -1958,8 +1958,8 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; - size_t i, j, n, s; + int ret, count; + size_t i, j, k, n, s; mbedtls_mpi W, R, T, A, RR; mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); @@ -1996,6 +1996,23 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, } A.p[0] |= 3; + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_msb( &A ); + k = mbedtls_mpi_msb( &W ); + if (j > k) { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + /* * A = A^R mod |X| */ @@ -2092,10 +2109,11 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); k = mbedtls_mpi_msb( X ); - if( k < nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, nbits - k ) ); - if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); - X->p[0] |= 3; + mbedtls_mpi_set_bit( X, nbits-1, 1 ); + + X->p[0] |= 1; if( dh_flag == 0 ) { @@ -2114,6 +2132,9 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). * Make sure it is satisfied, while keeping X = 3 mod 4 */ + + X->p[0] |= 2; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); if( r == 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); diff --git a/library/rsa.c b/library/rsa.c index f6a88fd92..1d6fd4a7d 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -773,7 +773,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, for( i = 0; i < ilen - 2 * hlen - 2; i++ ) { pad_done |= p[i]; - pad_len += ( pad_done == 0 ); + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; } p += pad_len; @@ -847,8 +847,8 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, * (minus one, for the 00 byte) */ for( i = 0; i < ilen - 3; i++ ) { - pad_done |= ( p[i] == 0 ); - pad_count += ( pad_done == 0 ); + pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; } p += pad_count; diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 4d2032ea9..4eb546d2b 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -3235,7 +3235,7 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, unsigned char ver[2]; unsigned char fake_pms[48], peer_pms[48]; unsigned char mask; - size_t i; + size_t i, diff, peer_pmslen; if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) { @@ -3280,16 +3280,17 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, return( ret ); ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, - peer_pms, &ssl->handshake->pmslen, + peer_pms, &peer_pmslen, sizeof( peer_pms ), ssl->f_rng, ssl->p_rng ); - ret |= ssl->handshake->pmslen - 48; - ret |= peer_pms[0] - ver[0]; - ret |= peer_pms[1] - ver[1]; + diff = (size_t) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ssl->handshake->max_major_ver; + diff |= peer_pms[1] ^ ssl->handshake->max_minor_ver; -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( ret != 0 ) +#if defined(POLARSSL_SSL_DEBUG_ALL) + if( diff != 0 ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); #endif @@ -3301,7 +3302,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, } ssl->handshake->pmslen = 48; - mask = (unsigned char)( - ( ret != 0 ) ); /* ret ? 0xff : 0x00 */ + mask = ( diff | - diff ) >> ( sizeof( size_t ) * 8 - 1 ); + mask = (unsigned char)( - ( ret != 0 ) ); /* mask = diff ? 0xff : 0x00 */ for( i = 0; i < ssl->handshake->pmslen; i++ ) pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );