PolarSSL Security Advisory 201201
Title 
Weak DiffieHellman and RSA key generation 

CVE 
CVE20122130 
Date 
23th of April 2012 ( Updated on 14th of October 2012 ) 
Affects 
PolarSSL 0.99pre4 up to and including PolarSSL 1.1.1 
Not affected 
Instances not using DiffieHellman key exchange and not 
Impact 
Weak prime generation and key negotiation resulting in possible 
Exploit 
Withheld 
Solution 
Upgrade to PolarSSL 1.1.2 
Workaround 
Disable ciphersuites using DiffieHellman key exchange or 
Credits 
Ruslan Yushchenko 
During code migration a bug was introduced in PolarSSL 0.99pre4. As a result the generation of Diffie Hellman value X is weak on the client and server. Only a part of the value X is filled with random data, instead of the whole value. (Determined by the server Diffie Hellman parameters). In addition, MPI primes are only generated within a limited subspace of the full prime space. Again only a part of the prime is filled with random data, instead of the whole value.
Impact
When a weak X is generated the resulting Diffie Hellman key exchange is weaker. This makes it easier for an attacker to brute force the private value and thus the master secret. When the master secret is known, an attacker is able to modify and read all data in the secure channel.
MPI primes generated with mpi_gen_prime() are less secure. If rsa_gen_key() was used to generate RSA keys with PolarSSL, these keys are less secure as well. This only affects keys / primes generated within affected versions of PolarSSL, not keys generated in older versions or imported keys.
Resolution
PolarSSL version 1.1.2 contains a fix for the bug and generates fullsize values of X and primes.
If you generated primes or RSA keys from within PolarSSL, regenerate and replace those primes / keys.
Workaround
For the DiffieHellman side of the issue: Either patch or disable affected ciphersuites as a workaround. For the RSA side of the issue: Patch and re generate primes and RSA keys created within PolarSSL.
Disable all DHE ciphersuites in either the server or the client, so that only RSA key exchange is used. In PolarSSL this is done by modifying the list that is sent to ssl_set_ciphersuites().
Note: The RSA only suites are considered less secure because only random from one side is used. Please keep this in mind when choosing this option.
Advice
We advise everyone affected by this issue to upgrade, patch or disable the ciphersuites as soon as possible.
Patch
The patch for PolarSSL version 1.1.1 is as follows:
Index: library/dhm.c
===================================================================
 library/dhm.c
+++ library/dhm.c
@@ 130,19 +130,21 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
 int ret, n;
+ int ret;
size_t n1, n2, n3;
unsigned char *p;
/*
* Generate X as large as possible ( < P )
*/
 n = x_size / sizeof( t_uint ) + 1;
+ do
+ {
+ mpi_fill_random( &ctx>X, x_size, f_rng, p_rng );
 mpi_fill_random( &ctx>X, n, f_rng, p_rng );

 while( mpi_cmp_mpi( &ctx>X, &ctx>P ) >= 0 )
+ while( mpi_cmp_mpi( &ctx>X, &ctx>P ) >= 0 )
mpi_shift_r( &ctx>X, 1 );
+ }
+ while( dhm_check_range( &ctx>X, &ctx>P ) != 0 );
/*
* Calculate GX = G^X mod P
@@ 207,7 +209,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
 int ret, n;
+ int ret;
if( ctx == NULL  olen < 1  olen > ctx>len )
return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
@@ 215,12 +217,14 @@
/*
* generate X and calculate GX = G^X mod P
*/
 n = x_size / sizeof( t_uint ) + 1;
+ do
+ {
+ mpi_fill_random( &ctx>X, x_size, f_rng, p_rng );
 mpi_fill_random( &ctx>X, n, f_rng, p_rng );

 while( mpi_cmp_mpi( &ctx>X, &ctx>P ) >= 0 )
+ while( mpi_cmp_mpi( &ctx>X, &ctx>P ) >= 0 )
mpi_shift_r( &ctx>X, 1 );
+ }
+ while( dhm_check_range( &ctx>X, &ctx>P ) != 0 );
MPI_CHK( mpi_exp_mod( &ctx>GX, &ctx>G, &ctx>X,
&ctx>P , &ctx>RP ) );
Index: library/bignum.c
===================================================================
 library/bignum.c
+++ library/bignum.c
@@ 1813,7 +1813,7 @@
/*
* pick a random A, 1 < A < X  1
*/
 MPI_CHK( mpi_fill_random( &A, X>n, f_rng, p_rng ) );
+ MPI_CHK( mpi_fill_random( &A, X>n * ciL, f_rng, p_rng ) );
if( mpi_cmp_mpi( &A, &W ) >= 0 )
{
@@ 1885,7 +1885,7 @@
n = BITS_TO_LIMBS( nbits );
 MPI_CHK( mpi_fill_random( X, n, f_rng, p_rng ) );
+ MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
k = mpi_msb( X );
if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits  k ) );