From b2bf5a1bbbf3652881ed55181d1f68dc6ea75dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 25 Mar 2014 16:28:12 +0100 Subject: [PATCH] Fix possible buffer overflow with PSK --- ChangeLog | 3 ++- library/ssl_srv.c | 2 +- library/ssl_tls.c | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e57b5a441..5beeb3532 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,10 +25,11 @@ Changes Security * Forbid change of server certificate during renegotiation to prevent - "triple handshake" attack when authentication mode is optional (the + "triple handshake" attack when authentication mode is 'optional' (the attack was already impossible when authentication is required). * Check notBefore timestamp of certificates and CRLs from the future. * Forbid sequence number wrapping + * Fix possible buffer overflow with overlong PSK Bugfix * ecp_gen_keypair() does more tries to prevent failure because of diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 85490502f..0241b43b7 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2455,7 +2455,7 @@ static int ssl_parse_encrypted_pms( ssl_context *ssl, ret = pk_decrypt( ssl_own_key( ssl ), p, len, pms, &ssl->handshake->pmslen, - sizeof(ssl->handshake->premaster), + sizeof( ssl->handshake->premaster ) - pms_offset, ssl->f_rng, ssl->p_rng ); if( ret != 0 || ssl->handshake->pmslen != 48 || diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3fd6e341a..8c6042858 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -916,6 +916,9 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ) } /* opaque psk<0..2^16-1>; */ + if( end - p < 2 + (int) ssl->psk_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); *(p++) = (unsigned char)( ssl->psk_len ); memcpy( p, ssl->psk, ssl->psk_len ); @@ -3784,6 +3787,14 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, if( psk == NULL || psk_identity == NULL ) return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + /* + * The length will be check later anyway, but in case it is obviously + * too large, better abort now. The PMS is as follows: + * other_len (2 bytes) + other + psk_len (2 bytes) + psk + */ + if( psk_len + 4 > POLARSSL_PREMASTER_SIZE ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + if( ssl->psk != NULL ) { polarssl_free( ssl->psk );