PolarSSL Security Advisory 2012-01
Title |
Weak Diffie-Hellman and RSA key generation |
---|---|
CVE |
CVE-2012-2130 |
Date |
23th of April 2012 ( Updated on 14th of October 2012 ) |
Affects |
PolarSSL 0.99-pre4 up to and including PolarSSL 1.1.1 |
Not affected |
Instances not using Diffie-Hellman 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 Diffie-Hellman key exchange or |
Credits |
Ruslan Yushchenko |
During code migration a bug was introduced in PolarSSL 0.99-pre4. 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 full-size values of X and primes.
If you generated primes or RSA keys from within PolarSSL, re-generate and replace those primes / keys.
Workaround
For the Diffie-Hellman 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 ) );