Commit 6e95d74f authored by Nathaniel Wesley Filardo's avatar Nathaniel Wesley Filardo Committed by Marcel Stör
Browse files

Update TLS protocol support (#2587)

* Update TLS protocol support

TLS1.0 is past PCI's EOL; BEAST is no more
Enable elliptic curve key exchanges
	Do not enable the smallest ECs for security
	Do not enable the largest ECs for computational time
	Do not enable 25519 (sad) because it doesn't go across the wire
Drop non-PFS key exchanges
Drop ARC4, Blowfish, DES, genprime, XTEA code
Drop renegotiation support completely
	It takes so much heap that it's not likely to work out well

Tidy handling of SSL_BUFFER_SIZE

Update docs
Drop mention of startcom, since they are no more, for letsencrypt

* Update mbedtls to 2.7.7

Preserve our vsnprintf and platform hacks

* Introduce TLS maximum fragment size knob

Reduce buffer size to 4Ki by default and advertize that.  That's the
largest we can advertize with the TLS MFL extension, so there's no
point in making them larger.  The truly adventurous can re-raise
SSL_BUFFER_SIZE and undefine the SSL_MAX_FRAGMENT_LENGTH_CODE and get
back to the earlier behavior.

* Default to mbedTLS debug with DEVELOP_VERSION
parent c6653b59
...@@ -38,9 +38,12 @@ ...@@ -38,9 +38,12 @@
#if defined(MBEDTLS_PKCS5_C) #if defined(MBEDTLS_PKCS5_C)
#include "mbedtls/pkcs5.h" #include "mbedtls/pkcs5.h"
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h" #include "mbedtls/asn1.h"
#include "mbedtls/cipher.h" #include "mbedtls/cipher.h"
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#endif /* MBEDTLS_ASN1_PARSE_C */
#include <string.h> #include <string.h>
...@@ -51,6 +54,22 @@ ...@@ -51,6 +54,22 @@
#define mbedtls_printf printf #define mbedtls_printf printf
#endif #endif
#if !defined(MBEDTLS_ASN1_PARSE_C)
int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t datalen,
unsigned char *output )
{
((void) pbe_params);
((void) mode);
((void) pwd);
((void) pwdlen);
((void) data);
((void) datalen);
((void) output);
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
}
#else
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations, mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type ) int *keylen, mbedtls_md_type_t *md_type )
...@@ -96,11 +115,9 @@ static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, ...@@ -96,11 +115,9 @@ static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
if( MBEDTLS_OID_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
*md_type = MBEDTLS_MD_SHA1;
if( p != end ) if( p != end )
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
...@@ -213,6 +230,7 @@ exit: ...@@ -213,6 +230,7 @@ exit:
return( ret ); return( ret );
} }
#endif /* MBEDTLS_ASN1_PARSE_C */
int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password,
size_t plen, const unsigned char *salt, size_t slen, size_t plen, const unsigned char *salt, size_t slen,
...@@ -231,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p ...@@ -231,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p
memset( counter, 0, 4 ); memset( counter, 0, 4 );
counter[3] = 1; counter[3] = 1;
#if UINT_MAX > 0xFFFFFFFF
if( iteration_count > 0xFFFFFFFF ) if( iteration_count > 0xFFFFFFFF )
return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
#endif
while( key_length ) while( key_length )
{ {
......
...@@ -181,6 +181,10 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end, ...@@ -181,6 +181,10 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
{ {
int ret; int ret;
if ( end - *p < 1 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
MBEDTLS_ERR_ASN1_OUT_OF_DATA );
/* Tag may be either OID or SEQUENCE */ /* Tag may be either OID or SEQUENCE */
params->tag = **p; params->tag = **p;
if( params->tag != MBEDTLS_ASN1_OID if( params->tag != MBEDTLS_ASN1_OID
...@@ -857,7 +861,10 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, ...@@ -857,7 +861,10 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
mbedtls_ecp_keypair_free( eck ); mbedtls_ecp_keypair_free( eck );
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
} }
}
if( p != end )
{
/* /*
* Is 'publickey' present? If not, or if we can't read it (eg because it * Is 'publickey' present? If not, or if we can't read it (eg because it
* is compressed), create it from the private key. * is compressed), create it from the private key.
...@@ -1261,7 +1268,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1261,7 +1268,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( ret ); return( ret );
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
#else #else
((void) ret);
((void) pwd); ((void) pwd);
((void) pwdlen); ((void) pwdlen);
#endif /* MBEDTLS_PEM_PARSE_C */ #endif /* MBEDTLS_PEM_PARSE_C */
...@@ -1277,6 +1283,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1277,6 +1283,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
{ {
unsigned char *key_copy; unsigned char *key_copy;
if( keylen == 0 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED ); return( MBEDTLS_ERR_PK_ALLOC_FAILED );
...@@ -1293,6 +1302,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1293,6 +1302,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 ); return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
{ {
...@@ -1304,39 +1314,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1304,39 +1314,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 ); return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
key, keylen ) ) != 0 ) key, keylen ) == 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
/* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
* it is ok to leave the PK context initialized but not
* freed: It is the caller's responsibility to call pk_init()
* before calling this function, and to call pk_free()
* when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
* isn't, this leads to mbedtls_pk_free() being called
* twice, once here and once by the caller, but this is
* also ok and in line with the mbedtls_pk_free() calls
* on failed PEM parsing attempts. */
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
} }
......
...@@ -46,7 +46,14 @@ static void mbedtls_zeroize( void *v, size_t n ) { ...@@ -46,7 +46,14 @@ static void mbedtls_zeroize( void *v, size_t n ) {
} }
#endif #endif
#if defined(MBEDTLS_PLATFORM_MEMORY) /* The compile time configuration of memory allocation via the macros
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
* configuration via mbedtls_platform_set_calloc_free(). So, omit everything
* related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
#if defined(MBEDTLS_PLATFORM_MEMORY) && \
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \
defined(MBEDTLS_PLATFORM_FREE_MACRO) )
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
static void *platform_calloc_uninit( size_t n, size_t size ) static void *platform_calloc_uninit( size_t n, size_t size )
{ {
...@@ -77,7 +84,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), ...@@ -77,7 +84,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
mbedtls_free = free_func; mbedtls_free = free_func;
return( 0 ); return( 0 );
} }
#endif /* MBEDTLS_PLATFORM_MEMORY */ #endif /* MBEDTLS_PLATFORM_MEMORY &&
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
#if defined(_WIN32) #if defined(_WIN32)
#include <stdarg.h> #include <stdarg.h>
...@@ -91,7 +100,7 @@ int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) ...@@ -91,7 +100,7 @@ int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
return( -1 ); return( -1 );
va_start( argp, fmt ); va_start( argp, fmt );
#if defined(_TRUNCATE) #if defined(_TRUNCATE) && !defined(__MINGW32__)
ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp );
#else #else
ret = _vsnprintf( s, n, fmt, argp ); ret = _vsnprintf( s, n, fmt, argp );
......
...@@ -112,6 +112,13 @@ int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) ...@@ -112,6 +112,13 @@ int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx )
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx )
{
mbedtls_ripemd160_starts_ret( ctx );
}
#endif
#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT)
/* /*
* Process one block * Process one block
...@@ -295,6 +302,14 @@ int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, ...@@ -295,6 +302,14 @@ int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_ripemd160_process( ctx, data );
}
#endif
#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */
/* /*
...@@ -349,6 +364,15 @@ int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, ...@@ -349,6 +364,15 @@ int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_ripemd160_update_ret( ctx, input, ilen );
}
#endif
static const unsigned char ripemd160_padding[64] = static const unsigned char ripemd160_padding[64] =
{ {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
...@@ -395,6 +419,14 @@ int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, ...@@ -395,6 +419,14 @@ int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx,
unsigned char output[20] )
{
mbedtls_ripemd160_finish_ret( ctx, output );
}
#endif
#endif /* ! MBEDTLS_RIPEMD160_ALT */ #endif /* ! MBEDTLS_RIPEMD160_ALT */
/* /*
...@@ -424,6 +456,15 @@ exit: ...@@ -424,6 +456,15 @@ exit:
return( ret ); return( ret );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_ripemd160( const unsigned char *input,
size_t ilen,
unsigned char output[20] )
{
mbedtls_ripemd160_ret( input, ilen, output );
}
#endif
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
/* /*
* Test vectors from the RIPEMD-160 paper and * Test vectors from the RIPEMD-160 paper and
......
...@@ -75,6 +75,7 @@ static void mbedtls_zeroize( void *v, size_t n ) { ...@@ -75,6 +75,7 @@ static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
} }
#if defined(MBEDTLS_PKCS1_V15)
/* constant-time buffer comparison */ /* constant-time buffer comparison */
static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
{ {
...@@ -88,6 +89,7 @@ static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) ...@@ -88,6 +89,7 @@ static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
return( diff ); return( diff );
} }
#endif /* MBEDTLS_PKCS1_V15 */
int mbedtls_rsa_import( mbedtls_rsa_context *ctx, int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
const mbedtls_mpi *N, const mbedtls_mpi *N,
...@@ -773,16 +775,38 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -773,16 +775,38 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
{ {
int ret; int ret;
size_t olen; size_t olen;
mbedtls_mpi T, T1, T2;
/* Temporary holding the result */
mbedtls_mpi T;
/* Temporaries holding P-1, Q-1 and the
* exponent blinding factor, respectively. */
mbedtls_mpi P1, Q1, R; mbedtls_mpi P1, Q1, R;
#if defined(MBEDTLS_RSA_NO_CRT)
mbedtls_mpi D_blind; #if !defined(MBEDTLS_RSA_NO_CRT)
mbedtls_mpi *D = &ctx->D; /* Temporaries holding the results mod p resp. mod q. */
#else mbedtls_mpi TP, TQ;
/* Temporaries holding the blinded exponents for
* the mod p resp. mod q computation (if used). */
mbedtls_mpi DP_blind, DQ_blind; mbedtls_mpi DP_blind, DQ_blind;
/* Pointers to actual exponents to be used - either the unblinded
* or the blinded ones, depending on the presence of a PRNG. */
mbedtls_mpi *DP = &ctx->DP; mbedtls_mpi *DP = &ctx->DP;
mbedtls_mpi *DQ = &ctx->DQ; mbedtls_mpi *DQ = &ctx->DQ;
#endif #else
/* Temporary holding the blinded exponent (if used). */
mbedtls_mpi D_blind;
/* Pointer to actual exponent to be used - either the unblinded
* or the blinded one, depending on the presence of a PRNG. */
mbedtls_mpi *D = &ctx->D;
#endif /* MBEDTLS_RSA_NO_CRT */
/* Temporaries holding the initial input and the double
* checked result; should be the same in the end. */
mbedtls_mpi I, C;
if( rsa_check_context( ctx, 1 /* private key checks */, if( rsa_check_context( ctx, 1 /* private key checks */,
f_rng != NULL /* blinding y/n */ ) != 0 ) f_rng != NULL /* blinding y/n */ ) != 0 )
...@@ -790,8 +814,17 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -790,8 +814,17 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
} }
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); #if defined(MBEDTLS_THREADING_C)
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return( ret );
#endif
/* MPI Initialization */
mbedtls_mpi_init( &T );
mbedtls_mpi_init( &P1 );
mbedtls_mpi_init( &Q1 );
mbedtls_mpi_init( &R );
if( f_rng != NULL ) if( f_rng != NULL )
{ {
...@@ -803,12 +836,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -803,12 +836,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
#endif #endif
} }
#if !defined(MBEDTLS_RSA_NO_CRT)
#if defined(MBEDTLS_THREADING_C) mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ );
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return( ret );
#endif #endif
mbedtls_mpi_init( &I );
mbedtls_mpi_init( &C );
/* End of MPI initialization */
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{ {
...@@ -816,6 +852,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -816,6 +852,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
goto cleanup; goto cleanup;
} }
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) );
if( f_rng != NULL ) if( f_rng != NULL )
{ {
/* /*
...@@ -874,24 +912,25 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -874,24 +912,25 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
/* /*
* Faster decryption using the CRT * Faster decryption using the CRT
* *
* T1 = input ^ dP mod P * TP = input ^ dP mod P
* T2 = input ^ dQ mod Q * TQ = input ^ dQ mod Q
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) );
/* /*
* T = (T1 - T2) * (Q^-1 mod P) mod P * T = (TP - TQ) * (Q^-1 mod P) mod P
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) );
/* /*
* T = T2 + T * Q * T = TQ + T * Q
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) );
#endif /* MBEDTLS_RSA_NO_CRT */ #endif /* MBEDTLS_RSA_NO_CRT */
if( f_rng != NULL ) if( f_rng != NULL )
...@@ -904,6 +943,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -904,6 +943,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
} }
/* Verify the result to prevent glitching attacks. */
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E,
&ctx->N, &ctx->RN ) );
if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 )
{
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
goto cleanup;
}
olen = ctx->len; olen = ctx->len;
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
...@@ -913,8 +961,9 @@ cleanup: ...@@ -913,8 +961,9 @@ cleanup:
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif #endif
mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &P1 );
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &Q1 );
mbedtls_mpi_free( &R );
if( f_rng != NULL ) if( f_rng != NULL )
{ {
...@@ -926,6 +975,15 @@ cleanup: ...@@ -926,6 +975,15 @@ cleanup:
#endif #endif
} }
mbedtls_mpi_free( &T );
#if !defined(MBEDTLS_RSA_NO_CRT)
mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ );
#endif
mbedtls_mpi_free( &C );
mbedtls_mpi_free( &I );
if( ret != 0 ) if( ret != 0 )
return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
...@@ -1306,6 +1364,97 @@ cleanup: ...@@ -1306,6 +1364,97 @@ cleanup:
#endif /* MBEDTLS_PKCS1_V21 */ #endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PKCS1_V15) #if defined(MBEDTLS_PKCS1_V15)
/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches.
*
* \param value The value to analyze.
* \return Zero if \p value is zero, otherwise all-bits-one.
*/
static unsigned all_or_nothing_int( unsigned value )
{
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
}
/** Check whether a size is out of bounds, without branches.
*
* This is equivalent to `size > max`, but is likely to be compiled to
* to code using bitwise operation rather than a branch.
*
* \param size Size to check.
* \param max Maximum desired value for \p size.
* \return \c 0 if `size <= max`.
* \return \c 1 if `size > max`.
*/
static unsigned size_greater_than( size_t size, size_t max )
{
/* Return the sign bit (1 for negative) of (max - size). */
return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) );
}
/** Choose between two integer values, without branches.
*
* This is equivalent to `cond ? if1 : if0`, but is likely to be compiled
* to code using bitwise operation rather than a branch.
*
* \param cond Condition to test.
* \param if1 Value to use if \p cond is nonzero.
* \param if0 Value to use if \p cond is zero.
* \return \c if1 if \p cond is nonzero, otherwise \c if0.
*/
static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 )
{
unsigned mask = all_or_nothing_int( cond );
return( ( mask & if1 ) | (~mask & if0 ) );
}
/** Shift some data towards the left inside a buffer without leaking
* the length of the data through side channels.
*
* `mem_move_to_left(start, total, offset)` is functionally equivalent to
* ```
* memmove(start, start + offset, total - offset);
* memset(start + offset, 0, total - offset);
* ```
* but it strives to use a memory access pattern (and thus total timing)
* that does not depend on \p offset. This timing independence comes at
* the expense of performance.
*
* \param start Pointer to the start of the buffer.
* \param total Total size of the buffer.
* \param offset Offset from which to copy \p total - \p offset bytes.
*/
static void mem_move_to_left( void *start,
size_t total,
size_t offset )
{
volatile unsigned char *buf = start;
size_t i, n;
if( total == 0 )
return;
for( i = 0; i < total; i++ )
{
unsigned no_op = size_greater_than( total - offset, i );
/* The first `total - offset` passes are a no-op. The last
* `offset` passes shift the data one byte to the left and
* zero out the last byte. */
for( n = 0; n < total - 1; n++ )
{
unsigned char current = buf[n];
unsigned char next = buf[n+1];
buf[n] = if_int( no_op, current, next );
}
buf[total-1] = if_int( no_op, buf[total-1], 0 );
}
}
/* /*
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
*/ */
...@@ -1315,18 +1464,34 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, ...@@ -1315,18 +1464,34 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
int mode, size_t *olen, int mode, size_t *olen,
const unsigned char *input, const unsigned char *input,
unsigned char *output, unsigned char *output,
size_t output_max_len) size_t output_max_len )
{ {
int ret; int ret;
size_t ilen, pad_count = 0, i; size_t ilen = ctx->len;
unsigned char *p, bad, pad_done = 0; size_t i;
size_t plaintext_max_size = ( output_max_len > ilen - 11 ?
ilen - 11 :
output_max_len );
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
/* The following variables take sensitive values: their value must
* not leak into the observable behavior of the function other than
* the designated outputs (output, olen, return value). Otherwise
* this would open the execution of the function to
* side-channel-based variants of the Bleichenbacher padding oracle
* attack. Potential side channels include overall timing, memory
* access patterns (especially visible to an adversary who has access
* to a shared memory cache), and branches (especially visible to
* an adversary who has access to a shared code cache or to a shared
* branch predictor). */
size_t pad_count = 0;
unsigned bad = 0;
unsigned char pad_done = 0;
size_t plaintext_size = 0;
unsigned output_too_large;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
ilen = ctx->len;
if( ilen < 16 || ilen > sizeof( buf ) ) if( ilen < 16 || ilen > sizeof( buf ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
...@@ -1337,63 +1502,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, ...@@ -1337,63 +1502,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
if( ret != 0 ) if( ret != 0 )
goto cleanup; goto cleanup;
p = buf; /* Check and get padding length in constant time and constant
bad = 0; * memory trace. The first byte must be 0. */
bad |= buf[0];
/*
* Check and get padding len in "constant-time"
*/
bad |= *p++; /* First byte must be 0 */
/* This test does not depend on secret data */
if( mode == MBEDTLS_RSA_PRIVATE ) if( mode == MBEDTLS_RSA_PRIVATE )
{ {
bad |= *p++ ^ MBEDTLS_RSA_CRYPT; /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
* where PS must be at least 8 nonzero bytes. */
bad |= buf[1] ^ MBEDTLS_RSA_CRYPT;
/* Get padding len, but always read till end of buffer /* Read the whole buffer. Set pad_done to nonzero if we find
* (minus one, for the 00 byte) */ * the 0x00 byte and remember the padding length in pad_count. */
for( i = 0; i < ilen - 3; i++ ) for( i = 2; i < ilen; i++ )
{ {
pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1;
pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
} }
p += pad_count;
bad |= *p++; /* Must be zero */
} }
else else
{ {
bad |= *p++ ^ MBEDTLS_RSA_SIGN; /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
* where PS must be at least 8 bytes with the value 0xFF. */
bad |= buf[1] ^ MBEDTLS_RSA_SIGN;
/* Get padding len, but always read till end of buffer /* Read the whole buffer. Set pad_done to nonzero if we find
* (minus one, for the 00 byte) */ * the 0x00 byte and remember the padding length in pad_count.
for( i = 0; i < ilen - 3; i++ ) * If there's a non-0xff byte in the padding, the padding is bad. */
for( i = 2; i < ilen; i++ )
{ {
pad_done |= ( p[i] != 0xFF ); pad_done |= if_int( buf[i], 0, 1 );
pad_count += ( pad_done == 0 ); pad_count += if_int( pad_done, 0, 1 );
bad |= if_int( pad_done, 0, buf[i] ^ 0xFF );
} }
p += pad_count;
bad |= *p++; /* Must be zero */
}
bad |= ( pad_count < 8 );
if( bad )
{
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
goto cleanup;
} }
if( ilen - ( p - buf ) > output_max_len ) /* If pad_done is still zero, there's no data, only unfinished padding. */
{ bad |= if_int( pad_done, 0, 1 );
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
goto cleanup; /* There must be at least 8 bytes of padding. */
} bad |= size_greater_than( 8, pad_count );
*olen = ilen - (p - buf); /* If the padding is valid, set plaintext_size to the number of
memcpy( output, p, *olen ); * remaining bytes after stripping the padding. If the padding
ret = 0; * is invalid, avoid leaking this fact through the size of the
* output: use the maximum message size that fits in the output
* buffer. Do it without branches to avoid leaking the padding
* validity through timing. RSA keys are small enough that all the
* size_t values involved fit in unsigned int. */
plaintext_size = if_int( bad,
(unsigned) plaintext_max_size,
(unsigned) ( ilen - pad_count - 3 ) );
/* Set output_too_large to 0 if the plaintext fits in the output
* buffer and to 1 otherwise. */
output_too_large = size_greater_than( plaintext_size,
plaintext_max_size );
/* Set ret without branches to avoid timing attacks. Return:
* - INVALID_PADDING if the padding is bad (bad != 0).
* - OUTPUT_TOO_LARGE if the padding is good but the decrypted
* plaintext does not fit in the output buffer.
* - 0 if the padding is correct. */
ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
0 ) );
/* If the padding is bad or the plaintext is too large, zero the
* data that we're about to copy to the output buffer.
* We need to copy the same amount of data
* from the same buffer whether the padding is good or not to
* avoid leaking the padding validity through overall timing or
* through memory or cache access patterns. */
bad = all_or_nothing_int( bad | output_too_large );
for( i = 11; i < ilen; i++ )
buf[i] &= ~bad;
/* If the plaintext is too large, truncate it to the buffer size.
* Copy anyway to avoid revealing the length through timing, because
* revealing the length is as bad as revealing the padding validity
* for a Bleichenbacher attack. */
plaintext_size = if_int( output_too_large,
(unsigned) plaintext_max_size,
(unsigned) plaintext_size );
/* Move the plaintext to the leftmost position where it can start in
* the working buffer, i.e. make it start plaintext_max_size from
* the end of the buffer. Do this with a memory access trace that
* does not depend on the plaintext size. After this move, the
* starting location of the plaintext is no longer sensitive
* information. */
mem_move_to_left( buf + ilen - plaintext_max_size,
plaintext_max_size,
plaintext_max_size - plaintext_size );
/* Finally copy the decrypted plaintext plus trailing zeros
* into the output buffer. */
memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
/* Report the amount of data we copied to the output buffer. In case
* of errors (bad padding or output too large), the value of *olen
* when this function returns is not specified. Making it equivalent
* to the good case limits the risks of leaking the padding validity. */
*olen = plaintext_size;
cleanup: cleanup:
mbedtls_zeroize( buf, sizeof( buf ) ); mbedtls_zeroize( buf, sizeof( buf ) );
...@@ -2222,7 +2433,8 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -2222,7 +2433,8 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
return( 1 ); ret = 1;
goto cleanup;
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -2237,7 +2449,8 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -2237,7 +2449,8 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
return( 1 ); ret = 1;
goto cleanup;
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -2250,7 +2463,8 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -2250,7 +2463,8 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
return( 1 ); ret = 1;
goto cleanup;
} }
if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
...@@ -2258,7 +2472,8 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -2258,7 +2472,8 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
return( 1 ); ret = 1;
goto cleanup;
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -2283,7 +2498,8 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -2283,7 +2498,8 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
return( 1 ); ret = 1;
goto cleanup;
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -2296,7 +2512,8 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -2296,7 +2512,8 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
return( 1 ); ret = 1;
goto cleanup;
} }
if( verbose != 0 ) if( verbose != 0 )
......
...@@ -111,6 +111,13 @@ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) ...@@ -111,6 +111,13 @@ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx )
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
{
mbedtls_sha1_starts_ret( ctx );
}
#endif
#if !defined(MBEDTLS_SHA1_PROCESS_ALT) #if !defined(MBEDTLS_SHA1_PROCESS_ALT)
int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx,
const unsigned char data[64] ) const unsigned char data[64] )
...@@ -270,6 +277,14 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, ...@@ -270,6 +277,14 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_sha1_process( ctx, data );
}
#endif
#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ #endif /* !MBEDTLS_SHA1_PROCESS_ALT */
/* /*
...@@ -322,13 +337,14 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, ...@@ -322,13 +337,14 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx,
return( 0 ); return( 0 );
} }
static const unsigned char sha1_padding[64] = #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
const unsigned char *input,
size_t ilen )
{ {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, mbedtls_sha1_update_ret( ctx, input, ilen );
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* /*
* SHA-1 final digest * SHA-1 final digest
...@@ -337,25 +353,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, ...@@ -337,25 +353,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
unsigned char output[20] ) unsigned char output[20] )
{ {
int ret; int ret;
uint32_t last, padn; uint32_t used;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8];
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80;
if( used <= 56 )
{
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used );
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
memset( ctx->buffer, 0, 56 );
}
/*
* Add message length
*/
high = ( ctx->total[0] >> 29 ) high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 ); | ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 ); low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 ); PUT_UINT32_BE( high, ctx->buffer, 56 );
PUT_UINT32_BE( low, msglen, 4 ); PUT_UINT32_BE( low, ctx->buffer, 60 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 )
return( ret ); return( ret );
/*
* Output final state
*/
PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE( ctx->state[2], output, 8 );
...@@ -365,6 +404,14 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, ...@@ -365,6 +404,14 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
mbedtls_sha1_finish_ret( ctx, output );
}
#endif
#endif /* !MBEDTLS_SHA1_ALT */ #endif /* !MBEDTLS_SHA1_ALT */
/* /*
...@@ -394,6 +441,15 @@ exit: ...@@ -394,6 +441,15 @@ exit:
return( ret ); return( ret );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1( const unsigned char *input,
size_t ilen,
unsigned char output[20] )
{
mbedtls_sha1_ret( input, ilen, output );
}
#endif
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
/* /*
* FIPS-180-1 test vectors * FIPS-180-1 test vectors
......
...@@ -135,6 +135,14 @@ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) ...@@ -135,6 +135,14 @@ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 )
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
int is224 )
{
mbedtls_sha256_starts_ret( ctx, is224 );
}
#endif
#if !defined(MBEDTLS_SHA256_PROCESS_ALT) #if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] = static const uint32_t K[] =
{ {
...@@ -238,6 +246,14 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, ...@@ -238,6 +246,14 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_sha256_process( ctx, data );
}
#endif
#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ #endif /* !MBEDTLS_SHA256_PROCESS_ALT */
/* /*
...@@ -290,13 +306,14 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, ...@@ -290,13 +306,14 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
return( 0 ); return( 0 );
} }
static const unsigned char sha256_padding[64] = #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen )
{ {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, mbedtls_sha256_update_ret( ctx, input, ilen );
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* /*
* SHA-256 final digest * SHA-256 final digest
...@@ -305,26 +322,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, ...@@ -305,26 +322,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] ) unsigned char output[32] )
{ {
int ret; int ret;
uint32_t last, padn; uint32_t used;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8];
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80;
if( used <= 56 )
{
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used );
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
memset( ctx->buffer, 0, 56 );
}
/*
* Add message length
*/
high = ( ctx->total[0] >> 29 ) high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 ); | ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 ); low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 ); PUT_UINT32_BE( high, ctx->buffer, 56 );
PUT_UINT32_BE( low, msglen, 4 ); PUT_UINT32_BE( low, ctx->buffer, 60 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 )
return( ret );
if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
return( ret ); return( ret );
/*
* Output final state
*/
PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE( ctx->state[2], output, 8 );
...@@ -339,6 +378,14 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, ...@@ -339,6 +378,14 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
mbedtls_sha256_finish_ret( ctx, output );
}
#endif
#endif /* !MBEDTLS_SHA256_ALT */ #endif /* !MBEDTLS_SHA256_ALT */
/* /*
...@@ -369,6 +416,16 @@ exit: ...@@ -369,6 +416,16 @@ exit:
return( ret ); return( ret );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256( const unsigned char *input,
size_t ilen,
unsigned char output[32],
int is224 )
{
mbedtls_sha256_ret( input, ilen, output, is224 );
}
#endif
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
/* /*
* FIPS-180-2 test vectors * FIPS-180-2 test vectors
......
...@@ -149,6 +149,14 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) ...@@ -149,6 +149,14 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
int is384 )
{
mbedtls_sha512_starts_ret( ctx, is384 );
}
#endif
#if !defined(MBEDTLS_SHA512_PROCESS_ALT) #if !defined(MBEDTLS_SHA512_PROCESS_ALT)
/* /*
...@@ -269,6 +277,14 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, ...@@ -269,6 +277,14 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_process( mbedtls_sha512_context *ctx,
const unsigned char data[128] )
{
mbedtls_internal_sha512_process( ctx, data );
}
#endif
#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ #endif /* !MBEDTLS_SHA512_PROCESS_ALT */
/* /*
...@@ -320,17 +336,14 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, ...@@ -320,17 +336,14 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
return( 0 ); return( 0 );
} }
static const unsigned char sha512_padding[128] = #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
const unsigned char *input,
size_t ilen )
{ {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, mbedtls_sha512_update_ret( ctx, input, ilen );
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #endif
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* /*
* SHA-512 final digest * SHA-512 final digest
...@@ -339,26 +352,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, ...@@ -339,26 +352,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned char output[64] ) unsigned char output[64] )
{ {
int ret; int ret;
size_t last, padn; unsigned used;
uint64_t high, low; uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 ) /*
| ( ctx->total[1] << 3 ); * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
low = ( ctx->total[0] << 3 ); */
used = ctx->total[0] & 0x7F;
PUT_UINT64_BE( high, msglen, 0 ); ctx->buffer[used++] = 0x80;
PUT_UINT64_BE( low, msglen, 8 );
last = (size_t)( ctx->total[0] & 0x7F ); if( used <= 112 )
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); {
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 112 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 128 - used );
if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
return( ret ); return( ret );
if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) memset( ctx->buffer, 0, 112 );
return( ret ); }
/*
* Add message length
*/
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, ctx->buffer, 112 );
PUT_UINT64_BE( low, ctx->buffer, 120 );
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
/*
* Output final state
*/
PUT_UINT64_BE( ctx->state[0], output, 0 ); PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 ); PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 ); PUT_UINT64_BE( ctx->state[2], output, 16 );
...@@ -375,6 +410,14 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, ...@@ -375,6 +410,14 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
mbedtls_sha512_finish_ret( ctx, output );
}
#endif
#endif /* !MBEDTLS_SHA512_ALT */ #endif /* !MBEDTLS_SHA512_ALT */
/* /*
...@@ -405,6 +448,16 @@ exit: ...@@ -405,6 +448,16 @@ exit:
return( ret ); return( ret );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512( const unsigned char *input,
size_t ilen,
unsigned char output[64],
int is384 )
{
mbedtls_sha512_ret( input, ilen, output, is384 );
}
#endif
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
/* /*
......
...@@ -1837,7 +1837,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers ...@@ -1837,7 +1837,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers
#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_PK_C */
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
{ {
switch( info->key_exchange ) switch( info->key_exchange )
...@@ -1847,13 +1848,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) ...@@ -1847,13 +1848,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
return( 1 ); return( 1 );
default: default:
return( 0 ); return( 0 );
} }
} }
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info )
......
...@@ -355,7 +355,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, ...@@ -355,7 +355,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
*olen = 6; *olen = 6;
} }
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
...@@ -717,6 +717,49 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) ...@@ -717,6 +717,49 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl )
return( 0 ); return( 0 );
} }
/**
* \brief Validate cipher suite against config in SSL context.
*
* \param suite_info cipher suite to validate
* \param ssl SSL context
* \param min_minor_ver Minimal minor version to accept a cipher suite
* \param max_minor_ver Maximal minor version to accept a cipher suite
*
* \return 0 if valid, else 1
*/
static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info,
const mbedtls_ssl_context * ssl,
int min_minor_ver, int max_minor_ver )
{
(void) ssl;
if( suite_info == NULL )
return( 1 );
if( suite_info->min_minor_ver > max_minor_ver ||
suite_info->max_minor_ver < min_minor_ver )
return( 1 );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
return( 1 );
#endif
#if defined(MBEDTLS_ARC4_C)
if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
return( 1 );
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
return( 1 );
#endif
return( 0 );
}
static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
{ {
int ret; int ret;
...@@ -726,6 +769,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ...@@ -726,6 +769,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
unsigned char offer_compress; unsigned char offer_compress;
const int *ciphersuites; const int *ciphersuites;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
int uses_ec = 0;
#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
...@@ -869,39 +916,26 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ...@@ -869,39 +916,26 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
{ {
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] );
if( ciphersuite_info == NULL ) if( ssl_validate_ciphersuite( ciphersuite_info, ssl,
continue; ssl->conf->min_minor_ver,
ssl->conf->max_minor_ver ) != 0 )
if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver ||
ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver )
continue; continue;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
continue;
#endif
#if defined(MBEDTLS_ARC4_C)
if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
continue;
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
continue;
#endif
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
ciphersuites[i] ) ); ciphersuites[i] ) );
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info );
#endif
n++; n++;
*p++ = (unsigned char)( ciphersuites[i] >> 8 ); *p++ = (unsigned char)( ciphersuites[i] >> 8 );
*p++ = (unsigned char)( ciphersuites[i] ); *p++ = (unsigned char)( ciphersuites[i] );
} }
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) );
/* /*
* Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
*/ */
...@@ -909,6 +943,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ...@@ -909,6 +943,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
#endif #endif
{ {
MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
*p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
*p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO );
n++; n++;
...@@ -928,8 +963,6 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ...@@ -928,8 +963,6 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
*q++ = (unsigned char)( n >> 7 ); *q++ = (unsigned char)( n >> 7 );
*q++ = (unsigned char)( n << 1 ); *q++ = (unsigned char)( n << 1 );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
#if defined(MBEDTLS_ZLIB_SUPPORT) #if defined(MBEDTLS_ZLIB_SUPPORT)
offer_compress = 1; offer_compress = 1;
#else #else
...@@ -937,7 +970,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ...@@ -937,7 +970,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
#endif #endif
/* /*
* We don't support compression with DTLS right now: is many records come * We don't support compression with DTLS right now: if many records come
* in the same datagram, uncompressing one could overwrite the next one. * in the same datagram, uncompressing one could overwrite the next one.
* We don't want to add complexity for handling that case unless there is * We don't want to add complexity for handling that case unless there is
* an actual need for it. * an actual need for it.
...@@ -989,11 +1022,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ...@@ -989,11 +1022,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); if( uses_ec )
ext_len += olen; {
ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen; ext_len += olen;
}
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
...@@ -1226,14 +1262,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, ...@@ -1226,14 +1262,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
size_t list_size; size_t list_size;
const unsigned char *p; const unsigned char *p;
list_size = buf[0]; if( len == 0 || (size_t)( buf[0] + 1 ) != len )
if( list_size + 1 != len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
list_size = buf[0];
p = buf + 1; p = buf + 1;
while( list_size > 0 ) while( list_size > 0 )
...@@ -1260,7 +1296,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, ...@@ -1260,7 +1296,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
...@@ -1689,22 +1725,9 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1689,22 +1725,9 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) );
suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); /*
if( suite_info == NULL * Perform cipher suite validation in same way as in ssl_write_client_hello.
#if defined(MBEDTLS_ARC4_C) */
|| ( ssl->conf->arc4_disabled &&
suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
#endif
)
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
i = 0; i = 0;
while( 1 ) while( 1 )
{ {
...@@ -1723,6 +1746,17 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1723,6 +1746,17 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
} }
} }
suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
if( comp != MBEDTLS_SSL_COMPRESS_NULL if( comp != MBEDTLS_SSL_COMPRESS_NULL
#if defined(MBEDTLS_ZLIB_SUPPORT) #if defined(MBEDTLS_ZLIB_SUPPORT)
&& comp != MBEDTLS_SSL_COMPRESS_DEFLATE && comp != MBEDTLS_SSL_COMPRESS_DEFLATE
...@@ -2057,10 +2091,16 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, ...@@ -2057,10 +2091,16 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
* *
* opaque psk_identity_hint<0..2^16-1>; * opaque psk_identity_hint<0..2^16-1>;
*/ */
if( end - (*p) < 2 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
len = (*p)[0] << 8 | (*p)[1]; len = (*p)[0] << 8 | (*p)[1];
*p += 2; *p += 2;
if( (*p) + len > end ) if( end - (*p) < (int) len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) ); "(psk_identity_hint length)" ) );
...@@ -2478,10 +2518,17 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2478,10 +2518,17 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
/* /*
* Read signature * Read signature
*/ */
if( p > end - 2 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
sig_len = ( p[0] << 8 ) | p[1]; sig_len = ( p[0] << 8 ) | p[1];
p += 2; p += 2;
if( end != p + sig_len ) if( p != end - sig_len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
...@@ -2658,10 +2705,27 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2658,10 +2705,27 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
buf = ssl->in_msg; buf = ssl->in_msg;
/* certificate_types */ /* certificate_types */
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
}
cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )];
n = cert_type_len; n = cert_type_len;
if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) /*
* In the subsequent code there are two paths that read from buf:
* * the length of the signature algorithms field (if minor version of
* SSL is 3),
* * distinguished name length otherwise.
* Both reach at most the index:
* ...hdr_len + 2 + n,
* therefore the buffer length at this point must be greater than that
* regardless of the actual code path.
*/
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
...@@ -2676,9 +2740,32 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2676,9 +2740,32 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 )
| ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) );
#if defined(MBEDTLS_DEBUG_C) #if defined(MBEDTLS_DEBUG_C)
unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; unsigned char* sig_alg;
size_t i; size_t i;
#endif
/*
* The furthest access in buf is in the loop few lines below:
* sig_alg[i + 1],
* where:
* sig_alg = buf + ...hdr_len + 3 + n,
* max(i) = sig_alg_len - 1.
* Therefore the furthest access is:
* buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1],
* which reduces to:
* buf[...hdr_len + 3 + n + sig_alg_len],
* which is one less than we need the buf to be.
*/
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
}
#if defined(MBEDTLS_DEBUG_C)
sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
for( i = 0; i < sig_alg_len; i += 2 ) for( i = 0; i < sig_alg_len; i += 2 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d"
...@@ -2687,14 +2774,6 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2687,14 +2774,6 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
#endif #endif
n += 2 + sig_alg_len; n += 2 + sig_alg_len;
if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
}
} }
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
...@@ -3248,8 +3327,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ...@@ -3248,8 +3327,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) |
( msg[2] << 8 ) | ( msg[3] ); ( msg[2] << 8 ) | ( msg[3] );
ticket_len = ( msg[4] << 8 ) | ( msg[5] ); ticket_len = ( msg[4] << 8 ) | ( msg[5] );
......
...@@ -97,6 +97,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, ...@@ -97,6 +97,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
if( len < 2 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( servername_list_size + 2 != len ) if( servername_list_size + 2 != len )
{ {
...@@ -107,7 +114,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, ...@@ -107,7 +114,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
} }
p = buf + 2; p = buf + 2;
while( servername_list_size > 0 ) while( servername_list_size > 2 )
{ {
hostname_len = ( ( p[1] << 8 ) | p[2] ); hostname_len = ( ( p[1] << 8 ) | p[2] );
if( hostname_len + 3 > servername_list_size ) if( hostname_len + 3 > servername_list_size )
...@@ -211,6 +218,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, ...@@ -211,6 +218,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
mbedtls_md_type_t md_cur; mbedtls_md_type_t md_cur;
mbedtls_pk_type_t sig_cur; mbedtls_pk_type_t sig_cur;
if ( len < 2 ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( sig_alg_list_size + 2 != len || if( sig_alg_list_size + 2 != len ||
sig_alg_list_size % 2 != 0 ) sig_alg_list_size % 2 != 0 )
...@@ -279,6 +292,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, ...@@ -279,6 +292,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
const unsigned char *p; const unsigned char *p;
const mbedtls_ecp_curve_info *curve_info, **curves; const mbedtls_ecp_curve_info *curve_info, **curves;
if ( len < 2 ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( list_size + 2 != len || if( list_size + 2 != len ||
list_size % 2 != 0 ) list_size % 2 != 0 )
...@@ -338,14 +357,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, ...@@ -338,14 +357,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
size_t list_size; size_t list_size;
const unsigned char *p; const unsigned char *p;
list_size = buf[0]; if( len == 0 || (size_t)( buf[0] + 1 ) != len )
if( list_size + 1 != len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
list_size = buf[0];
p = buf + 1; p = buf + 1;
while( list_size > 0 ) while( list_size > 0 )
...@@ -793,7 +812,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, ...@@ -793,7 +812,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
const mbedtls_ssl_ciphersuite_t *suite_info; const mbedtls_ssl_ciphersuite_t *suite_info;
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
mbedtls_pk_type_t sig_type; mbedtls_pk_type_t sig_type;
#endif #endif
...@@ -1662,10 +1681,16 @@ read_record_header: ...@@ -1662,10 +1681,16 @@ read_record_header:
while( ext_len != 0 ) while( ext_len != 0 )
{ {
unsigned int ext_id = ( ( ext[0] << 8 ) unsigned int ext_id;
| ( ext[1] ) ); unsigned int ext_size;
unsigned int ext_size = ( ( ext[2] << 8 ) if ( ext_len < 4 ) {
| ( ext[3] ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) );
ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) );
if( ext_size + 4 > ext_len ) if( ext_size + 4 > ext_len )
{ {
...@@ -2570,8 +2595,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ...@@ -2570,8 +2595,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); if ( mbedtls_ssl_ciphersuite_uses_ec(
ext_len += olen; mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
{
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
}
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
...@@ -2843,7 +2872,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2843,7 +2872,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
unsigned char *p = ssl->out_msg + 4; unsigned char *p = ssl->out_msg + 4;
size_t len; size_t len = 0;
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
unsigned char *dig_signed = p; unsigned char *dig_signed = p;
size_t dig_signed_len = 0; size_t dig_signed_len = 0;
...@@ -2961,7 +2990,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2961,7 +2990,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p; dig_signed = p;
dig_signed_len = len; dig_signed_len = len;
#endif #endif
...@@ -3050,7 +3079,7 @@ curve_matching_done: ...@@ -3050,7 +3079,7 @@ curve_matching_done:
/* /*
* 3.1: Choose hash algorithm: * 3.1: Choose hash algorithm:
* A: For TLS 1.2, obey signature-hash-algorithm extension * A: For TLS 1.2, obey signature-hash-algorithm extension
* to choose appropriate hash. * to choose appropriate hash.
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
* (RFC 4492, Sec. 5.4) * (RFC 4492, Sec. 5.4)
...@@ -3071,7 +3100,7 @@ curve_matching_done: ...@@ -3071,7 +3100,7 @@ curve_matching_done:
sig_alg ) ) == MBEDTLS_MD_NONE ) sig_alg ) ) == MBEDTLS_MD_NONE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
/* (... because we choose a cipher suite /* (... because we choose a cipher suite
* only if there is a matching hash.) */ * only if there is a matching hash.) */
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
...@@ -3305,6 +3334,10 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, ...@@ -3305,6 +3334,10 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
defined(MBEDTLS_SSL_PROTO_TLS1_2) defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
{ {
if ( p + 2 > end ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
if( *p++ != ( ( len >> 8 ) & 0xFF ) || if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
*p++ != ( ( len ) & 0xFF ) ) *p++ != ( ( len ) & 0xFF ) )
{ {
......
...@@ -101,7 +101,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) ...@@ -101,7 +101,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
uint32_t current_time = (uint32_t) mbedtls_time( NULL ); uint32_t current_time = (uint32_t) mbedtls_time( NULL );
uint32_t key_time = ctx->keys[ctx->active].generation_time; uint32_t key_time = ctx->keys[ctx->active].generation_time;
if( current_time > key_time && if( current_time >= key_time &&
current_time - key_time < ctx->ticket_lifetime ) current_time - key_time < ctx->ticket_lifetime )
{ {
return( 0 ); return( 0 );
...@@ -192,9 +192,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session, ...@@ -192,9 +192,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session,
if( left < 3 + cert_len ) if( left < 3 + cert_len )
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
*p++ = (unsigned char)( cert_len >> 16 & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
*p++ = (unsigned char)( cert_len >> 8 & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
*p++ = (unsigned char)( cert_len & 0xFF ); *p++ = (unsigned char)( ( cert_len ) & 0xFF );
if( session->peer_cert != NULL ) if( session->peer_cert != NULL )
memcpy( p, session->peer_cert->raw.p, cert_len ); memcpy( p, session->peer_cert->raw.p, cert_len );
...@@ -219,14 +219,14 @@ static int ssl_load_session( mbedtls_ssl_session *session, ...@@ -219,14 +219,14 @@ static int ssl_load_session( mbedtls_ssl_session *session,
size_t cert_len; size_t cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
if( p + sizeof( mbedtls_ssl_session ) > end ) if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
memcpy( session, p, sizeof( mbedtls_ssl_session ) ); memcpy( session, p, sizeof( mbedtls_ssl_session ) );
p += sizeof( mbedtls_ssl_session ); p += sizeof( mbedtls_ssl_session );
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
if( p + 3 > end ) if( 3 > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
...@@ -240,7 +240,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, ...@@ -240,7 +240,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
{ {
int ret; int ret;
if( p + cert_len > end ) if( cert_len > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
...@@ -251,7 +251,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, ...@@ -251,7 +251,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
mbedtls_x509_crt_init( session->peer_cert ); mbedtls_x509_crt_init( session->peer_cert );
if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert,
p, cert_len ) ) != 0 ) p, cert_len ) ) != 0 )
{ {
mbedtls_x509_crt_free( session->peer_cert ); mbedtls_x509_crt_free( session->peer_cert );
mbedtls_free( session->peer_cert ); mbedtls_free( session->peer_cert );
......
This diff is collapsed.
...@@ -111,8 +111,12 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ...@@ -111,8 +111,12 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t *
mbedtls_mutex_lock = mutex_lock; mbedtls_mutex_lock = mutex_lock;
mbedtls_mutex_unlock = mutex_unlock; mbedtls_mutex_unlock = mutex_unlock;
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
#endif
} }
/* /*
...@@ -120,8 +124,12 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ...@@ -120,8 +124,12 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t *
*/ */
void mbedtls_threading_free_alt( void ) void mbedtls_threading_free_alt( void )
{ {
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
#endif
} }
#endif /* MBEDTLS_THREADING_ALT */ #endif /* MBEDTLS_THREADING_ALT */
...@@ -131,7 +139,11 @@ void mbedtls_threading_free_alt( void ) ...@@ -131,7 +139,11 @@ void mbedtls_threading_free_alt( void )
#ifndef MUTEX_INIT #ifndef MUTEX_INIT
#define MUTEX_INIT #define MUTEX_INIT
#endif #endif
#if defined(MBEDTLS_FS_IO)
mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
#endif
#endif /* MBEDTLS_THREADING_C */ #endif /* MBEDTLS_THREADING_C */
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <windows.h> #include <windows.h>
#include <winbase.h> #include <winbase.h>
#include <process.h>
struct _hr_time struct _hr_time
{ {
...@@ -266,18 +267,17 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int ...@@ -266,18 +267,17 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int
/* It's OK to use a global because alarm() is supposed to be global anyway */ /* It's OK to use a global because alarm() is supposed to be global anyway */
static DWORD alarmMs; static DWORD alarmMs;
static DWORD WINAPI TimerProc( LPVOID TimerContext ) static void TimerProc( void *TimerContext )
{ {
((void) TimerContext); (void) TimerContext;
Sleep( alarmMs ); Sleep( alarmMs );
mbedtls_timing_alarmed = 1; mbedtls_timing_alarmed = 1;
return( TRUE ); /* _endthread will be called implicitly on return
* That ensures execution of thread funcition's epilogue */
} }
void mbedtls_set_alarm( int seconds ) void mbedtls_set_alarm( int seconds )
{ {
DWORD ThreadId;
if( seconds == 0 ) if( seconds == 0 )
{ {
/* No need to create a thread for this simple case. /* No need to create a thread for this simple case.
...@@ -288,7 +288,7 @@ void mbedtls_set_alarm( int seconds ) ...@@ -288,7 +288,7 @@ void mbedtls_set_alarm( int seconds )
mbedtls_timing_alarmed = 0; mbedtls_timing_alarmed = 0;
alarmMs = seconds * 1000; alarmMs = seconds * 1000;
CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); (void) _beginthread( TimerProc, 0, NULL );
} }
#else /* _WIN32 && !EFIX64 && !EFI32 */ #else /* _WIN32 && !EFIX64 && !EFI32 */
......
...@@ -468,6 +468,9 @@ static const char *features[] = { ...@@ -468,6 +468,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
"MBEDTLS_SSL_TRUNCATED_HMAC", "MBEDTLS_SSL_TRUNCATED_HMAC",
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT)
"MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT",
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */
#if defined(MBEDTLS_THREADING_ALT) #if defined(MBEDTLS_THREADING_ALT)
"MBEDTLS_THREADING_ALT", "MBEDTLS_THREADING_ALT",
#endif /* MBEDTLS_THREADING_ALT */ #endif /* MBEDTLS_THREADING_ALT */
......
...@@ -70,15 +70,6 @@ ...@@ -70,15 +70,6 @@
#include <time.h> #include <time.h>
#endif #endif
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#if !defined(_WIN32)
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#endif
#endif
#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
......
...@@ -95,17 +95,23 @@ static int x509_crl_get_version( unsigned char **p, ...@@ -95,17 +95,23 @@ static int x509_crl_get_version( unsigned char **p,
} }
/* /*
* X.509 CRL v2 extensions (no extensions parsed yet.) * X.509 CRL v2 extensions
*
* We currently don't parse any extension's content, but we do check that the
* list of extensions is well-formed and abort on critical extensions (that
* are unsupported as we don't support any extension so far)
*/ */
static int x509_get_crl_ext( unsigned char **p, static int x509_get_crl_ext( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_x509_buf *ext ) mbedtls_x509_buf *ext )
{ {
int ret; int ret;
size_t len = 0;
/* Get explicit tag */ /*
if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) * crlExtensions [0] EXPLICIT Extensions OPTIONAL
* -- if present, version MUST be v2
*/
if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 )
{ {
if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
return( 0 ); return( 0 );
...@@ -115,11 +121,54 @@ static int x509_get_crl_ext( unsigned char **p, ...@@ -115,11 +121,54 @@ static int x509_get_crl_ext( unsigned char **p,
while( *p < end ) while( *p < end )
{ {
/*
* Extension ::= SEQUENCE {
* extnID OBJECT IDENTIFIER,
* critical BOOLEAN DEFAULT FALSE,
* extnValue OCTET STRING }
*/
int is_critical = 0;
const unsigned char *end_ext_data;
size_t len;
/* Get enclosing sequence tag */
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
end_ext_data = *p + len;
/* Get OID (currently ignored) */
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
MBEDTLS_ASN1_OID ) ) != 0 )
{
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
}
*p += len;
/* Get optional critical */
if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data,
&is_critical ) ) != 0 &&
( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
{
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
}
/* Data should be octet string type */
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
/* Ignore data so far and just check its length */
*p += len; *p += len;
if( *p != end_ext_data )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
/* Abort on (unsupported) critical extensions */
if( is_critical )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
} }
if( *p != end ) if( *p != end )
...@@ -257,7 +306,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, ...@@ -257,7 +306,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
{ {
int ret; int ret;
size_t len; size_t len;
unsigned char *p, *end; unsigned char *p = NULL, *end = NULL;
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
mbedtls_x509_crl *crl = chain; mbedtls_x509_crl *crl = chain;
...@@ -294,7 +343,11 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, ...@@ -294,7 +343,11 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
/* /*
* Copy raw DER-encoded CRL * Copy raw DER-encoded CRL
*/ */
if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) if( buflen == 0 )
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
p = mbedtls_calloc( 1, buflen );
if( p == NULL )
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); return( MBEDTLS_ERR_X509_ALLOC_FAILED );
memcpy( p, buf, buflen ); memcpy( p, buf, buflen );
......
This diff is collapsed.
...@@ -278,34 +278,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz ...@@ -278,34 +278,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init( &pem );
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
if( buf[buflen - 1] != '\0' ) if( buf[buflen - 1] == '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; {
else mbedtls_pem_init( &pem );
ret = mbedtls_pem_read_buffer( &pem, ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN CERTIFICATE REQUEST-----", "-----BEGIN CERTIFICATE REQUEST-----",
"-----END CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----",
buf, NULL, 0, &use_len ); buf, NULL, 0, &use_len );
if( ret == 0 ) if( ret == 0 )
{ /*
/* * Was PEM encoded, parse the result
* Was PEM encoded, parse the result */
*/ ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
return( ret );
mbedtls_pem_free( &pem ); mbedtls_pem_free( &pem );
return( 0 ); if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
} return( ret );
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
mbedtls_pem_free( &pem );
return( ret );
} }
else
#endif /* MBEDTLS_PEM_PARSE_C */ #endif /* MBEDTLS_PEM_PARSE_C */
return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment