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

Update mbedTLS (#2214)

* mbedTLS update
* mbedtls: vsnprintf macroification
* Further update mbedTLS to 2.6.1
* mbedtls: make debugging work again
* Silence SSL messages on normal teardown
* Drop DTLS support from mbedtls
parent fc2f3250
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0; volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
} }
/* /*
...@@ -307,7 +307,7 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, ...@@ -307,7 +307,7 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input,
memcpy( (void *) (ctx->buffer + left), input, ilen ); memcpy( (void *) (ctx->buffer + left), input, ilen );
} }
static const unsigned char sha1_padding[64] ICACHE_RODATA_ATTR = static const unsigned char sha1_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,
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,
...@@ -323,9 +323,6 @@ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) ...@@ -323,9 +323,6 @@ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] )
uint32_t last, padn; uint32_t last, padn;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8]; unsigned char msglen[8];
unsigned char sha1_padding_local[64];
memcpy(sha1_padding_local, sha1_padding, 64);
high = ( ctx->total[0] >> 29 ) high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 ); | ( ctx->total[1] << 3 );
...@@ -337,7 +334,7 @@ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) ...@@ -337,7 +334,7 @@ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] )
last = ctx->total[0] & 0x3F; last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha1_update( ctx, sha1_padding_local, padn ); mbedtls_sha1_update( ctx, sha1_padding, padn );
mbedtls_sha1_update( ctx, msglen, 8 ); mbedtls_sha1_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[0], output, 0 );
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
#include "c_types.h"
#include <string.h> #include <string.h>
...@@ -42,7 +41,10 @@ ...@@ -42,7 +41,10 @@
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf #define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
...@@ -132,7 +134,7 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) ...@@ -132,7 +134,7 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
} }
#if !defined(MBEDTLS_SHA256_PROCESS_ALT) #if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] ICACHE_RODATA_ATTR STORE_ATTR = static const uint32_t K[] =
{ {
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
...@@ -274,7 +276,7 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in ...@@ -274,7 +276,7 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in
memcpy( (void *) (ctx->buffer + left), input, ilen ); memcpy( (void *) (ctx->buffer + left), input, ilen );
} }
static const unsigned char sha256_padding[64] ICACHE_RODATA_ATTR = static const unsigned char sha256_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,
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,
...@@ -290,9 +292,6 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32 ...@@ -290,9 +292,6 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32
uint32_t last, padn; uint32_t last, padn;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8]; unsigned char msglen[8];
unsigned char sha256_padding_local[64];
memcpy(sha256_padding_local, sha256_padding, 64);
high = ( ctx->total[0] >> 29 ) high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 ); | ( ctx->total[1] << 3 );
...@@ -304,7 +303,7 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32 ...@@ -304,7 +303,7 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32
last = ctx->total[0] & 0x3F; last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha256_update( ctx, sha256_padding_local, padn ); mbedtls_sha256_update( ctx, sha256_padding, padn );
mbedtls_sha256_update( ctx, msglen, 8 ); mbedtls_sha256_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[0], output, 0 );
...@@ -393,10 +392,19 @@ static const unsigned char sha256_test_sum[6][32] = ...@@ -393,10 +392,19 @@ static const unsigned char sha256_test_sum[6][32] =
int mbedtls_sha256_self_test( int verbose ) int mbedtls_sha256_self_test( int verbose )
{ {
int i, j, k, buflen, ret = 0; int i, j, k, buflen, ret = 0;
unsigned char buf[1024]; unsigned char *buf;
unsigned char sha256sum[32]; unsigned char sha256sum[32];
mbedtls_sha256_context ctx; mbedtls_sha256_context ctx;
buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
if( NULL == buf )
{
if( verbose != 0 )
mbedtls_printf( "Buffer allocation failed\n" );
return( 1 );
}
mbedtls_sha256_init( &ctx ); mbedtls_sha256_init( &ctx );
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
...@@ -440,6 +448,7 @@ int mbedtls_sha256_self_test( int verbose ) ...@@ -440,6 +448,7 @@ int mbedtls_sha256_self_test( int verbose )
exit: exit:
mbedtls_sha256_free( &ctx ); mbedtls_sha256_free( &ctx );
mbedtls_free( buf );
return( ret ); return( ret );
} }
......
...@@ -39,8 +39,7 @@ ...@@ -39,8 +39,7 @@
#else #else
#define UL64(x) x##ULL #define UL64(x) x##ULL
#endif #endif
#include "c_types.h"
#include "mem.h"
#include <string.h> #include <string.h>
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
...@@ -48,7 +47,10 @@ ...@@ -48,7 +47,10 @@
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf #define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
...@@ -90,53 +92,6 @@ static void mbedtls_zeroize( void *v, size_t n ) { ...@@ -90,53 +92,6 @@ static void mbedtls_zeroize( void *v, size_t n ) {
} }
#endif /* PUT_UINT64_BE */ #endif /* PUT_UINT64_BE */
/*
* Round constants
*/
static const uint64_t K[80] ICACHE_RODATA_ATTR STORE_ATTR =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{ {
memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
...@@ -193,6 +148,54 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) ...@@ -193,6 +148,54 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
} }
#if !defined(MBEDTLS_SHA512_PROCESS_ALT) #if !defined(MBEDTLS_SHA512_PROCESS_ALT)
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
{ {
int i; int i;
...@@ -303,7 +306,7 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in ...@@ -303,7 +306,7 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in
memcpy( (void *) (ctx->buffer + left), input, ilen ); memcpy( (void *) (ctx->buffer + left), input, ilen );
} }
static const unsigned char sha512_padding[128] ICACHE_RODATA_ATTR STORE_ATTR = static const unsigned char sha512_padding[128] =
{ {
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,
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,
...@@ -323,9 +326,6 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64 ...@@ -323,9 +326,6 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64
size_t last, padn; size_t last, padn;
uint64_t high, low; uint64_t high, low;
unsigned char msglen[16]; unsigned char msglen[16];
unsigned char sha512_padding_local[128];
memcpy(sha512_padding_local, sha512_padding, 128);
high = ( ctx->total[0] >> 61 ) high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 ); | ( ctx->total[1] << 3 );
...@@ -337,8 +337,7 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64 ...@@ -337,8 +337,7 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64
last = (size_t)( ctx->total[0] & 0x7F ); last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
mbedtls_sha512_update( ctx, sha512_padding, padn );
mbedtls_sha512_update( ctx, sha512_padding_local, padn );
mbedtls_sha512_update( ctx, msglen, 16 ); mbedtls_sha512_update( ctx, msglen, 16 );
PUT_UINT64_BE( ctx->state[0], output, 0 ); PUT_UINT64_BE( ctx->state[0], output, 0 );
...@@ -449,10 +448,19 @@ static const unsigned char sha512_test_sum[6][64] = ...@@ -449,10 +448,19 @@ static const unsigned char sha512_test_sum[6][64] =
int mbedtls_sha512_self_test( int verbose ) int mbedtls_sha512_self_test( int verbose )
{ {
int i, j, k, buflen, ret = 0; int i, j, k, buflen, ret = 0;
unsigned char buf[1024]; unsigned char *buf;
unsigned char sha512sum[64]; unsigned char sha512sum[64];
mbedtls_sha512_context ctx; mbedtls_sha512_context ctx;
buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
if( NULL == buf )
{
if( verbose != 0 )
mbedtls_printf( "Buffer allocation failed\n" );
return( 1 );
}
mbedtls_sha512_init( &ctx ); mbedtls_sha512_init( &ctx );
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
...@@ -496,6 +504,7 @@ int mbedtls_sha512_self_test( int verbose ) ...@@ -496,6 +504,7 @@ int mbedtls_sha512_self_test( int verbose )
exit: exit:
mbedtls_sha512_free( &ctx ); mbedtls_sha512_free( &ctx );
mbedtls_free( buf );
return( ret ); return( ret );
} }
......
...@@ -31,18 +31,18 @@ ...@@ -31,18 +31,18 @@
#if defined(MBEDTLS_SSL_CACHE_C) #if defined(MBEDTLS_SSL_CACHE_C)
#include "mbedtls/ssl_cache.h"
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
#define mbedtls_free free #define mbedtls_free free
#endif #endif
#include "mbedtls/ssl_cache.h"
#include <string.h>
void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache )
{ {
memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) );
...@@ -59,7 +59,7 @@ int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) ...@@ -59,7 +59,7 @@ int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
{ {
int ret = 1; int ret = 1;
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
time_t t = time( NULL ); mbedtls_time_t t = mbedtls_time( NULL );
#endif #endif
mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
mbedtls_ssl_cache_entry *cur, *entry; mbedtls_ssl_cache_entry *cur, *entry;
...@@ -138,7 +138,7 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) ...@@ -138,7 +138,7 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
{ {
int ret = 1; int ret = 1;
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
time_t t = time( NULL ), oldest = 0; mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0;
mbedtls_ssl_cache_entry *old = NULL; mbedtls_ssl_cache_entry *old = NULL;
#endif #endif
mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
......
...@@ -29,11 +29,15 @@ ...@@ -29,11 +29,15 @@
#if defined(MBEDTLS_SSL_TLS_C) #if defined(MBEDTLS_SSL_TLS_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#endif
#include "mbedtls/ssl_ciphersuites.h" #include "mbedtls/ssl_ciphersuites.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#include "c_types.h"
#include <string.h> #include <string.h>
/* /*
...@@ -48,7 +52,7 @@ ...@@ -48,7 +52,7 @@
* 4. By hash function used when relevant * 4. By hash function used when relevant
* 5. By key exchange/auth again: EC > non-EC * 5. By key exchange/auth again: EC > non-EC
*/ */
static const int ciphersuite_preference[] ICACHE_RODATA_ATTR STORE_ATTR = static const int ciphersuite_preference[] =
{ {
#if defined(MBEDTLS_SSL_CIPHERSUITES) #if defined(MBEDTLS_SSL_CIPHERSUITES)
MBEDTLS_SSL_CIPHERSUITES, MBEDTLS_SSL_CIPHERSUITES,
...@@ -260,7 +264,7 @@ static const int ciphersuite_preference[] ICACHE_RODATA_ATTR STORE_ATTR = ...@@ -260,7 +264,7 @@ static const int ciphersuite_preference[] ICACHE_RODATA_ATTR STORE_ATTR =
0 0
}; };
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] ICACHE_RODATA_ATTR STORE_ATTR = static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
{ {
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_AES_C)
...@@ -1813,6 +1817,24 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciph ...@@ -1813,6 +1817,24 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciph
return( MBEDTLS_PK_NONE ); return( MBEDTLS_PK_NONE );
} }
} }
mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info )
{
switch( info->key_exchange )
{
case MBEDTLS_KEY_EXCHANGE_RSA:
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
return( MBEDTLS_PK_RSA );
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
return( MBEDTLS_PK_ECDSA );
default:
return( MBEDTLS_PK_NONE );
}
}
#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)
......
...@@ -27,24 +27,24 @@ ...@@ -27,24 +27,24 @@
#if defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_CLI_C)
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
#define mbedtls_free free #define mbedtls_free free
#endif #endif
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
#include <string.h>
#include <stdint.h> #include <stdint.h>
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
#include <time.h> #include "mbedtls/platform_time.h"
#endif #endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
...@@ -264,12 +264,19 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, ...@@ -264,12 +264,19 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
{
info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
#else #else
for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
#endif
{ {
#if defined(MBEDTLS_ECP_C)
info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
#endif #endif
if( info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) );
return;
}
elliptic_curve_len += 2; elliptic_curve_len += 2;
} }
...@@ -283,13 +290,13 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, ...@@ -283,13 +290,13 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ )
{
info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
#else #else
for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
#endif
{ {
#if defined(MBEDTLS_ECP_C)
info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
#endif #endif
elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
} }
...@@ -664,7 +671,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) ...@@ -664,7 +671,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl )
int ret; int ret;
unsigned char *p = ssl->handshake->randbytes; unsigned char *p = ssl->handshake->randbytes;
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
time_t t; mbedtls_time_t t;
#endif #endif
/* /*
...@@ -679,7 +686,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) ...@@ -679,7 +686,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl )
#endif #endif
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
t = time( NULL ); t = mbedtls_time( NULL );
*p++ = (unsigned char)( t >> 24 ); *p++ = (unsigned char)( t >> 24 );
*p++ = (unsigned char)( t >> 16 ); *p++ = (unsigned char)( t >> 16 );
*p++ = (unsigned char)( t >> 8 ); *p++ = (unsigned char)( t >> 8 );
...@@ -1050,8 +1057,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -1050,8 +1057,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf, const unsigned char *buf,
size_t len ) size_t len )
{ {
int ret;
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
{ {
...@@ -1064,10 +1069,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -1064,10 +1069,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
} }
...@@ -1077,10 +1080,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -1077,10 +1080,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
if( len != 1 || buf[0] != 0x00 ) if( len != 1 || buf[0] != 0x00 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1103,6 +1104,9 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, ...@@ -1103,6 +1104,9 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
len != 1 || len != 1 ||
buf[0] != ssl->conf->mfl_code ) buf[0] != ssl->conf->mfl_code )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1118,6 +1122,9 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, ...@@ -1118,6 +1122,9 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ||
len != 0 ) len != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1138,6 +1145,9 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, ...@@ -1138,6 +1145,9 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
len != 0 ) len != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1158,6 +1168,9 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, ...@@ -1158,6 +1168,9 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
len != 0 ) len != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1177,6 +1190,9 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, ...@@ -1177,6 +1190,9 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
len != 0 ) len != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1201,6 +1217,8 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, ...@@ -1201,6 +1217,8 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
if( list_size + 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1212,7 +1230,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, ...@@ -1212,7 +1230,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
{ {
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
ssl->handshake->ecdh_ctx.point_format = p[0]; ssl->handshake->ecdh_ctx.point_format = p[0];
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
ssl->handshake->ecjpake_ctx.point_format = p[0]; ssl->handshake->ecjpake_ctx.point_format = p[0];
#endif #endif
...@@ -1225,6 +1243,8 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, ...@@ -1225,6 +1243,8 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
} }
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
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 ||
...@@ -1253,6 +1273,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, ...@@ -1253,6 +1273,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
buf, len ) ) != 0 ) buf, len ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret ); return( ret );
} }
...@@ -1269,7 +1291,12 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, ...@@ -1269,7 +1291,12 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
/* If we didn't send it, the server shouldn't send it */ /* If we didn't send it, the server shouldn't send it */
if( ssl->conf->alpn_list == NULL ) if( ssl->conf->alpn_list == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
/* /*
* opaque ProtocolName<1..2^8-1>; * opaque ProtocolName<1..2^8-1>;
...@@ -1283,15 +1310,27 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, ...@@ -1283,15 +1310,27 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
/* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
if( len < 4 ) if( len < 4 )
{
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
list_len = ( buf[0] << 8 ) | buf[1]; list_len = ( buf[0] << 8 ) | buf[1];
if( list_len != len - 2 ) if( list_len != len - 2 )
{
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
name_len = buf[2]; name_len = buf[2];
if( name_len != list_len - 1 ) if( name_len != list_len - 1 )
{
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
/* Check that the server chosen protocol was in our list and save it */ /* Check that the server chosen protocol was in our list and save it */
for( p = ssl->conf->alpn_list; *p != NULL; p++ ) for( p = ssl->conf->alpn_list; *p != NULL; p++ )
...@@ -1304,6 +1343,9 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, ...@@ -1304,6 +1343,9 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
} }
} }
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
#endif /* MBEDTLS_SSL_ALPN */ #endif /* MBEDTLS_SSL_ALPN */
...@@ -1350,6 +1392,15 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) ...@@ -1350,6 +1392,15 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
cookie_len = *p++; cookie_len = *p++;
MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len );
if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1,
( "cookie length does not match incoming message size" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
mbedtls_free( ssl->handshake->verify_cookie ); mbedtls_free( ssl->handshake->verify_cookie );
ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len );
...@@ -1399,6 +1450,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1399,6 +1450,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{ {
/* No alert on a read error. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret ); return( ret );
} }
...@@ -1419,11 +1471,15 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1419,11 +1471,15 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
} }
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) );
ssl->keep_current_message = 1;
return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
} }
#endif /* MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_RENEGOTIATION */
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_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -1450,6 +1506,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1450,6 +1506,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1504,6 +1562,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1504,6 +1562,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( n > 32 ) if( n > 32 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1516,6 +1576,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1516,6 +1576,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
} }
...@@ -1526,6 +1588,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1526,6 +1588,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
else else
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1553,6 +1617,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1553,6 +1617,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
#endif/* MBEDTLS_ZLIB_SUPPORT */ #endif/* MBEDTLS_ZLIB_SUPPORT */
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
} }
...@@ -1564,6 +1630,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1564,6 +1630,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( ssl->transform_negotiate->ciphersuite_info == NULL ) if( ssl->transform_negotiate->ciphersuite_info == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
} }
...@@ -1587,7 +1655,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1587,7 +1655,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
ssl->state++; ssl->state++;
ssl->handshake->resume = 0; ssl->handshake->resume = 0;
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
ssl->session_negotiate->start = time( NULL ); ssl->session_negotiate->start = mbedtls_time( NULL );
#endif #endif
ssl->session_negotiate->ciphersuite = i; ssl->session_negotiate->ciphersuite = i;
ssl->session_negotiate->compression = comp; ssl->session_negotiate->compression = comp;
...@@ -1601,6 +1669,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1601,6 +1669,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( ret ); return( ret );
} }
} }
...@@ -1620,6 +1690,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1620,6 +1690,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
) )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1631,6 +1703,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1631,6 +1703,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1648,6 +1722,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1648,6 +1722,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
) )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
ssl->session_negotiate->compression = comp; ssl->session_negotiate->compression = comp;
...@@ -1666,6 +1742,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1666,6 +1742,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( ext_size + 4 > ext_len ) if( ext_size + 4 > ext_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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1836,9 +1914,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ...@@ -1836,9 +1914,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
if( handshake_failure == 1 ) if( handshake_failure == 1 )
{ {
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
return( ret ); MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
} }
...@@ -1977,12 +2054,16 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, ...@@ -1977,12 +2054,16 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
if( (*p) + len > end ) if( (*p) + len > end )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
// TODO: Retrieve PSK identity hint and callback to app /*
// * Note: we currently ignore the PKS identity hint, as we only allow one
* PSK to be provisionned on the client. This could be changed later if
* someone needs that feature.
*/
*p += len; *p += len;
ret = 0; ret = 0;
...@@ -2116,8 +2197,8 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, ...@@ -2116,8 +2197,8 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
*/ */
if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm " MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered",
"that was not offered" ) ); *(p)[0] ) );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
...@@ -2175,7 +2256,8 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) ...@@ -2175,7 +2256,8 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
{ {
int ret; int ret;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
unsigned char *p, *end; unsigned char *p, *end;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
...@@ -2199,6 +2281,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2199,6 +2281,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret ); return( ret );
} }
...@@ -2220,6 +2304,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2220,6 +2304,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
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_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -2232,11 +2318,17 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2232,11 +2318,17 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{ {
ssl->record_read = 1; /* Current message is probably either
* CertificateRequest or ServerHelloDone */
ssl->keep_current_message = 1;
goto exit; goto exit;
} }
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must "
"not be skipped" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -2253,6 +2345,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2253,6 +2345,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
} /* FALLTROUGH */ } /* FALLTROUGH */
...@@ -2274,6 +2368,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2274,6 +2368,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
} }
...@@ -2290,6 +2386,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2290,6 +2386,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
} }
...@@ -2305,6 +2403,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2305,6 +2403,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
} }
...@@ -2315,12 +2415,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2315,12 +2415,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
{ {
size_t sig_len, hashlen; size_t sig_len, hashlen;
unsigned char hash[64]; unsigned char hash[64];
...@@ -2339,12 +2435,16 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2339,12 +2435,16 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
&md_alg, &pk_alg ) != 0 ) &md_alg, &pk_alg ) != 0 )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
} }
...@@ -2376,6 +2476,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2376,6 +2476,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( end != p + sig_len ) if( end != p + 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
} }
...@@ -2447,6 +2549,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2447,6 +2549,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( ret ); return( ret );
} }
...@@ -2470,6 +2574,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2470,6 +2574,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ssl->session_negotiate->peer_cert == NULL ) if( ssl->session_negotiate->peer_cert == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -2479,19 +2585,21 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2479,19 +2585,21 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
{ {
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_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
} }
if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
md_alg, hash, hashlen, p, sig_len ) ) != 0 ) md_alg, hash, hashlen, p, sig_len ) ) != 0 )
{ {
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
return( ret ); return( ret );
} }
} }
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
exit: exit:
ssl->state++; ssl->state++;
...@@ -2501,21 +2609,15 @@ exit: ...@@ -2501,21 +2609,15 @@ exit:
return( 0 ); return( 0 );
} }
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ #if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED)
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{ {
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
ssl->state++; ssl->state++;
...@@ -2525,61 +2627,51 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2525,61 +2627,51 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
#else #else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{ {
int ret; int ret;
unsigned char *buf, *p; unsigned char *buf;
size_t n = 0, m = 0; size_t n = 0;
size_t cert_type_len = 0, dn_len = 0; size_t cert_type_len = 0, dn_len = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
ssl->state++; ssl->state++;
return( 0 ); return( 0 );
} }
if( ssl->record_read == 0 ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{ {
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
{ return( ret );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); }
return( ret );
}
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
}
ssl->record_read = 1; if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
ssl->client_auth = 0;
ssl->state++; ssl->state++;
ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST );
if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST )
ssl->client_auth++;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request",
ssl->client_auth ? "a" : "no" ) ); ssl->client_auth ? "a" : "no" ) );
if( ssl->client_auth == 0 ) if( ssl->client_auth == 0 )
{
/* Current message is probably the ServerHelloDone */
ssl->keep_current_message = 1;
goto exit; goto exit;
}
ssl->record_read = 0;
// TODO: handshake_failure alert for an anonymous server to request
// client authentication
/* /*
* struct { * struct {
...@@ -2588,77 +2680,76 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2588,77 +2680,76 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
* supported_signature_algorithms<2^16-1>; -- TLS 1.2 only * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only
* DistinguishedName certificate_authorities<0..2^16-1>; * DistinguishedName certificate_authorities<0..2^16-1>;
* } CertificateRequest; * } CertificateRequest;
*
* Since we only support a single certificate on clients, let's just
* ignore all the information that's supposed to help us pick a
* certificate.
*
* We could check that our certificate matches the request, and bail out
* if it doesn't, but it's simpler to just send the certificate anyway,
* and give the server the opportunity to decide if it should terminate
* the connection when it doesn't like our certificate.
*
* Same goes for the hash in TLS 1.2's signature_algorithms: at this
* point we only have one hash available (see comments in
* write_certificate_verify), so let's just use what we have.
*
* However, we still minimally parse the message to check it is at least
* superficially sane.
*/ */
buf = ssl->in_msg; buf = ssl->in_msg;
// Retrieve cert types /* certificate_types */
//
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 ) 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
} }
p = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 1; /* supported_signature_algorithms */
while( cert_type_len > 0 )
{
#if defined(MBEDTLS_RSA_C)
if( *p == MBEDTLS_SSL_CERT_TYPE_RSA_SIGN &&
mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
{
ssl->handshake->cert_type = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN;
break;
}
else
#endif
#if defined(MBEDTLS_ECDSA_C)
if( *p == MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN &&
mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) )
{
ssl->handshake->cert_type = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN;
break;
}
else
#endif
{
; /* Unsupported cert type, ignore */
}
cert_type_len--;
p++;
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{ {
/* Ignored, see comments about hash in write_certificate_verify */
// TODO: should check the signature part against our pk_key though
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)
unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
size_t i;
m += 2; for( i = 0; i < sig_alg_len; i += 2 )
n += sig_alg_len; {
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d"
",%d", sig_alg[i], sig_alg[i + 1] ) );
}
#endif
n += 2 + sig_alg_len;
if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
} }
} }
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
/* Ignore certificate_authorities, we only have one cert anyway */ /* certificate_authorities */
// TODO: should not send cert if no CA matches dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 )
dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + m + n] << 8 ) | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) );
| ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + m + n] ) );
n += dn_len; n += dn_len;
if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + m + n ) if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
} }
...@@ -2667,10 +2758,7 @@ exit: ...@@ -2667,10 +2758,7 @@ exit:
return( 0 ); return( 0 );
} }
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && #endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
{ {
...@@ -2678,26 +2766,24 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) ...@@ -2678,26 +2766,24 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
if( ssl->record_read == 0 ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{ {
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
{ return( ret );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); }
return( ret );
}
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
}
} }
ssl->record_read = 0;
if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ||
ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done 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_HELLO_DONE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
} }
...@@ -2717,7 +2803,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2717,7 +2803,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
{ {
int ret; int ret;
size_t i, n; size_t i, n;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
...@@ -2804,10 +2891,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2804,10 +2891,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) )
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{ {
/* /*
* opaque psk_identity<0..2^16-1>; * opaque psk_identity<0..2^16-1>;
...@@ -2971,11 +3055,14 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2971,11 +3055,14 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{ {
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
int ret; int ret;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
...@@ -3004,7 +3091,8 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3004,7 +3091,8 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{ {
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
size_t n = 0, offset = 0; size_t n = 0, offset = 0;
unsigned char hash[48]; unsigned char hash[48];
unsigned char *hash_start = hash; unsigned char *hash_start = hash;
...@@ -3151,7 +3239,10 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3151,7 +3239,10 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
} }
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
...@@ -3173,6 +3264,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ...@@ -3173,6 +3264,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -3190,6 +3283,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ...@@ -3190,6 +3283,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
} }
...@@ -3203,6 +3298,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ...@@ -3203,6 +3298,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
} }
...@@ -3228,6 +3325,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ...@@ -3228,6 +3325,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
} }
...@@ -3284,7 +3383,7 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) ...@@ -3284,7 +3383,7 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET;
} }
#endif #endif
switch( ssl->state ) switch( ssl->state )
{ {
case MBEDTLS_SSL_HELLO_REQUEST: case MBEDTLS_SSL_HELLO_REQUEST:
...@@ -3350,9 +3449,6 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) ...@@ -3350,9 +3449,6 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
case MBEDTLS_SSL_CLIENT_FINISHED: case MBEDTLS_SSL_CLIENT_FINISHED:
ret = mbedtls_ssl_write_finished( ssl ); ret = mbedtls_ssl_write_finished( ssl );
#if defined(ESP8266_PLATFORM)
mbedtls_write_finished(ssl);
#endif
break; break;
/* /*
......
...@@ -31,16 +31,16 @@ ...@@ -31,16 +31,16 @@
#if defined(MBEDTLS_SSL_COOKIE_C) #if defined(MBEDTLS_SSL_COOKIE_C)
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/ssl_internal.h"
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
#define mbedtls_free free #define mbedtls_free free
#endif #endif
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/ssl_internal.h"
#include <string.h> #include <string.h>
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
...@@ -98,7 +98,7 @@ void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) ...@@ -98,7 +98,7 @@ void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx )
mbedtls_md_free( &ctx->hmac_ctx ); mbedtls_md_free( &ctx->hmac_ctx );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex ); mbedtls_mutex_free( &ctx->mutex );
#endif #endif
mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) );
...@@ -172,7 +172,7 @@ int mbedtls_ssl_cookie_write( void *p_ctx, ...@@ -172,7 +172,7 @@ int mbedtls_ssl_cookie_write( void *p_ctx,
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
t = (unsigned long) time( NULL ); t = (unsigned long) mbedtls_time( NULL );
#else #else
t = ctx->serial++; t = ctx->serial++;
#endif #endif
...@@ -242,7 +242,7 @@ int mbedtls_ssl_cookie_check( void *p_ctx, ...@@ -242,7 +242,7 @@ int mbedtls_ssl_cookie_check( void *p_ctx,
return( -1 ); return( -1 );
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
cur_time = (unsigned long) time( NULL ); cur_time = (unsigned long) mbedtls_time( NULL );
#else #else
cur_time = ctx->serial; cur_time = ctx->serial;
#endif #endif
......
...@@ -27,6 +27,14 @@ ...@@ -27,6 +27,14 @@
#if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_SRV_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "mbedtls/debug.h" #include "mbedtls/debug.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h" #include "mbedtls/ssl_internal.h"
...@@ -37,16 +45,8 @@ ...@@ -37,16 +45,8 @@
#include "mbedtls/ecp.h" #include "mbedtls/ecp.h"
#endif #endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
#include <time.h> #include "mbedtls/platform_time.h"
#endif #endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
...@@ -101,6 +101,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, ...@@ -101,6 +101,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
if( servername_list_size + 2 != len ) if( servername_list_size + 2 != 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -111,6 +113,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, ...@@ -111,6 +113,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
if( hostname_len + 3 > servername_list_size ) if( hostname_len + 3 > servername_list_size )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -135,6 +139,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, ...@@ -135,6 +139,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
if( servername_list_size != 0 ) if( servername_list_size != 0 )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -146,8 +152,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -146,8 +152,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf, const unsigned char *buf,
size_t len ) size_t len )
{ {
int ret;
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
{ {
...@@ -158,10 +162,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -158,10 +162,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
ssl->verify_data_len ) != 0 ) ssl->verify_data_len ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
} }
...@@ -171,10 +173,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -171,10 +173,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
if( len != 1 || buf[0] != 0x0 ) if( len != 1 || buf[0] != 0x0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -186,46 +186,83 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ...@@ -186,46 +186,83 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
#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)
/*
* Status of the implementation of signature-algorithms extension:
*
* Currently, we are only considering the signature-algorithm extension
* to pick a ciphersuite which allows us to send the ServerKeyExchange
* message with a signature-hash combination that the user allows.
*
* We do *not* check whether all certificates in our certificate
* chain are signed with an allowed signature-hash pair.
* This needs to be done at a later stage.
*
*/
static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf, const unsigned char *buf,
size_t len ) size_t len )
{ {
size_t sig_alg_list_size; size_t sig_alg_list_size;
const unsigned char *p; const unsigned char *p;
const unsigned char *end = buf + len; const unsigned char *end = buf + len;
const int *md_cur;
mbedtls_md_type_t md_cur;
mbedtls_pk_type_t sig_cur;
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 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
/* /* Currently we only guarantee signing the ServerKeyExchange message according
* For now, ignore the SignatureAlgorithm part and rely on offered * to the constraints specified in this extension (see above), so it suffices
* ciphersuites only for that part. To be fixed later. * to remember only one suitable hash for each possible signature algorithm.
* *
* So, just look at the HashAlgorithm part. * This will change when we also consider certificate signatures,
* in which case we will need to remember the whole signature-hash
* pair list from the extension.
*/ */
for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) {
for( p = buf + 2; p < end; p += 2 ) { for( p = buf + 2; p < end; p += 2 )
if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) { {
ssl->handshake->sig_alg = p[0]; /* Silently ignore unknown signature or hash algorithms. */
goto have_sig_alg;
} if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext"
" unknown sig alg encoding %d", p[1] ) );
continue;
} }
}
/* Some key echanges do not need signatures at all */ /* Check if we support the hash the user proposes */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) ); md_cur = mbedtls_ssl_md_alg_from_hash( p[0] );
return( 0 ); if( md_cur == MBEDTLS_MD_NONE )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
" unknown hash alg encoding %d", p[0] ) );
continue;
}
have_sig_alg: if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", {
ssl->handshake->sig_alg ) ); mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
" match sig %d and hash %d",
sig_cur, md_cur ) );
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: "
"hash alg %d not supported", md_cur ) );
}
}
return( 0 ); return( 0 );
} }
...@@ -247,6 +284,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, ...@@ -247,6 +284,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
list_size % 2 != 0 ) list_size % 2 != 0 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -254,6 +293,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, ...@@ -254,6 +293,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
if( ssl->handshake->curves != NULL ) if( ssl->handshake->curves != NULL )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -264,7 +305,11 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, ...@@ -264,7 +305,11 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
our_size = MBEDTLS_ECP_DP_MAX; our_size = MBEDTLS_ECP_DP_MAX;
if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL )
{
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
ssl->handshake->curves = curves; ssl->handshake->curves = curves;
...@@ -297,6 +342,8 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, ...@@ -297,6 +342,8 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
if( list_size + 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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -342,6 +389,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, ...@@ -342,6 +389,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
buf, len ) ) != 0 ) buf, len ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( ret ); return( ret );
} }
...@@ -360,6 +409,8 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, ...@@ -360,6 +409,8 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID )
{ {
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_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -377,6 +428,8 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, ...@@ -377,6 +428,8 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
if( len != 0 ) if( len != 0 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -397,6 +450,8 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, ...@@ -397,6 +450,8 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
if( len != 0 ) if( len != 0 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -420,6 +475,8 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, ...@@ -420,6 +475,8 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
if( len != 0 ) if( len != 0 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -531,11 +588,19 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, ...@@ -531,11 +588,19 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
/* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
if( len < 4 ) if( len < 4 )
{
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 ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
list_len = ( buf[0] << 8 ) | buf[1]; list_len = ( buf[0] << 8 ) | buf[1];
if( list_len != len - 2 ) if( list_len != len - 2 )
{
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 ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
/* /*
* Use our order of preference * Use our order of preference
...@@ -549,13 +614,21 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, ...@@ -549,13 +614,21 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
{ {
/* If the list is well formed, we should get equality first */ /* If the list is well formed, we should get equality first */
if( theirs > end ) if( theirs > end )
{
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
cur_len = *theirs++; cur_len = *theirs++;
/* Empty strings MUST NOT be included */ /* Empty strings MUST NOT be included */
if( cur_len == 0 ) if( cur_len == 0 )
{
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( cur_len == ours_len && if( cur_len == ours_len &&
memcmp( theirs, *ours, cur_len ) == 0 ) memcmp( theirs, *ours, cur_len ) == 0 )
...@@ -607,7 +680,8 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, ...@@ -607,7 +680,8 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) const mbedtls_ssl_ciphersuite_t * ciphersuite_info )
{ {
mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; mbedtls_ssl_key_cert *cur, *list, *fallback = NULL;
mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); mbedtls_pk_type_t pk_alg =
mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
uint32_t flags; uint32_t flags;
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
...@@ -710,6 +784,11 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, ...@@ -710,6 +784,11 @@ 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) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
mbedtls_pk_type_t sig_type;
#endif
suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id );
if( suite_info == NULL ) if( suite_info == NULL )
{ {
...@@ -776,6 +855,25 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, ...@@ -776,6 +855,25 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
} }
#endif #endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
/* If the ciphersuite requires signing, check whether
* a suitable hash algorithm is present. */
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info );
if( sig_type != MBEDTLS_PK_NONE &&
mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm "
"for signature algorithm %d", sig_type ) );
return( 0 );
}
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
/* /*
* Final check: if ciphersuite requires us to have a * Final check: if ciphersuite requires us to have a
...@@ -813,10 +911,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) ...@@ -813,10 +911,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
#endif /* MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_RENEGOTIATION */
...@@ -962,9 +1058,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) ...@@ -962,9 +1058,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV "
"during renegotiation" ) ); "during renegotiation" ) );
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
return( ret ); MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
#endif /* MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_RENEGOTIATION */
...@@ -1002,11 +1097,9 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) ...@@ -1002,11 +1097,9 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
ciphersuite_info = NULL; ciphersuite_info = NULL;
#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
{
for( i = 0; ciphersuites[i] != 0; i++ ) for( i = 0; ciphersuites[i] != 0; i++ )
#else #else
for( i = 0; ciphersuites[i] != 0; i++ ) for( i = 0; ciphersuites[i] != 0; i++ )
{
for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
#endif #endif
{ {
...@@ -1024,7 +1117,6 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) ...@@ -1024,7 +1117,6 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
if( ciphersuite_info != NULL ) if( ciphersuite_info != NULL )
goto have_ciphersuite_v2; goto have_ciphersuite_v2;
} }
}
if( got_common_suite ) if( got_common_suite )
{ {
...@@ -1043,7 +1135,6 @@ have_ciphersuite_v2: ...@@ -1043,7 +1135,6 @@ have_ciphersuite_v2:
ssl->session_negotiate->ciphersuite = ciphersuites[i]; ssl->session_negotiate->ciphersuite = ciphersuites[i];
ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
/* /*
* SSLv2 Client Hello relevant renegotiation security checks * SSLv2 Client Hello relevant renegotiation security checks
...@@ -1052,10 +1143,8 @@ have_ciphersuite_v2: ...@@ -1052,10 +1143,8 @@ have_ciphersuite_v2:
ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( ret );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1068,6 +1157,9 @@ have_ciphersuite_v2: ...@@ -1068,6 +1157,9 @@ have_ciphersuite_v2:
} }
#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ #endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
/* This function doesn't alert on errors that happen early during
ClientHello parsing because they might indicate that the client is
not talking SSL/TLS at all and would not understand our alert. */
static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
{ {
int ret, got_common_suite; int ret, got_common_suite;
...@@ -1086,6 +1178,15 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) ...@@ -1086,6 +1178,15 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
const mbedtls_ssl_ciphersuite_t *ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
int major, minor; int major, minor;
/* If there is no signature-algorithm extension present,
* we need to fall back to the default values for allowed
* signature-hash pairs. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
int sig_hash_alg_ext_present = 0;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
...@@ -1102,6 +1203,7 @@ read_record_header: ...@@ -1102,6 +1203,7 @@ read_record_header:
{ {
if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
{ {
/* No alert on a read error. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
return( ret ); return( ret );
} }
...@@ -1114,7 +1216,7 @@ read_record_header: ...@@ -1114,7 +1216,7 @@ read_record_header:
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
#endif #endif
if( ( buf[0] & 0x80 ) != 0 ) if( ( buf[0] & 0x80 ) != 0 )
return ssl_parse_client_hello_v2( ssl ); return( ssl_parse_client_hello_v2( ssl ) );
#endif #endif
MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) );
...@@ -1205,7 +1307,8 @@ read_record_header: ...@@ -1205,7 +1307,8 @@ read_record_header:
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) if( ( ret = mbedtls_ssl_fetch_input( ssl,
mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
return( ret ); return( ret );
...@@ -1353,10 +1456,8 @@ read_record_header: ...@@ -1353,10 +1456,8 @@ read_record_header:
" [%d:%d] < [%d:%d]", " [%d:%d] < [%d:%d]",
ssl->major_ver, ssl->minor_ver, ssl->major_ver, ssl->minor_ver,
ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) );
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_PROTOCOL_VERSION ); MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
} }
...@@ -1384,6 +1485,8 @@ read_record_header: ...@@ -1384,6 +1485,8 @@ read_record_header:
sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1407,6 +1510,8 @@ read_record_header: ...@@ -1407,6 +1510,8 @@ read_record_header:
if( cookie_offset + 1 + cookie_len + 2 > msg_len ) if( cookie_offset + 1 + cookie_len + 2 > msg_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_ALERT_MSG_PROTOCOL_VERSION );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1439,6 +1544,7 @@ read_record_header: ...@@ -1439,6 +1544,7 @@ read_record_header:
/* We know we didn't send a cookie, so it should be empty */ /* We know we didn't send a cookie, so it should be empty */
if( cookie_len != 0 ) if( cookie_len != 0 )
{ {
/* This may be an attacker's probe, so don't send an alert */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1463,6 +1569,8 @@ read_record_header: ...@@ -1463,6 +1569,8 @@ read_record_header:
( ciph_len % 2 ) != 0 ) ( ciph_len % 2 ) != 0 )
{ {
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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1481,6 +1589,8 @@ read_record_header: ...@@ -1481,6 +1589,8 @@ read_record_header:
comp_len + comp_offset + 1 > msg_len ) comp_len + comp_offset + 1 > msg_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_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1505,195 +1615,209 @@ read_record_header: ...@@ -1505,195 +1615,209 @@ read_record_header:
ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL;
#endif #endif
/* /* Do not parse the extensions if the protocol is SSLv3 */
* Check the extension length #if defined(MBEDTLS_SSL_PROTO_SSL3)
*/ if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
ext_offset = comp_offset + 1 + comp_len;
if( msg_len > ext_offset )
{ {
if( msg_len < ext_offset + 2 ) #endif
/*
* Check the extension length
*/
ext_offset = comp_offset + 1 + comp_len;
if( msg_len > ext_offset )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); if( msg_len < ext_offset + 2 )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); {
} 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_len = ( buf[ext_offset + 0] << 8 ) ext_len = ( buf[ext_offset + 0] << 8 )
| ( buf[ext_offset + 1] ); | ( buf[ext_offset + 1] );
if( ( ext_len > 0 && ext_len < 4 ) || if( ( ext_len > 0 && ext_len < 4 ) ||
msg_len != ext_offset + 2 + ext_len ) msg_len != ext_offset + 2 + ext_len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); 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 );
}
} }
} else
else ext_len = 0;
ext_len = 0;
ext = buf + ext_offset + 2;
MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len );
while( ext_len != 0 ) ext = buf + ext_offset + 2;
{ MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len );
unsigned int ext_id = ( ( ext[0] << 8 )
| ( ext[1] ) );
unsigned int ext_size = ( ( ext[2] << 8 )
| ( ext[3] ) );
if( ext_size + 4 > ext_len ) while( ext_len != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
switch( ext_id )
{ {
unsigned int ext_id = ( ( ext[0] << 8 )
| ( ext[1] ) );
unsigned int ext_size = ( ( ext[2] << 8 )
| ( ext[3] ) );
if( ext_size + 4 > ext_len )
{
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 );
}
switch( ext_id )
{
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
case MBEDTLS_TLS_EXT_SERVERNAME: case MBEDTLS_TLS_EXT_SERVERNAME:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
if( ssl->conf->f_sni == NULL ) if( ssl->conf->f_sni == NULL )
break; break;
ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
renegotiation_info_seen = 1; renegotiation_info_seen = 1;
#endif #endif
ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#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)
case MBEDTLS_TLS_EXT_SIG_ALG: case MBEDTLS_TLS_EXT_SIG_ALG:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
break;
#endif
ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break;
sig_hash_alg_ext_present = 1;
break;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
#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)
case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) );
ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) );
ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#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)
case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) );
ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) );
ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
case MBEDTLS_TLS_EXT_SESSION_TICKET: case MBEDTLS_TLS_EXT_SESSION_TICKET:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) );
ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */
#if defined(MBEDTLS_SSL_ALPN) #if defined(MBEDTLS_SSL_ALPN)
case MBEDTLS_TLS_EXT_ALPN: case MBEDTLS_TLS_EXT_ALPN:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
break; break;
#endif /* MBEDTLS_SSL_SESSION_TICKETS */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */
default: default:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
ext_id ) ); ext_id ) );
} }
ext_len -= 4 + ext_size; ext_len -= 4 + ext_size;
ext += 4 + ext_size; ext += 4 + ext_size;
if( ext_len > 0 && ext_len < 4 ) if( ext_len > 0 && ext_len < 4 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); 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 );
}
} }
#if defined(MBEDTLS_SSL_PROTO_SSL3)
} }
#endif
#if defined(MBEDTLS_SSL_FALLBACK_SCSV) #if defined(MBEDTLS_SSL_FALLBACK_SCSV)
for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 )
{ {
if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) &&
p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) )
...@@ -1715,6 +1839,26 @@ read_record_header: ...@@ -1715,6 +1839,26 @@ read_record_header:
} }
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ #endif /* MBEDTLS_SSL_FALLBACK_SCSV */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
/*
* Try to fall back to default hash SHA1 if the client
* hasn't provided any preferred signature-hash combinations.
*/
if( sig_hash_alg_ext_present == 0 )
{
mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1;
if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 )
md_default = MBEDTLS_MD_NONE;
mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
/* /*
* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
*/ */
...@@ -1726,11 +1870,10 @@ read_record_header: ...@@ -1726,11 +1870,10 @@ read_record_header:
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV "
"during renegotiation" ) );
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
return( ret ); MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
#endif #endif
...@@ -1774,9 +1917,8 @@ read_record_header: ...@@ -1774,9 +1917,8 @@ read_record_header:
if( handshake_failure == 1 ) if( handshake_failure == 1 )
{ {
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
return( ret ); MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
...@@ -1790,11 +1932,9 @@ read_record_header: ...@@ -1790,11 +1932,9 @@ read_record_header:
ciphersuite_info = NULL; ciphersuite_info = NULL;
#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
{
for( i = 0; ciphersuites[i] != 0; i++ ) for( i = 0; ciphersuites[i] != 0; i++ )
#else #else
for( i = 0; ciphersuites[i] != 0; i++ ) for( i = 0; ciphersuites[i] != 0; i++ )
{
for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
#endif #endif
{ {
...@@ -1811,19 +1951,20 @@ read_record_header: ...@@ -1811,19 +1951,20 @@ read_record_header:
if( ciphersuite_info != NULL ) if( ciphersuite_info != NULL )
goto have_ciphersuite; goto have_ciphersuite;
} }
}
if( got_common_suite ) if( got_common_suite )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
"but none of them usable" ) ); "but none of them usable" ) );
mbedtls_ssl_send_fatal_handshake_failure( ssl ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE );
} }
else else
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
mbedtls_ssl_send_fatal_handshake_failure( ssl ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
} }
...@@ -1832,7 +1973,6 @@ have_ciphersuite: ...@@ -1832,7 +1973,6 @@ have_ciphersuite:
ssl->session_negotiate->ciphersuite = ciphersuites[i]; ssl->session_negotiate->ciphersuite = ciphersuites[i];
ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
ssl->state++; ssl->state++;
...@@ -1841,6 +1981,28 @@ have_ciphersuite: ...@@ -1841,6 +1981,28 @@ have_ciphersuite:
mbedtls_ssl_recv_flight_completed( ssl ); mbedtls_ssl_recv_flight_completed( ssl );
#endif #endif
/* Debugging-only output for testsuite */
#if defined(MBEDTLS_DEBUG_C) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info );
if( sig_alg != MBEDTLS_PK_NONE )
{
mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs,
sig_alg );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
mbedtls_ssl_hash_from_md_alg( md_alg ) ) );
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm "
"%d - should not happen", sig_alg ) );
}
}
#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
return( 0 ); return( 0 );
...@@ -2210,7 +2372,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) ...@@ -2210,7 +2372,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
{ {
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
time_t t; mbedtls_time_t t;
#endif #endif
int ret; int ret;
size_t olen, ext_len = 0, n; size_t olen, ext_len = 0, n;
...@@ -2253,7 +2415,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ...@@ -2253,7 +2415,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
buf[4], buf[5] ) ); buf[4], buf[5] ) );
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
t = time( NULL ); t = mbedtls_time( NULL );
*p++ = (unsigned char)( t >> 24 ); *p++ = (unsigned char)( t >> 24 );
*p++ = (unsigned char)( t >> 16 ); *p++ = (unsigned char)( t >> 16 );
*p++ = (unsigned char)( t >> 8 ); *p++ = (unsigned char)( t >> 8 );
...@@ -2302,7 +2464,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ...@@ -2302,7 +2464,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
ssl->state++; ssl->state++;
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
ssl->session_negotiate->start = time( NULL ); ssl->session_negotiate->start = mbedtls_time( NULL );
#endif #endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
...@@ -2361,6 +2523,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ...@@ -2361,6 +2523,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
ssl->session_negotiate->compression ) ); ssl->session_negotiate->compression ) );
/* Do not write the extensions if the protocol is SSLv3 */
#if defined(MBEDTLS_SSL_PROTO_SSL3)
if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
{
#endif
/* /*
* First write extensions, then the total length * First write extensions, then the total length
*/ */
...@@ -2417,6 +2585,10 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ...@@ -2417,6 +2585,10 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
p += ext_len; p += ext_len;
} }
#if defined(MBEDTLS_SSL_PROTO_SSL3)
}
#endif
ssl->out_msglen = p - buf; ssl->out_msglen = p - buf;
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO;
...@@ -2430,11 +2602,14 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ...@@ -2430,11 +2602,14 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
{ {
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
...@@ -2456,7 +2631,8 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2456,7 +2631,8 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
{ {
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
size_t dn_size, total_dn_size; /* excluding length bytes */ size_t dn_size, total_dn_size; /* excluding length bytes */
size_t ct_len, sa_len; /* including length bytes */ size_t ct_len, sa_len; /* including length bytes */
unsigned char *buf, *p; unsigned char *buf, *p;
...@@ -2536,29 +2712,27 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2536,29 +2712,27 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
*/ */
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{ {
/* const int *cur;
* Only use current running hash algorithm that is already required
* for requested ciphersuite.
*/
ssl->handshake->verify_sig_alg = MBEDTLS_SSL_HASH_SHA256;
if( ssl->transform_negotiate->ciphersuite_info->mac ==
MBEDTLS_MD_SHA384 )
{
ssl->handshake->verify_sig_alg = MBEDTLS_SSL_HASH_SHA384;
}
/* /*
* Supported signature algorithms * Supported signature algorithms
*/ */
for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
{
unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur );
if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) )
continue;
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
p[2 + sa_len++] = ssl->handshake->verify_sig_alg; p[2 + sa_len++] = hash;
p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA;
#endif #endif
#if defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDSA_C)
p[2 + sa_len++] = ssl->handshake->verify_sig_alg; p[2 + sa_len++] = hash;
p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA;
#endif #endif
}
p[0] = (unsigned char)( sa_len >> 8 ); p[0] = (unsigned char)( sa_len >> 8 );
p[1] = (unsigned char)( sa_len ); p[1] = (unsigned char)( sa_len );
...@@ -2572,35 +2746,40 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2572,35 +2746,40 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
* opaque DistinguishedName<1..2^16-1>; * opaque DistinguishedName<1..2^16-1>;
*/ */
p += 2; p += 2;
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if( ssl->handshake->sni_ca_chain != NULL )
crt = ssl->handshake->sni_ca_chain;
else
#endif
crt = ssl->conf->ca_chain;
total_dn_size = 0; total_dn_size = 0;
while( crt != NULL && crt->version != 0 )
if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED )
{ {
dn_size = crt->subject_raw.len; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if( ssl->handshake->sni_ca_chain != NULL )
crt = ssl->handshake->sni_ca_chain;
else
#endif
crt = ssl->conf->ca_chain;
if( end < p || while( crt != NULL && crt->version != 0 )
(size_t)( end - p ) < dn_size ||
(size_t)( end - p ) < 2 + dn_size )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); dn_size = crt->subject_raw.len;
break;
}
*p++ = (unsigned char)( dn_size >> 8 ); if( end < p ||
*p++ = (unsigned char)( dn_size ); (size_t)( end - p ) < dn_size ||
memcpy( p, crt->subject_raw.p, dn_size ); (size_t)( end - p ) < 2 + dn_size )
p += dn_size; {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) );
break;
}
MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); *p++ = (unsigned char)( dn_size >> 8 );
*p++ = (unsigned char)( dn_size );
memcpy( p, crt->subject_raw.p, dn_size );
p += dn_size;
total_dn_size += 2 + dn_size; MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size );
crt = crt->next;
total_dn_size += 2 + dn_size;
crt = crt->next;
}
} }
ssl->out_msglen = p - buf; ssl->out_msglen = p - buf;
...@@ -2617,7 +2796,9 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) ...@@ -2617,7 +2796,9 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
} }
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
...@@ -2652,73 +2833,81 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2652,73 +2833,81 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info; ssl->transform_negotiate->ciphersuite_info;
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ #if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
unsigned char *p = ssl->out_msg + 4; unsigned char *p = ssl->out_msg + 4;
size_t len;
#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, len; size_t dig_signed_len = 0;
((void) dig_signed); #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
((void) dig_signed_len); #endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
((void) len);
#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ /*
defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ *
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) * Part 1: Extract static ECDH parameters and abort
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA || * if ServerKeyExchange not needed.
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || *
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) */
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ /* For suites involving ECDH, extract DH parameters
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) * from certificate at this point. */
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || #if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{ {
ssl_get_ecdh_params_from_cert( ssl ); ssl_get_ecdh_params_from_cert( ssl );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
/* Key exchanges not involving ephemeral keys don't use
* ServerKeyExchange, so end here. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++; ssl->state++;
return( 0 ); return( 0 );
} }
#endif #endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */
/*
*
* Part 2: Provide key exchange parameters for chosen ciphersuite.
*
*/
/*
* - ECJPAKE key exchanges
*/
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{ {
size_t jlen;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
p, end - p, &jlen, ssl->conf->f_rng, ssl->conf->p_rng ); p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
return( ret ); return( ret );
} }
p += jlen; p += len;
n += jlen; n += len;
} }
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ /*
* For (EC)DHE key exchanges with PSK, parameters are prefixed by support
* identity hint (RFC 4279, Sec. 3). Until someone needs this feature,
* we use empty support identity hints here.
**/
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{ {
/* TODO: Support identity hints */
*(p++) = 0x00; *(p++) = 0x00;
*(p++) = 0x00; *(p++) = 0x00;
...@@ -2727,10 +2916,11 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2727,10 +2916,11 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ /*
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) * - DHE key exchanges
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || */
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
{ {
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
{ {
...@@ -2762,8 +2952,10 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2762,8 +2952,10 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p; dig_signed = p;
dig_signed_len = len; dig_signed_len = len;
#endif
p += len; p += len;
n += len; n += len;
...@@ -2773,13 +2965,13 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -2773,13 +2965,13 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G );
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
} }
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || #endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */
MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
/*
* - ECDHE key exchanges
*/
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) )
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{ {
/* /*
* Ephemeral ECDH parameters: * Ephemeral ECDH parameters:
...@@ -2822,8 +3014,10 @@ curve_matching_done: ...@@ -2822,8 +3014,10 @@ curve_matching_done:
return( ret ); return( ret );
} }
dig_signed = p; #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p;
dig_signed_len = len; dig_signed_len = len;
#endif
p += len; p += len;
n += len; n += len;
...@@ -2832,29 +3026,44 @@ curve_matching_done: ...@@ -2832,29 +3026,44 @@ curve_matching_done:
} }
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ /*
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ *
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) * Part 3: For key exchanges involving the server signing the
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || * exchange parameters, compute and add the signature here.
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || *
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
{ {
size_t signature_len = 0; size_t signature_len = 0;
unsigned int hashlen = 0; unsigned int hashlen = 0;
unsigned char hash[64]; unsigned char hash[64];
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
/* /*
* Choose hash algorithm. NONE means MD5 + SHA1 here. * 3.1: Choose hash algorithm:
* A: For TLS 1.2, obey signature-hash-algorithm extension
* to choose appropriate hash.
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
* (RFC 4492, Sec. 5.4)
* C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3)
*/ */
mbedtls_md_type_t md_alg;
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
mbedtls_pk_type_t sig_alg =
mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{ {
md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->sig_alg ); /* A: For TLS 1.2, obey signature-hash-algorithm extension
* (RFC 5246, Sec. 7.4.1.4.1). */
if( md_alg == MBEDTLS_MD_NONE ) if( sig_alg == MBEDTLS_PK_NONE ||
( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs,
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
* only if there is a matching hash.) */
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
} }
...@@ -2862,19 +3071,23 @@ curve_matching_done: ...@@ -2862,19 +3071,23 @@ curve_matching_done:
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1) defined(MBEDTLS_SSL_PROTO_TLS1_1)
if( ciphersuite_info->key_exchange == if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
{ {
/* B: Default hash SHA1 */
md_alg = MBEDTLS_MD_SHA1; md_alg = MBEDTLS_MD_SHA1;
} }
else else
#endif #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
MBEDTLS_SSL_PROTO_TLS1_1 */
{ {
/* C: MD5 + SHA1 */
md_alg = MBEDTLS_MD_NONE; md_alg = MBEDTLS_MD_NONE;
} }
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
/* /*
* Compute the hash to be signed * 3.2: Compute the hash to be signed
*/ */
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1) defined(MBEDTLS_SSL_PROTO_TLS1_1)
...@@ -2899,6 +3112,7 @@ curve_matching_done: ...@@ -2899,6 +3112,7 @@ curve_matching_done:
* SHA(ClientHello.random + ServerHello.random * SHA(ClientHello.random + ServerHello.random
* + ServerParams); * + ServerParams);
*/ */
mbedtls_md5_starts( &mbedtls_md5 ); mbedtls_md5_starts( &mbedtls_md5 );
mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 );
mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len ); mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len );
...@@ -2960,7 +3174,7 @@ curve_matching_done: ...@@ -2960,7 +3174,7 @@ curve_matching_done:
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
/* /*
* Make the signature * 3.3: Compute and add the signature
*/ */
if( mbedtls_ssl_own_key( ssl ) == NULL ) if( mbedtls_ssl_own_key( ssl ) == NULL )
{ {
...@@ -2971,16 +3185,31 @@ curve_matching_done: ...@@ -2971,16 +3185,31 @@ curve_matching_done:
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{ {
*(p++) = ssl->handshake->sig_alg; /*
*(p++) = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); * For TLS 1.2, we need to specify signature and hash algorithm
* explicitly through a prefix to the signature.
*
* struct {
* HashAlgorithm hash;
* SignatureAlgorithm signature;
* } SignatureAndHashAlgorithm;
*
* struct {
* SignatureAndHashAlgorithm algorithm;
* opaque signature<0..2^16-1>;
* } DigitallySigned;
*
*/
*(p++) = mbedtls_ssl_hash_from_md_alg( md_alg );
*(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg );
n += 2; n += 2;
} }
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen,
p + 2 , &signature_len, p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
return( ret ); return( ret );
...@@ -2994,9 +3223,9 @@ curve_matching_done: ...@@ -2994,9 +3223,9 @@ curve_matching_done:
n += signature_len; n += signature_len;
} }
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ /* Done with actual work; add header and send. */
ssl->out_msglen = 4 + n; ssl->out_msglen = 4 + n;
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
...@@ -3238,13 +3467,8 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha ...@@ -3238,13 +3467,8 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha
if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY )
{ {
MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n );
if( ( ret = mbedtls_ssl_send_alert_message( ssl, mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY );
MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 )
{
return( ret );
}
return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY );
} }
...@@ -3506,11 +3730,14 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) ...@@ -3506,11 +3730,14 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ #if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
{ {
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
...@@ -3540,7 +3767,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3540,7 +3767,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
mbedtls_pk_type_t pk_alg; mbedtls_pk_type_t pk_alg;
#endif #endif
mbedtls_md_type_t md_alg; mbedtls_md_type_t md_alg;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
...@@ -3556,17 +3784,28 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3556,17 +3784,28 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
return( 0 ); return( 0 );
} }
/* Needs to be done before read_record() to exclude current message */ /* Read the message without adding it to the checksum */
ssl->handshake->calc_verify( ssl, hash ); do {
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
return( ret );
}
ret = mbedtls_ssl_handle_message_type( ssl );
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
if( 0 != ret )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
return( ret ); return( ret );
} }
ssl->state++; ssl->state++;
/* Process the message contents */
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY )
{ {
...@@ -3613,14 +3852,19 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3613,14 +3852,19 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
/* /*
* Hash * Hash
*/ */
if( ssl->in_msg[i] != ssl->handshake->verify_sig_alg ) md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] );
if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
" for verify message" ) ); " for verify message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
} }
md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg ); #if !defined(MBEDTLS_MD_SHA1)
if( MBEDTLS_MD_SHA1 == md_alg )
hash_start += 16;
#endif
/* Info from md_alg will be used instead */ /* Info from md_alg will be used instead */
hashlen = 0; hashlen = 0;
...@@ -3671,6 +3915,9 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3671,6 +3915,9 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
} }
/* Calculate hash and verify signature */
ssl->handshake->calc_verify( ssl, hash );
if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
md_alg, hash_start, hashlen, md_alg, hash_start, hashlen,
ssl->in_msg + i, sig_len ) ) != 0 ) ssl->in_msg + i, sig_len ) ) != 0 )
...@@ -3679,13 +3926,18 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) ...@@ -3679,13 +3926,18 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
mbedtls_ssl_update_handshake_status( ssl );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
return( ret ); return( ret );
} }
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && #endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_SESSION_TICKETS)
static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
...@@ -3860,9 +4112,6 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) ...@@ -3860,9 +4112,6 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
case MBEDTLS_SSL_SERVER_FINISHED: case MBEDTLS_SSL_SERVER_FINISHED:
ret = mbedtls_ssl_write_finished( ssl ); ret = mbedtls_ssl_write_finished( ssl );
#if defined(ESP8266_PLATFORM)
mbedtls_write_finished(ssl);
#endif
break; break;
case MBEDTLS_SSL_FLUSH_BUFFERS: case MBEDTLS_SSL_FLUSH_BUFFERS:
......
...@@ -27,16 +27,16 @@ ...@@ -27,16 +27,16 @@
#if defined(MBEDTLS_SSL_TICKET_C) #if defined(MBEDTLS_SSL_TICKET_C)
#include "mbedtls/ssl_ticket.h"
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
#define mbedtls_free free #define mbedtls_free free
#endif #endif
#include "mbedtls/ssl_ticket.h"
#include <string.h> #include <string.h>
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
...@@ -69,7 +69,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, ...@@ -69,7 +69,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
mbedtls_ssl_ticket_key *key = ctx->keys + index; mbedtls_ssl_ticket_key *key = ctx->keys + index;
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
key->generation_time = (uint32_t) time( NULL ); key->generation_time = (uint32_t) mbedtls_time( NULL );
#endif #endif
if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 )
...@@ -98,7 +98,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) ...@@ -98,7 +98,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
#else #else
if( ctx->ticket_lifetime != 0 ) if( ctx->ticket_lifetime != 0 )
{ {
uint32_t current_time = (uint32_t) 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 &&
...@@ -451,7 +451,7 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, ...@@ -451,7 +451,7 @@ int mbedtls_ssl_ticket_parse( void *p_ticket,
#if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_HAVE_TIME)
{ {
/* Check for expiration */ /* Check for expiration */
time_t current_time = time( NULL ); mbedtls_time_t current_time = mbedtls_time( NULL );
if( current_time < session->start || if( current_time < session->start ||
(uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime )
......
...@@ -35,25 +35,24 @@ ...@@ -35,25 +35,24 @@
#if defined(MBEDTLS_SSL_TLS_C) #if defined(MBEDTLS_SSL_TLS_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "mbedtls/debug.h" #include "mbedtls/debug.h"
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h" #include "mbedtls/ssl_internal.h"
#include <string.h> #include <string.h>
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ #if defined(MBEDTLS_X509_CRT_PARSE_C)
defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#endif #endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0; volatile unsigned char *p = v; while( n-- ) *p++ = 0;
...@@ -1374,17 +1373,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) ...@@ -1374,17 +1373,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
/* /*
* Generate IV * Generate IV
*/ */
#if defined(MBEDTLS_SSL_AEAD_RANDOM_IV)
ret = ssl->conf->f_rng( ssl->conf->p_rng,
ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
if( ret != 0 )
return( ret );
memcpy( ssl->out_iv,
ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
#else
if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 )
{ {
/* Reminder if we ever add an AEAD mode with a different size */ /* Reminder if we ever add an AEAD mode with a different size */
...@@ -1395,7 +1383,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) ...@@ -1395,7 +1383,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
ssl->out_ctr, 8 ); ssl->out_ctr, 8 );
memcpy( ssl->out_iv, ssl->out_ctr, 8 ); memcpy( ssl->out_iv, ssl->out_ctr, 8 );
#endif
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
...@@ -2708,7 +2695,7 @@ void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) ...@@ -2708,7 +2695,7 @@ void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
*/ */
int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
{ {
int ret, done = 0; int ret, done = 0, out_msg_type;
size_t len = ssl->out_msglen; size_t len = ssl->out_msglen;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
...@@ -2724,7 +2711,9 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ...@@ -2724,7 +2711,9 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
#endif #endif
if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
if( ssl->out_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST && out_msg_type = ssl->out_msg[0];
if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST &&
ssl->handshake == NULL ) ssl->handshake == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
...@@ -2751,7 +2740,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ...@@ -2751,7 +2740,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
len += 8; len += 8;
/* Write message_seq and update it, except for HelloRequest */ /* Write message_seq and update it, except for HelloRequest */
if( ssl->out_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ) if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
{ {
ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF;
...@@ -2769,7 +2758,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ...@@ -2769,7 +2758,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
} }
#endif /* MBEDTLS_SSL_PROTO_DTLS */ #endif /* MBEDTLS_SSL_PROTO_DTLS */
if( ssl->out_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ) if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); ssl->handshake->update_checksum( ssl, ssl->out_msg, len );
} }
...@@ -3081,7 +3070,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) ...@@ -3081,7 +3070,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
} }
#endif /* MBEDTLS_SSL_PROTO_DTLS */ #endif /* MBEDTLS_SSL_PROTO_DTLS */
static int ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
{ {
if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
{ {
...@@ -3163,6 +3152,12 @@ static int ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) ...@@ -3163,6 +3152,12 @@ static int ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
} }
return( 0 );
}
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
{
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
ssl->handshake != NULL ) ssl->handshake != NULL )
{ {
...@@ -3177,8 +3172,6 @@ static int ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) ...@@ -3177,8 +3172,6 @@ static int ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
ssl->handshake->in_msg_seq++; ssl->handshake->in_msg_seq++;
} }
#endif #endif
return( 0 );
} }
/* /*
...@@ -3435,7 +3428,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) ...@@ -3435,7 +3428,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
{ {
/* Dont check write errors as we can't do anything here. /* Don't check write errors as we can't do anything here.
* If the error is permanent we'll catch it later, * If the error is permanent we'll catch it later,
* if it's not, then hopefully it'll work next time. */ * if it's not, then hopefully it'll work next time. */
(void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len );
...@@ -3480,7 +3473,6 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) ...@@ -3480,7 +3473,6 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
*/ */
static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
{ {
int ret;
int major_ver, minor_ver; int major_ver, minor_ver;
MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) );
...@@ -3501,14 +3493,8 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) ...@@ -3501,14 +3493,8 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 )
{
return( ret );
}
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); return( MBEDTLS_ERR_SSL_INVALID_RECORD );
} }
...@@ -3529,7 +3515,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) ...@@ -3529,7 +3515,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN
- (size_t)( ssl->in_msg - ssl->in_buf ) ) - (size_t)( ssl->in_msg - ssl->in_buf ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length: in_msglen=%d", ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); return( MBEDTLS_ERR_SSL_INVALID_RECORD );
} }
...@@ -3539,7 +3525,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) ...@@ -3539,7 +3525,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
if( ssl->in_msglen < 1 || if( ssl->in_msglen < 1 ||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length: in_msglen=%d", ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); return( MBEDTLS_ERR_SSL_INVALID_RECORD );
} }
} }
...@@ -3547,7 +3533,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) ...@@ -3547,7 +3533,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
{ {
if( ssl->in_msglen < ssl->transform_in->minlen ) if( ssl->in_msglen < ssl->transform_in->minlen )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length: in_msglen=%d", ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); return( MBEDTLS_ERR_SSL_INVALID_RECORD );
} }
...@@ -3568,7 +3554,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) ...@@ -3568,7 +3554,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
ssl->in_msglen > ssl->transform_in->minlen + ssl->in_msglen > ssl->transform_in->minlen +
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length: in_msglen=%d", ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); return( MBEDTLS_ERR_SSL_INVALID_RECORD );
} }
#endif #endif
...@@ -3692,7 +3678,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) ...@@ -3692,7 +3678,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl )
if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length: in_msglen=%d", ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD ); return( MBEDTLS_ERR_SSL_INVALID_RECORD );
} }
} }
...@@ -3706,10 +3692,6 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) ...@@ -3706,10 +3692,6 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
return( ret ); return( ret );
} }
// TODO: what's the purpose of these lines? is in_len used?
ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 );
ssl->in_len[1] = (unsigned char)( ssl->in_msglen );
} }
#endif /* MBEDTLS_ZLIB_SUPPORT */ #endif /* MBEDTLS_ZLIB_SUPPORT */
...@@ -3738,31 +3720,156 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) ...@@ -3738,31 +3720,156 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
if( ssl->in_hslen != 0 && ssl->in_hslen < ssl->in_msglen ) if( ssl->keep_current_message == 0 )
{
do {
if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
return( ret );
}
ret = mbedtls_ssl_handle_message_type( ssl );
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
if( 0 != ret )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
return( ret );
}
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
{
mbedtls_ssl_update_handshake_status( ssl );
}
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) );
ssl->keep_current_message = 0;
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
return( 0 );
}
int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
{
int ret;
/*
* Step A
*
* Consume last content-layer message and potentially
* update in_msglen which keeps track of the contents'
* consumption state.
*
* (1) Handshake messages:
* Remove last handshake message, move content
* and adapt in_msglen.
*
* (2) Alert messages:
* Consume whole record content, in_msglen = 0.
*
* NOTE: This needs to be fixed, since like for
* handshake messages it is allowed to have
* multiple alerts witin a single record.
* Internal reference IOTSSL-1321.
*
* (3) Change cipher spec:
* Consume whole record content, in_msglen = 0.
*
* (4) Application data:
* Don't do anything - the record layer provides
* the application data as a stream transport
* and consumes through mbedtls_ssl_read only.
*
*/
/* Case (1): Handshake messages */
if( ssl->in_hslen != 0 )
{ {
/* Hard assertion to be sure that no application data
* is in flight, as corrupting ssl->in_msglen during
* ssl->in_offt != NULL is fatal. */
if( ssl->in_offt != NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
/* /*
* Get next Handshake message in the current record * Get next Handshake message in the current record
*/ */
ssl->in_msglen -= ssl->in_hslen;
memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, /* Notes:
ssl->in_msglen ); * (1) in_hslen is *NOT* necessarily the size of the
* current handshake content: If DTLS handshake
MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", * fragmentation is used, that's the fragment
ssl->in_msg, ssl->in_msglen ); * size instead. Using the total handshake message
* size here is FAULTY and should be changed at
* some point. Internal reference IOTSSL-1414.
* (2) While it doesn't seem to cause problems, one
* has to be very careful not to assume that in_hslen
* is always <= in_msglen in a sensible communication.
* Again, it's wrong for DTLS handshake fragmentation.
* The following check is therefore mandatory, and
* should not be treated as a silently corrected assertion.
* Additionally, ssl->in_hslen might be arbitrarily out of
* bounds after handling a DTLS message with an unexpected
* sequence number, see mbedtls_ssl_prepare_handshake_record.
*/
if( ssl->in_hslen < ssl->in_msglen )
{
ssl->in_msglen -= ssl->in_hslen;
memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
ssl->in_msglen );
if( ( ret = ssl_prepare_handshake_record( ssl ) ) != 0 ) MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record",
return( ret ); ssl->in_msg, ssl->in_msglen );
}
else
{
ssl->in_msglen = 0;
}
ssl->in_hslen = 0;
}
/* Case (4): Application data */
else if( ssl->in_offt != NULL )
{
return( 0 ); return( 0 );
} }
/* Everything else (CCS & Alerts) */
ssl->in_hslen = 0; else
{
ssl->in_msglen = 0;
}
/* /*
* Read the record header and parse it * Step B
*
* Fetch and decode new record if current one is fully consumed.
*
*/ */
if( ssl->in_msglen > 0 )
{
/* There's something left to be processed in the current record. */
return( 0 );
}
/* Need to fetch a new record */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
read_record_header: read_record_header:
#endif
/* Current record either fully processed or to be discarded. */
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
...@@ -3854,6 +3961,12 @@ read_record_header: ...@@ -3854,6 +3961,12 @@ read_record_header:
} }
#endif #endif
/* As above, invalid records cause
* dismissal of the whole datagram. */
ssl->next_record_offset = 0;
ssl->in_left = 0;
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
goto read_record_header; goto read_record_header;
} }
...@@ -3916,13 +4029,22 @@ read_record_header: ...@@ -3916,13 +4029,22 @@ read_record_header:
} }
#endif #endif
return( 0 );
}
int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
{
int ret;
/* /*
* Handle particular types of records * Handle particular types of records
*/ */
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
if( ( ret = ssl_prepare_handshake_record( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 )
{
return( ret ); return( ret );
}
} }
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
...@@ -3970,11 +4092,9 @@ read_record_header: ...@@ -3970,11 +4092,9 @@ read_record_header:
#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
/* Silently ignore: fetch new message */ /* Silently ignore: fetch new message */
goto read_record_header; return MBEDTLS_ERR_SSL_NON_FATAL;
} }
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
return( 0 ); return( 0 );
} }
...@@ -4002,6 +4122,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, ...@@ -4002,6 +4122,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
ssl->out_msglen = 2; ssl->out_msglen = 2;
...@@ -4013,7 +4134,6 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, ...@@ -4013,7 +4134,6 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret ); return( ret );
} }
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
return( 0 ); return( 0 );
...@@ -4029,6 +4149,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, ...@@ -4029,6 +4149,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
/* No certificate support -> dummy functions */
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
{ {
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
...@@ -4068,7 +4189,10 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4068,7 +4189,10 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
#else #else
/* Some certificate support -> implement write and parse */
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
{ {
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
...@@ -4191,6 +4315,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4191,6 +4315,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
size_t i, n; size_t i, n;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
int authmode = ssl->conf->authmode; int authmode = ssl->conf->authmode;
uint8_t alert;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
...@@ -4230,6 +4355,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4230,6 +4355,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{ {
/* mbedtls_ssl_read_record may have sent an alert already. We
let it decide whether to alert. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret ); return( ret );
} }
...@@ -4251,6 +4378,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4251,6 +4378,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
/* The client was asked for a certificate but didn't send
one. The client should know what's going on, so we
don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
return( 0 ); return( 0 );
...@@ -4272,6 +4402,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4272,6 +4402,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
/* The client was asked for a certificate but didn't send
one. The client should know what's going on, so we
don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
return( 0 ); return( 0 );
...@@ -4286,6 +4419,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4286,6 +4419,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -4293,6 +4428,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4293,6 +4428,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate 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 ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
} }
...@@ -4307,6 +4444,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4307,6 +4444,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate 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 ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
} }
...@@ -4322,6 +4461,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4322,6 +4461,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
sizeof( mbedtls_x509_crt ) ) ); sizeof( mbedtls_x509_crt ) ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
} }
...@@ -4334,6 +4475,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4334,6 +4475,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ssl->in_msg[i] != 0 ) if( ssl->in_msg[i] != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate 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 ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
} }
...@@ -4344,13 +4487,33 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4344,13 +4487,33 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( n < 128 || i + n > ssl->in_hslen ) if( n < 128 || i + n > ssl->in_hslen )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate 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 ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
} }
ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert,
ssl->in_msg + i, n ); ssl->in_msg + i, n );
if( ret != 0 ) switch( ret )
{ {
case 0: /*ok*/
case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
/* Ignore certificate with an unknown algorithm: maybe a
prior certificate was already trusted. */
break;
case MBEDTLS_ERR_X509_ALLOC_FAILED:
alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
goto crt_parse_der_failed;
case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
goto crt_parse_der_failed;
default:
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
crt_parse_der_failed:
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert );
MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
return( ret ); return( ret );
} }
...@@ -4371,6 +4534,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4371,6 +4534,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ssl->session->peer_cert == NULL ) if( ssl->session->peer_cert == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
} }
...@@ -4381,6 +4546,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4381,6 +4546,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
ssl->session->peer_cert->raw.len ) != 0 ) ssl->session->peer_cert->raw.len ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
} }
} }
...@@ -4404,12 +4571,6 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4404,12 +4571,6 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
ca_crl = ssl->conf->ca_crl; ca_crl = ssl->conf->ca_crl;
} }
if( ca_chain == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED );
}
/* /*
* Main check: verify certificate * Main check: verify certificate
*/ */
...@@ -4423,6 +4584,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4423,6 +4584,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "x509_verify_cert flags: %d", ssl->session_negotiate->verify_result ) );
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
} }
...@@ -4438,6 +4600,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4438,6 +4600,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
{ {
ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
if( ret == 0 ) if( ret == 0 )
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
...@@ -4446,8 +4610,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4446,8 +4610,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
ciphersuite_info, ciphersuite_info,
! ssl->conf->endpoint, ! ssl->conf->endpoint,
&ssl->session_negotiate->verify_result ) != 0 ) &ssl->session_negotiate->verify_result ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
...@@ -4455,8 +4619,67 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ...@@ -4455,8 +4619,67 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
} }
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) /* mbedtls_x509_crt_verify_with_profile is supposed to report a
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
* with details encoded in the verification flags. All other kinds
* of error codes, including those from the user provided f_vrfy
* functions, are treated as fatal and lead to a failure of
* ssl_parse_certificate even if verification was optional. */
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
{
ret = 0; ret = 0;
}
if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
}
if( ret != 0 )
{
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER )
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH )
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE )
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE )
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE )
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK )
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY )
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED )
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED )
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED )
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
else
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
alert );
}
#if defined(MBEDTLS_DEBUG_C)
if( ssl->session_negotiate->verify_result != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x",
ssl->session_negotiate->verify_result ) );
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
}
#endif /* MBEDTLS_DEBUG_C */
} }
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
...@@ -4509,12 +4732,16 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) ...@@ -4509,12 +4732,16 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
} }
...@@ -4537,6 +4764,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) ...@@ -4537,6 +4764,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
if( ++ssl->in_epoch == 0 ) if( ++ssl->in_epoch == 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
/* This is highly unlikely to happen for legitimate reasons, so
treat it as an attack and don't send an alert. */
return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
} }
} }
...@@ -4561,6 +4790,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) ...@@ -4561,6 +4790,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
} }
} }
...@@ -5015,7 +5246,12 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) ...@@ -5015,7 +5246,12 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
// TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) /*
* RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
* may define some other value. Currently (early 2016), no defined
* ciphersuite does this (and this is unlikely to change as activity has
* moved to TLS 1.3 now) so we can keep the hardcoded 12 here.
*/
hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12;
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
...@@ -5134,6 +5370,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ...@@ -5134,6 +5370,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
...@@ -5149,6 +5387,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ...@@ -5149,6 +5387,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
} }
...@@ -5156,6 +5396,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ...@@ -5156,6 +5396,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
buf, hash_len ) != 0 ) buf, hash_len ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
} }
...@@ -5211,7 +5453,11 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) ...@@ -5211,7 +5453,11 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
handshake->update_checksum = ssl_update_checksum_start; handshake->update_checksum = ssl_update_checksum_start;
handshake->sig_alg = MBEDTLS_SSL_HASH_SHA1;
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs );
#endif
#if defined(MBEDTLS_DHM_C) #if defined(MBEDTLS_DHM_C)
mbedtls_dhm_init( &handshake->dhm_ctx ); mbedtls_dhm_init( &handshake->dhm_ctx );
...@@ -5368,7 +5614,6 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, ...@@ -5368,7 +5614,6 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
/* /*
* Prepare base structures * Prepare base structures
*/ */
#if !defined(ESP8266_PLATFORM)
if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL ||
( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL )
{ {
...@@ -5377,16 +5622,6 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, ...@@ -5377,16 +5622,6 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
ssl->in_buf = NULL; ssl->in_buf = NULL;
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
} }
#else
if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL)
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) );
mbedtls_free( ssl->in_buf );
ssl->in_buf = NULL;
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
ssl->out_buf = ssl->in_buf;
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
...@@ -5468,7 +5703,8 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ...@@ -5468,7 +5703,8 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->in_hslen = 0; ssl->in_hslen = 0;
ssl->nb_zero = 0; ssl->nb_zero = 0;
ssl->record_read = 0;
ssl->keep_current_message = 0;
ssl->out_msg = ssl->out_buf + 13; ssl->out_msg = ssl->out_buf + 13;
ssl->out_msgtype = 0; ssl->out_msgtype = 0;
...@@ -5608,9 +5844,9 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, ...@@ -5608,9 +5844,9 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf,
void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
void *p_bio, void *p_bio,
int (*f_send)(void *, const unsigned char *, size_t), mbedtls_ssl_send_t *f_send,
int (*f_recv)(void *, unsigned char *, size_t), mbedtls_ssl_recv_t *f_recv,
int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ) mbedtls_ssl_recv_timeout_t *f_recv_timeout )
{ {
ssl->p_bio = p_bio; ssl->p_bio = p_bio;
ssl->f_send = f_send; ssl->f_send = f_send;
...@@ -5625,8 +5861,8 @@ void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) ...@@ -5625,8 +5861,8 @@ void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout )
void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
void *p_timer, void *p_timer,
void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms), mbedtls_ssl_set_timer_t *f_set_timer,
int (*f_get_timer)(void *) ) mbedtls_ssl_get_timer_t *f_get_timer )
{ {
ssl->p_timer = p_timer; ssl->p_timer = p_timer;
ssl->f_set_timer = f_set_timer; ssl->f_set_timer = f_set_timer;
...@@ -5780,7 +6016,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, ...@@ -5780,7 +6016,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
{ {
mbedtls_ecjpake_role role; mbedtls_ecjpake_role role;
if( ssl->handshake == NULL && ssl->conf == NULL ) if( ssl->handshake == NULL || ssl->conf == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
...@@ -5984,8 +6220,9 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot ...@@ -5984,8 +6220,9 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot
const char **p; const char **p;
/* /*
* "Empty strings MUST NOT be included and byte strings MUST NOT be * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings
* truncated". Check lengths now rather than later. * MUST NOT be truncated."
* We check lengths now rather than later.
*/ */
tot_len = 0; tot_len = 0;
for( p = protos; *p != NULL; p++ ) for( p = protos; *p != NULL; p++ )
...@@ -6027,6 +6264,14 @@ void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) ...@@ -6027,6 +6264,14 @@ void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback )
} }
#endif #endif
#if defined(MBEDTLS_SSL_SRV_C)
void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
char cert_req_ca_list )
{
conf->cert_req_ca_list = cert_req_ca_list;
}
#endif
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm )
{ {
...@@ -6299,7 +6544,6 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) ...@@ -6299,7 +6544,6 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
void mbedtls_handshake_heap(mbedtls_ssl_context *ssl);
/* /*
* Perform the SSL handshake * Perform the SSL handshake
...@@ -6315,7 +6559,6 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) ...@@ -6315,7 +6559,6 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl )
while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
{ {
//mbedtls_handshake_heap(ssl);
ret = mbedtls_ssl_handshake_step( ssl ); ret = mbedtls_ssl_handshake_step( ssl );
if( ret != 0 ) if( ret != 0 )
...@@ -6461,6 +6704,10 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) ...@@ -6461,6 +6704,10 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl )
*/ */
static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
{ {
size_t ep_len = ssl_ep_len( ssl );
int in_ctr_cmp;
int out_ctr_cmp;
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
...@@ -6468,8 +6715,12 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) ...@@ -6468,8 +6715,12 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
return( 0 ); return( 0 );
} }
if( memcmp( ssl->in_ctr, ssl->conf->renego_period, 8 ) <= 0 && in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
memcmp( ssl->out_ctr, ssl->conf->renego_period, 8 ) <= 0 ) ssl->conf->renego_period + ep_len, 8 - ep_len );
out_ctr_cmp = memcmp( ssl->out_ctr + ep_len,
ssl->conf->renego_period + ep_len, 8 - ep_len );
if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
{ {
return( 0 ); return( 0 );
} }
...@@ -6484,7 +6735,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) ...@@ -6484,7 +6735,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
*/ */
int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
{ {
int ret, record_read = 0; int ret;
size_t n; size_t n;
if( ssl == NULL || ssl->conf == NULL ) if( ssl == NULL || ssl->conf == NULL )
...@@ -6507,8 +6758,22 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6507,8 +6758,22 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
} }
#endif #endif
/*
* Check if renegotiation is necessary and/or handshake is
* in process. If yes, perform/continue, and fall through
* if an unexpected packet is received while the client
* is waiting for the ServerHello.
*
* (There is no equivalent to the last condition on
* the server-side as it is not treated as within
* a handshake while waiting for the ClientHello
* after a renegotiation request.)
*/
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) ret = ssl_check_ctr_renegotiate( ssl );
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
return( ret ); return( ret );
...@@ -6518,17 +6783,49 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6518,17 +6783,49 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
{ {
ret = mbedtls_ssl_handshake( ssl ); ret = mbedtls_ssl_handshake( ssl );
if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
{ ret != 0 )
record_read = 1;
}
else if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
return( ret ); return( ret );
} }
} }
/*
* TODO
*
* The logic should be streamlined here:
*
* Instead of
*
* - Manually checking whether ssl->in_offt is NULL
* - Fetching a new record if yes
* - Setting ssl->in_offt if one finds an application record
* - Resetting keep_current_message after handling the application data
*
* one should
*
* - Adapt read_record to set ssl->in_offt automatically
* when a new application data record is processed.
* - Always call mbedtls_ssl_read_record here.
*
* This way, the logic of ssl_read would be much clearer:
*
* (1) Always call record layer and see what kind of record is on
* and have it ready for consumption (in particular, in_offt
* properly set for application data records).
* (2) If it's application data (either freshly fetched
* or something already being partially processed),
* serve the read request from it.
* (3) If it's something different from application data,
* handle it accordingly, e.g. potentially start a
* renegotiation.
*
* This will also remove the need to manually reset
* ssl->keep_current_message = 0 below.
*
*/
if( ssl->in_offt == NULL ) if( ssl->in_offt == NULL )
{ {
/* Start timer if not already running */ /* Start timer if not already running */
...@@ -6538,16 +6835,13 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6538,16 +6835,13 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
ssl_set_timer( ssl, ssl->conf->read_timeout ); ssl_set_timer( ssl, ssl->conf->read_timeout );
} }
if( ! record_read ) if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{ {
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
{ return( 0 );
if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
return( 0 );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret ); return( ret );
}
} }
if( ssl->in_msglen == 0 && if( ssl->in_msglen == 0 &&
...@@ -6571,10 +6865,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6571,10 +6865,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
/*
* - For client-side, expect SERVER_HELLO_REQUEST.
* - For server-side, expect CLIENT_HELLO.
* - Fail (TLS) or silently drop record (DTLS) in other cases.
*/
#if defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_CLI_C)
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
...@@ -6585,7 +6885,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6585,7 +6885,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
#endif #endif
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
#endif /* MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SRV_C)
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
{ {
...@@ -6598,23 +6900,29 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6598,23 +6900,29 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
#endif #endif
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
#endif #endif /* MBEDTLS_SSL_SRV_C */
/* Determine whether renegotiation attempt should be accepted */
if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
ssl->conf->allow_legacy_renegotiation == ssl->conf->allow_legacy_renegotiation ==
MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) )
{ {
/*
* Refuse renegotiation
*/
MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
#if defined(MBEDTLS_SSL_PROTO_SSL3) #if defined(MBEDTLS_SSL_PROTO_SSL3)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
{ {
/* /* SSLv3 does not have a "no_renegotiation" warning, so
* SSLv3 does not have a "no_renegotiation" alert we send a fatal alert and abort the connection. */
*/ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( ret ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
else else
#endif /* MBEDTLS_SSL_PROTO_SSL3 */ #endif /* MBEDTLS_SSL_PROTO_SSL3 */
...@@ -6639,6 +6947,10 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6639,6 +6947,10 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
} }
else else
{ {
/*
* Accept renegotiation request
*/
/* DTLS clients need to know renego is server-initiated */ /* DTLS clients need to know renego is server-initiated */
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
...@@ -6648,25 +6960,18 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6648,25 +6960,18 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
} }
#endif #endif
ret = ssl_start_renegotiation( ssl ); ret = ssl_start_renegotiation( ssl );
if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
{ ret != 0 )
record_read = 1;
}
else if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
return( ret ); return( ret );
} }
} }
/* If a non-handshake record was read during renego, fallthrough, return( MBEDTLS_ERR_SSL_WANT_READ );
* else tell the user they should call mbedtls_ssl_read() again */
if( ! record_read )
return( MBEDTLS_ERR_SSL_WANT_READ );
} }
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
{ {
if( ssl->conf->renego_max_records >= 0 ) if( ssl->conf->renego_max_records >= 0 )
{ {
if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
...@@ -6714,7 +7019,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6714,7 +7019,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
} }
} }
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
#endif #endif /* MBEDTLS_SSL_PROTO_DTLS */
} }
n = ( len < ssl->in_msglen ) n = ( len < ssl->in_msglen )
...@@ -6724,11 +7029,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ...@@ -6724,11 +7029,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
ssl->in_msglen -= n; ssl->in_msglen -= n;
if( ssl->in_msglen == 0 ) if( ssl->in_msglen == 0 )
/* all bytes consumed */ {
/* all bytes consumed */
ssl->in_offt = NULL; ssl->in_offt = NULL;
ssl->keep_current_message = 0;
}
else else
{
/* more data available */ /* more data available */
ssl->in_offt += n; ssl->in_offt += n;
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
...@@ -6962,7 +7272,8 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) ...@@ -6962,7 +7272,8 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake )
#endif #endif
#endif #endif
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
/* explicit void pointer cast for buggy MS compiler */ /* explicit void pointer cast for buggy MS compiler */
mbedtls_free( (void *) handshake->curves ); mbedtls_free( (void *) handshake->curves );
#endif #endif
...@@ -7033,8 +7344,6 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) ...@@ -7033,8 +7344,6 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) );
#if !defined(ESP8266_PLATFORM)
if( ssl->out_buf != NULL ) if( ssl->out_buf != NULL )
{ {
mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN );
...@@ -7046,14 +7355,6 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) ...@@ -7046,14 +7355,6 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
mbedtls_free( ssl->in_buf ); mbedtls_free( ssl->in_buf );
} }
#else
if( ssl->in_buf != NULL )
{
mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
mbedtls_free( ssl->in_buf );
}
#endif
#if defined(MBEDTLS_ZLIB_SUPPORT) #if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->compress_buf != NULL ) if( ssl->compress_buf != NULL )
...@@ -7130,7 +7431,7 @@ static int ssl_preset_default_hashes[] = { ...@@ -7130,7 +7431,7 @@ static int ssl_preset_default_hashes[] = {
MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA256,
MBEDTLS_MD_SHA224, MBEDTLS_MD_SHA224,
#endif #endif
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE)
MBEDTLS_MD_SHA1, MBEDTLS_MD_SHA1,
#endif #endif
MBEDTLS_MD_NONE MBEDTLS_MD_NONE
...@@ -7212,6 +7513,10 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, ...@@ -7212,6 +7513,10 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED;
#endif #endif
#if defined(MBEDTLS_SSL_SRV_C)
conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED;
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN;
conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;
...@@ -7219,8 +7524,8 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, ...@@ -7219,8 +7524,8 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_RENEGOTIATION)
conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT;
memset( conf->renego_period, 0xFF, 7 ); memset( conf->renego_period, 0x00, 2 );
conf->renego_period[7] = 0x00; memset( conf->renego_period + 2, 0xFF, 6 );
#endif #endif
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
...@@ -7355,6 +7660,19 @@ unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) ...@@ -7355,6 +7660,19 @@ unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk )
return( MBEDTLS_SSL_SIG_ANON ); return( MBEDTLS_SSL_SIG_ANON );
} }
unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type )
{
switch( type ) {
case MBEDTLS_PK_RSA:
return( MBEDTLS_SSL_SIG_RSA );
case MBEDTLS_PK_ECDSA:
case MBEDTLS_PK_ECKEY:
return( MBEDTLS_SSL_SIG_ECDSA );
default:
return( MBEDTLS_SSL_SIG_ANON );
}
}
mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig )
{ {
switch( sig ) switch( sig )
...@@ -7373,6 +7691,57 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) ...@@ -7373,6 +7691,57 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig )
} }
#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ #endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
/* Find an entry in a signature-hash set matching a given hash algorithm. */
mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set,
mbedtls_pk_type_t sig_alg )
{
switch( sig_alg )
{
case MBEDTLS_PK_RSA:
return( set->rsa );
case MBEDTLS_PK_ECDSA:
return( set->ecdsa );
default:
return( MBEDTLS_MD_NONE );
}
}
/* Add a signature-hash-pair to a signature-hash set */
void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set,
mbedtls_pk_type_t sig_alg,
mbedtls_md_type_t md_alg )
{
switch( sig_alg )
{
case MBEDTLS_PK_RSA:
if( set->rsa == MBEDTLS_MD_NONE )
set->rsa = md_alg;
break;
case MBEDTLS_PK_ECDSA:
if( set->ecdsa == MBEDTLS_MD_NONE )
set->ecdsa = md_alg;
break;
default:
break;
}
}
/* Allow exactly one hash algorithm for each signature. */
void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set,
mbedtls_md_type_t md_alg )
{
set->rsa = md_alg;
set->ecdsa = md_alg;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2) &&
MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
/* /*
* Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX
*/ */
...@@ -7574,7 +7943,7 @@ int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, ...@@ -7574,7 +7943,7 @@ int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
* and, for DTLS, to/from TLS equivalent. * and, for DTLS, to/from TLS equivalent.
* *
* For TLS this is the identity. * For TLS this is the identity.
* For DTLS, use one complement (v -> 255 - v, and then map as follows: * For DTLS, use 1's complement (v -> 255 - v, and then map as follows:
* 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1)
* 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2)
*/ */
...@@ -7622,4 +7991,46 @@ void mbedtls_ssl_read_version( int *major, int *minor, int transport, ...@@ -7622,4 +7991,46 @@ void mbedtls_ssl_read_version( int *major, int *minor, int transport,
} }
} }
int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md )
{
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
switch( md )
{
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
#if defined(MBEDTLS_MD5_C)
case MBEDTLS_SSL_HASH_MD5:
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
#endif
#if defined(MBEDTLS_SHA1_C)
case MBEDTLS_SSL_HASH_SHA1:
ssl->handshake->calc_verify = ssl_calc_verify_tls;
break;
#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_SSL_HASH_SHA384:
ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384;
break;
#endif
#if defined(MBEDTLS_SHA256_C)
case MBEDTLS_SSL_HASH_SHA256:
ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256;
break;
#endif
default:
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
}
return 0;
#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */
(void) ssl;
(void) md;
return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
}
#endif /* MBEDTLS_SSL_TLS_C */ #endif /* MBEDTLS_SSL_TLS_C */
...@@ -40,10 +40,11 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) ...@@ -40,10 +40,11 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex )
{ {
if( mutex == NULL ) if( mutex == NULL || !mutex->is_valid )
return; return;
(void) pthread_mutex_destroy( &mutex->mutex ); (void) pthread_mutex_destroy( &mutex->mutex );
mutex->is_valid = 0;
} }
static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex )
......
...@@ -38,6 +38,11 @@ ...@@ -38,6 +38,11 @@
#if !defined(MBEDTLS_TIMING_ALT) #if !defined(MBEDTLS_TIMING_ALT)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32)
#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
#endif
#ifndef asm #ifndef asm
#define asm __asm #define asm __asm
#endif #endif
......
...@@ -36,6 +36,9 @@ static const char *features[] = { ...@@ -36,6 +36,9 @@ static const char *features[] = {
#if defined(MBEDTLS_HAVE_ASM) #if defined(MBEDTLS_HAVE_ASM)
"MBEDTLS_HAVE_ASM", "MBEDTLS_HAVE_ASM",
#endif /* MBEDTLS_HAVE_ASM */ #endif /* MBEDTLS_HAVE_ASM */
#if defined(MBEDTLS_NO_UDBL_DIVISION)
"MBEDTLS_NO_UDBL_DIVISION",
#endif /* MBEDTLS_NO_UDBL_DIVISION */
#if defined(MBEDTLS_HAVE_SSE2) #if defined(MBEDTLS_HAVE_SSE2)
"MBEDTLS_HAVE_SSE2", "MBEDTLS_HAVE_SSE2",
#endif /* MBEDTLS_HAVE_SSE2 */ #endif /* MBEDTLS_HAVE_SSE2 */
...@@ -54,6 +57,9 @@ static const char *features[] = { ...@@ -54,6 +57,9 @@ static const char *features[] = {
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) #if defined(MBEDTLS_PLATFORM_EXIT_ALT)
"MBEDTLS_PLATFORM_EXIT_ALT", "MBEDTLS_PLATFORM_EXIT_ALT",
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ #endif /* MBEDTLS_PLATFORM_EXIT_ALT */
#if defined(MBEDTLS_PLATFORM_TIME_ALT)
"MBEDTLS_PLATFORM_TIME_ALT",
#endif /* MBEDTLS_PLATFORM_TIME_ALT */
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
"MBEDTLS_PLATFORM_FPRINTF_ALT", "MBEDTLS_PLATFORM_FPRINTF_ALT",
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
...@@ -63,6 +69,12 @@ static const char *features[] = { ...@@ -63,6 +69,12 @@ static const char *features[] = {
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
"MBEDTLS_PLATFORM_SNPRINTF_ALT", "MBEDTLS_PLATFORM_SNPRINTF_ALT",
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
"MBEDTLS_PLATFORM_NV_SEED_ALT",
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT)
"MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT",
#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
"MBEDTLS_DEPRECATED_WARNING", "MBEDTLS_DEPRECATED_WARNING",
#endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* MBEDTLS_DEPRECATED_WARNING */
...@@ -111,6 +123,9 @@ static const char *features[] = { ...@@ -111,6 +123,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SHA512_ALT) #if defined(MBEDTLS_SHA512_ALT)
"MBEDTLS_SHA512_ALT", "MBEDTLS_SHA512_ALT",
#endif /* MBEDTLS_SHA512_ALT */ #endif /* MBEDTLS_SHA512_ALT */
#if defined(MBEDTLS_ECP_ALT)
"MBEDTLS_ECP_ALT",
#endif /* MBEDTLS_ECP_ALT */
#if defined(MBEDTLS_MD2_PROCESS_ALT) #if defined(MBEDTLS_MD2_PROCESS_ALT)
"MBEDTLS_MD2_PROCESS_ALT", "MBEDTLS_MD2_PROCESS_ALT",
#endif /* MBEDTLS_MD2_PROCESS_ALT */ #endif /* MBEDTLS_MD2_PROCESS_ALT */
...@@ -153,6 +168,36 @@ static const char *features[] = { ...@@ -153,6 +168,36 @@ static const char *features[] = {
#if defined(MBEDTLS_AES_DECRYPT_ALT) #if defined(MBEDTLS_AES_DECRYPT_ALT)
"MBEDTLS_AES_DECRYPT_ALT", "MBEDTLS_AES_DECRYPT_ALT",
#endif /* MBEDTLS_AES_DECRYPT_ALT */ #endif /* MBEDTLS_AES_DECRYPT_ALT */
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
"MBEDTLS_ECP_INTERNAL_ALT",
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
"MBEDTLS_ECP_RANDOMIZE_JAC_ALT",
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
"MBEDTLS_ECP_ADD_MIXED_ALT",
#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
"MBEDTLS_ECP_DOUBLE_JAC_ALT",
#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
"MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT",
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
"MBEDTLS_ECP_NORMALIZE_JAC_ALT",
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
"MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT",
#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
"MBEDTLS_ECP_RANDOMIZE_MXZ_ALT",
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
"MBEDTLS_ECP_NORMALIZE_MXZ_ALT",
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
"MBEDTLS_TEST_NULL_ENTROPY",
#endif /* MBEDTLS_TEST_NULL_ENTROPY */
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
"MBEDTLS_ENTROPY_HARDWARE_ALT", "MBEDTLS_ENTROPY_HARDWARE_ALT",
#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
...@@ -288,6 +333,9 @@ static const char *features[] = { ...@@ -288,6 +333,9 @@ static const char *features[] = {
#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) #if defined(MBEDTLS_ENTROPY_FORCE_SHA256)
"MBEDTLS_ENTROPY_FORCE_SHA256", "MBEDTLS_ENTROPY_FORCE_SHA256",
#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ #endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */
#if defined(MBEDTLS_ENTROPY_NV_SEED)
"MBEDTLS_ENTROPY_NV_SEED",
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_MEMORY_DEBUG) #if defined(MBEDTLS_MEMORY_DEBUG)
"MBEDTLS_MEMORY_DEBUG", "MBEDTLS_MEMORY_DEBUG",
#endif /* MBEDTLS_MEMORY_DEBUG */ #endif /* MBEDTLS_MEMORY_DEBUG */
...@@ -312,9 +360,6 @@ static const char *features[] = { ...@@ -312,9 +360,6 @@ static const char *features[] = {
#if defined(MBEDTLS_SHA256_SMALLER) #if defined(MBEDTLS_SHA256_SMALLER)
"MBEDTLS_SHA256_SMALLER", "MBEDTLS_SHA256_SMALLER",
#endif /* MBEDTLS_SHA256_SMALLER */ #endif /* MBEDTLS_SHA256_SMALLER */
#if defined(MBEDTLS_SSL_AEAD_RANDOM_IV)
"MBEDTLS_SSL_AEAD_RANDOM_IV",
#endif /* MBEDTLS_SSL_AEAD_RANDOM_IV */
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
"MBEDTLS_SSL_ALL_ALERT_MESSAGES", "MBEDTLS_SSL_ALL_ALERT_MESSAGES",
#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
...@@ -453,6 +498,9 @@ static const char *features[] = { ...@@ -453,6 +498,9 @@ static const char *features[] = {
#if defined(MBEDTLS_CIPHER_C) #if defined(MBEDTLS_CIPHER_C)
"MBEDTLS_CIPHER_C", "MBEDTLS_CIPHER_C",
#endif /* MBEDTLS_CIPHER_C */ #endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_CMAC_C)
"MBEDTLS_CMAC_C",
#endif /* MBEDTLS_CMAC_C */
#if defined(MBEDTLS_CTR_DRBG_C) #if defined(MBEDTLS_CTR_DRBG_C)
"MBEDTLS_CTR_DRBG_C", "MBEDTLS_CTR_DRBG_C",
#endif /* MBEDTLS_CTR_DRBG_C */ #endif /* MBEDTLS_CTR_DRBG_C */
......
...@@ -53,10 +53,15 @@ ...@@ -53,10 +53,15 @@
#else #else
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_free free #define mbedtls_free free
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
#define mbedtls_printf printf #define mbedtls_printf printf
#define mbedtls_snprintf snprintf #define mbedtls_snprintf snprintf
#endif
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#endif #endif
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
...@@ -75,6 +80,7 @@ ...@@ -75,6 +80,7 @@
#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 ); }
/* /*
* CertificateSerialNumber ::= INTEGER * CertificateSerialNumber ::= INTEGER
...@@ -474,14 +480,111 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, ...@@ -474,14 +480,111 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
} }
} }
static int x509_parse_int(unsigned char **p, unsigned n, int *res){ static int x509_parse_int( unsigned char **p, size_t n, int *res )
{
*res = 0; *res = 0;
for( ; n > 0; --n ){
if( ( **p < '0') || ( **p > '9' ) ) return MBEDTLS_ERR_X509_INVALID_DATE; for( ; n > 0; --n )
{
if( ( **p < '0') || ( **p > '9' ) )
return ( MBEDTLS_ERR_X509_INVALID_DATE );
*res *= 10; *res *= 10;
*res += (*(*p)++ - '0'); *res += ( *(*p)++ - '0' );
} }
return 0;
return( 0 );
}
static int x509_date_is_valid(const mbedtls_x509_time *t)
{
int ret = MBEDTLS_ERR_X509_INVALID_DATE;
CHECK_RANGE( 0, 9999, t->year );
CHECK_RANGE( 0, 23, t->hour );
CHECK_RANGE( 0, 59, t->min );
CHECK_RANGE( 0, 59, t->sec );
switch( t->mon )
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
CHECK_RANGE( 1, 31, t->day );
break;
case 4: case 6: case 9: case 11:
CHECK_RANGE( 1, 30, t->day );
break;
case 2:
CHECK_RANGE( 1, 28 + (t->year % 4 == 0), t->day );
break;
default:
return( ret );
}
return( 0 );
}
/*
* Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
* field.
*/
static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
mbedtls_x509_time *tm )
{
int ret;
/*
* Minimum length is 10 or 12 depending on yearlen
*/
if ( len < yearlen + 8 )
return ( MBEDTLS_ERR_X509_INVALID_DATE );
len -= yearlen + 8;
/*
* Parse year, month, day, hour, minute
*/
CHECK( x509_parse_int( p, yearlen, &tm->year ) );
if ( 2 == yearlen )
{
if ( tm->year < 50 )
tm->year += 100;
tm->year += 1900;
}
CHECK( x509_parse_int( p, 2, &tm->mon ) );
CHECK( x509_parse_int( p, 2, &tm->day ) );
CHECK( x509_parse_int( p, 2, &tm->hour ) );
CHECK( x509_parse_int( p, 2, &tm->min ) );
/*
* Parse seconds if present
*/
if ( len >= 2 )
{
CHECK( x509_parse_int( p, 2, &tm->sec ) );
len -= 2;
}
else
return ( MBEDTLS_ERR_X509_INVALID_DATE );
/*
* Parse trailing 'Z' if present
*/
if ( 1 == len && 'Z' == **p )
{
(*p)++;
len--;
}
/*
* We should have parsed all characters at this point
*/
if ( 0 != len )
return ( MBEDTLS_ERR_X509_INVALID_DATE );
CHECK( x509_date_is_valid( tm ) );
return ( 0 );
} }
/* /*
...@@ -490,10 +593,10 @@ static int x509_parse_int(unsigned char **p, unsigned n, int *res){ ...@@ -490,10 +593,10 @@ static int x509_parse_int(unsigned char **p, unsigned n, int *res){
* generalTime GeneralizedTime } * generalTime GeneralizedTime }
*/ */
int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
mbedtls_x509_time *time ) mbedtls_x509_time *tm )
{ {
int ret; int ret;
size_t len; size_t len, year_len;
unsigned char tag; unsigned char tag;
if( ( end - *p ) < 1 ) if( ( end - *p ) < 1 )
...@@ -503,67 +606,38 @@ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, ...@@ -503,67 +606,38 @@ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
tag = **p; tag = **p;
if( tag == MBEDTLS_ASN1_UTC_TIME ) if( tag == MBEDTLS_ASN1_UTC_TIME )
{ year_len = 2;
(*p)++;
ret = mbedtls_asn1_get_len( p, end, &len );
if( ret != 0 )
return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
CHECK( x509_parse_int( p, 2, &time->year ) );
CHECK( x509_parse_int( p, 2, &time->mon ) );
CHECK( x509_parse_int( p, 2, &time->day ) );
CHECK( x509_parse_int( p, 2, &time->hour ) );
CHECK( x509_parse_int( p, 2, &time->min ) );
if( len > 10 )
CHECK( x509_parse_int( p, 2, &time->sec ) );
if( len > 12 && *(*p)++ != 'Z' )
return( MBEDTLS_ERR_X509_INVALID_DATE );
time->year += 100 * ( time->year < 50 );
time->year += 1900;
return( 0 );
}
else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
{ year_len = 4;
(*p)++;
ret = mbedtls_asn1_get_len( p, end, &len );
if( ret != 0 )
return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
CHECK( x509_parse_int( p, 4, &time->year ) );
CHECK( x509_parse_int( p, 2, &time->mon ) );
CHECK( x509_parse_int( p, 2, &time->day ) );
CHECK( x509_parse_int( p, 2, &time->hour ) );
CHECK( x509_parse_int( p, 2, &time->min ) );
if( len > 12 )
CHECK( x509_parse_int( p, 2, &time->sec ) );
if( len > 14 && *(*p)++ != 'Z' )
return( MBEDTLS_ERR_X509_INVALID_DATE );
return( 0 );
}
else else
return( MBEDTLS_ERR_X509_INVALID_DATE + return( MBEDTLS_ERR_X509_INVALID_DATE +
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
(*p)++;
ret = mbedtls_asn1_get_len( p, end, &len );
if( ret != 0 )
return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
return x509_parse_time( p, len, year_len, tm );
} }
int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
{ {
int ret; int ret;
size_t len; size_t len;
int tag_type;
if( ( end - *p ) < 1 ) if( ( end - *p ) < 1 )
return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
MBEDTLS_ERR_ASN1_OUT_OF_DATA ); MBEDTLS_ERR_ASN1_OUT_OF_DATA );
sig->tag = **p; tag_type = **p;
if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
sig->tag = tag_type;
sig->len = len; sig->len = len;
sig->p = *p; sig->p = *p;
...@@ -622,7 +696,7 @@ int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x50 ...@@ -622,7 +696,7 @@ int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x50
/* /*
* X.509 Extensions (No parsing of extensions, pointer should * X.509 Extensions (No parsing of extensions, pointer should
* be either manually updated or extensions should be parsed! * be either manually updated or extensions should be parsed!)
*/ */
int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *ext, int tag ) mbedtls_x509_buf *ext, int tag )
...@@ -843,7 +917,7 @@ static int x509_get_current_time( mbedtls_x509_time *now ) ...@@ -843,7 +917,7 @@ static int x509_get_current_time( mbedtls_x509_time *now )
static int x509_get_current_time( mbedtls_x509_time *now ) static int x509_get_current_time( mbedtls_x509_time *now )
{ {
struct tm *lt; struct tm *lt;
time_t tt; mbedtls_time_t tt;
int ret = 0; int ret = 0;
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
...@@ -851,7 +925,7 @@ static int x509_get_current_time( mbedtls_x509_time *now ) ...@@ -851,7 +925,7 @@ static int x509_get_current_time( mbedtls_x509_time *now )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif #endif
tt = time( NULL ); tt = mbedtls_time( NULL );
lt = gmtime( &tt ); lt = gmtime( &tt );
if( lt == NULL ) if( lt == NULL )
...@@ -961,7 +1035,7 @@ int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) ...@@ -961,7 +1035,7 @@ int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
*/ */
int mbedtls_x509_self_test( int verbose ) int mbedtls_x509_self_test( int verbose )
{ {
#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
int ret; int ret;
uint32_t flags; uint32_t flags;
mbedtls_x509_crt cacert; mbedtls_x509_crt cacert;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "mbedtls/x509.h" #include "mbedtls/x509.h"
#include "mbedtls/asn1write.h" #include "mbedtls/asn1write.h"
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#include "c_types.h"
#include <string.h> #include <string.h>
typedef struct { typedef struct {
...@@ -41,7 +41,7 @@ typedef struct { ...@@ -41,7 +41,7 @@ typedef struct {
#define ADD_STRLEN( s ) s, sizeof( s ) - 1 #define ADD_STRLEN( s ) s, sizeof( s ) - 1
static const x509_attr_descriptor_t x509_attrs[] ICACHE_RODATA_ATTR STORE_ATTR = static const x509_attr_descriptor_t x509_attrs[] =
{ {
{ ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN },
{ ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN },
......
...@@ -352,14 +352,14 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, ...@@ -352,14 +352,14 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
return( ret ); return( ret );
} }
crl->version++; if( crl->version < 0 || crl->version > 1 )
if( crl->version > 2 )
{ {
mbedtls_x509_crl_free( crl ); mbedtls_x509_crl_free( crl );
return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
} }
crl->version++;
if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1,
&crl->sig_md, &crl->sig_pk, &crl->sig_md, &crl->sig_pk,
&crl->sig_opts ) ) != 0 ) &crl->sig_opts ) ) != 0 )
...@@ -502,14 +502,15 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s ...@@ -502,14 +502,15 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s
{ {
mbedtls_pem_init( &pem ); 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
if( buflen == 0 || buf[buflen - 1] != '\0' ) // string
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; if( buflen == 0 || buf[buflen - 1] != '\0' )
else ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
ret = mbedtls_pem_read_buffer( &pem, else
"-----BEGIN X509 CRL-----", ret = mbedtls_pem_read_buffer( &pem,
"-----END X509 CRL-----", "-----BEGIN X509 CRL-----",
buf, NULL, 0, &use_len ); "-----END X509 CRL-----",
buf, NULL, 0, &use_len );
if( ret == 0 ) if( ret == 0 )
{ {
...@@ -524,16 +525,17 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s ...@@ -524,16 +525,17 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s
if( ( ret = mbedtls_x509_crl_parse_der( chain, if( ( ret = mbedtls_x509_crl_parse_der( chain,
pem.buf, pem.buflen ) ) != 0 ) pem.buf, pem.buflen ) ) != 0 )
{ {
mbedtls_pem_free( &pem );
return( ret ); return( ret );
} }
mbedtls_pem_free( &pem );
} }
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) else if( is_pem )
{ {
mbedtls_pem_free( &pem ); mbedtls_pem_free( &pem );
return( ret ); return( ret );
} }
mbedtls_pem_free( &pem );
} }
/* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
* And a valid CRL cannot be less than 1 byte anyway. */ * And a valid CRL cannot be less than 1 byte anyway. */
......
...@@ -83,33 +83,28 @@ static void mbedtls_zeroize( void *v, size_t n ) { ...@@ -83,33 +83,28 @@ static void mbedtls_zeroize( void *v, size_t n ) {
/* /*
* Default profile * Default profile
*/ */
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default ICACHE_RODATA_ATTR = const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
{ {
/* Hashes from SHA-1 and above */ #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
/* Allow SHA-1 (weak, but still safe in controlled environments) */
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | #endif
/* Only SHA-2 hashes */
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
0xFFFFFFF, /* Any PK alg */ 0xFFFFFFF, /* Any PK alg */
0xFFFFFFF, /* Any curve */ 0xFFFFFFF, /* Any curve */
#if defined(ESP8266_PLATFORM)
512,
#else
2048, 2048,
#endif
}; };
/* /*
* Next-default profile * Next-default profile
*/ */
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next ICACHE_RODATA_ATTR = const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
{ {
/* Hashes from SHA-256 and above */ /* Hashes from SHA-256 and above */
#if defined(ESP8266_PLATFORM)
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
#endif
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
...@@ -126,22 +121,15 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next ICACHE_RODATA_ATTR ...@@ -126,22 +121,15 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next ICACHE_RODATA_ATTR
#else #else
0, 0,
#endif #endif
#if defined(ESP8266_PLATFORM)
512,
#else
2048, 2048,
#endif
}; };
/* /*
* NSA Suite B Profile * NSA Suite B Profile
*/ */
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb ICACHE_RODATA_ATTR = const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
{ {
/* Only SHA-256 and 384 */ /* Only SHA-256 and 384 */
#if defined(ESP8266_PLATFORM)
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
#endif
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
/* Only ECDSA */ /* Only ECDSA */
...@@ -530,9 +518,6 @@ static int x509_get_subject_alt_name( unsigned char **p, ...@@ -530,9 +518,6 @@ static int x509_get_subject_alt_name( unsigned char **p,
/* /*
* X.509 v3 extensions * X.509 v3 extensions
* *
* TODO: Perform all of the basic constraints tests required by the RFC
* TODO: Set values for undetected extensions to a sane default?
*
*/ */
static int x509_get_crt_ext( unsigned char **p, static int x509_get_crt_ext( unsigned char **p,
const unsigned char *end, const unsigned char *end,
...@@ -694,14 +679,9 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * ...@@ -694,14 +679,9 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *
if( crt == NULL || buf == NULL ) if( crt == NULL || buf == NULL )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
p = mbedtls_calloc( 1, len = buflen ); // Use the original buffer until we figure out actual length
if( p == NULL ) p = (unsigned char*) buf;
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); len = buflen;
memcpy( p, buf, buflen );
crt->raw.p = p;
crt->raw.len = len;
end = p + len; end = p + len;
/* /*
...@@ -725,6 +705,18 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * ...@@ -725,6 +705,18 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *
} }
crt_end = p + len; crt_end = p + len;
// Create and populate a new buffer for the raw field
crt->raw.len = crt_end - buf;
crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
if( p == NULL )
return( MBEDTLS_ERR_X509_ALLOC_FAILED );
memcpy( p, buf, crt->raw.len );
// Direct pointers to the new buffer
p += crt->raw.len - len;
end = crt_end = p + len;
/* /*
* TBSCertificate ::= SEQUENCE { * TBSCertificate ::= SEQUENCE {
*/ */
...@@ -756,14 +748,14 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * ...@@ -756,14 +748,14 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *
return( ret ); return( ret );
} }
crt->version++; if( crt->version < 0 || crt->version > 2 )
if( crt->version > 3 )
{ {
mbedtls_x509_crt_free( crt ); mbedtls_x509_crt_free( crt );
return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
} }
crt->version++;
if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
&crt->sig_md, &crt->sig_pk, &crt->sig_md, &crt->sig_pk,
&crt->sig_opts ) ) != 0 ) &crt->sig_opts ) ) != 0 )
...@@ -979,8 +971,10 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu ...@@ -979,8 +971,10 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu
*/ */
int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen )
{ {
#if defined(MBEDTLS_PEM_PARSE_C)
int success = 0, first_error = 0, total_failed = 0; int success = 0, first_error = 0, total_failed = 0;
int buf_format = MBEDTLS_X509_FORMAT_DER; int buf_format = MBEDTLS_X509_FORMAT_DER;
#endif
/* /*
* Check for valid input * Check for valid input
...@@ -998,10 +992,12 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s ...@@ -998,10 +992,12 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s
{ {
buf_format = MBEDTLS_X509_FORMAT_PEM; buf_format = MBEDTLS_X509_FORMAT_PEM;
} }
#endif
if( buf_format == MBEDTLS_X509_FORMAT_DER ) if( buf_format == MBEDTLS_X509_FORMAT_DER )
return mbedtls_x509_crt_parse_der( chain, buf, buflen ); return mbedtls_x509_crt_parse_der( chain, buf, buflen );
#else
return mbedtls_x509_crt_parse_der( chain, buf, buflen );
#endif
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
if( buf_format == MBEDTLS_X509_FORMAT_PEM ) if( buf_format == MBEDTLS_X509_FORMAT_PEM )
...@@ -1074,7 +1070,6 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s ...@@ -1074,7 +1070,6 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s
success = 1; success = 1;
} }
} }
#endif /* MBEDTLS_PEM_PARSE_C */
if( success ) if( success )
return( total_failed ); return( total_failed );
...@@ -1082,6 +1077,7 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s ...@@ -1082,6 +1077,7 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s
return( first_error ); return( first_error );
else else
return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
#endif /* MBEDTLS_PEM_PARSE_C */
} }
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
...@@ -1128,7 +1124,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) ...@@ -1128,7 +1124,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
p = filename + len; p = filename + len;
filename[len++] = '*'; filename[len++] = '*';
w_ret = MultiByteToWideChar( CP_ACP, 0, filename, len, szDir, w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
MAX_PATH - 3 ); MAX_PATH - 3 );
if( w_ret == 0 ) if( w_ret == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
...@@ -1150,7 +1146,10 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) ...@@ -1150,7 +1146,10 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
p, (int) len - 1, p, (int) len - 1,
NULL, NULL ); NULL, NULL );
if( w_ret == 0 ) if( w_ret == 0 )
return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); {
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
goto cleanup;
}
w_ret = mbedtls_x509_crt_parse_file( chain, filename ); w_ret = mbedtls_x509_crt_parse_file( chain, filename );
if( w_ret < 0 ) if( w_ret < 0 )
...@@ -1163,32 +1162,39 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) ...@@ -1163,32 +1162,39 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
if( GetLastError() != ERROR_NO_MORE_FILES ) if( GetLastError() != ERROR_NO_MORE_FILES )
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
cleanup:
FindClose( hFind ); FindClose( hFind );
#else /* _WIN32 */ #else /* _WIN32 */
int t_ret; int t_ret;
int snp_ret;
struct stat sb; struct stat sb;
struct dirent *entry; struct dirent *entry;
char entry_name[255]; char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
DIR *dir = opendir( path ); DIR *dir = opendir( path );
if( dir == NULL ) if( dir == NULL )
return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
#if defined(MBEDTLS_THREADING_PTHREAD) #if defined(MBEDTLS_THREADING_C)
if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
{ {
closedir( dir ); closedir( dir );
return( ret ); return( ret );
} }
#endif #endif /* MBEDTLS_THREADING_C */
while( ( entry = readdir( dir ) ) != NULL ) while( ( entry = readdir( dir ) ) != NULL )
{ {
mbedtls_snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name ); snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
"%s/%s", path, entry->d_name );
if( stat( entry_name, &sb ) == -1 ) if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
{
ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
goto cleanup;
}
else if( stat( entry_name, &sb ) == -1 )
{ {
closedir( dir );
ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
goto cleanup; goto cleanup;
} }
...@@ -1204,13 +1210,14 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) ...@@ -1204,13 +1210,14 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
else else
ret += t_ret; ret += t_ret;
} }
closedir( dir );
cleanup: cleanup:
#if defined(MBEDTLS_THREADING_PTHREAD) closedir( dir );
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
#endif #endif /* MBEDTLS_THREADING_C */
#endif /* _WIN32 */ #endif /* _WIN32 */
...@@ -1363,6 +1370,14 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, ...@@ -1363,6 +1370,14 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
p = buf; p = buf;
n = size; n = size;
if( NULL == crt )
{
ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
MBEDTLS_X509_SAFE_SNPRINTF;
return( (int) ( size - n ) );
}
ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
prefix, crt->version ); prefix, crt->version );
MBEDTLS_X509_SAFE_SNPRINTF; MBEDTLS_X509_SAFE_SNPRINTF;
...@@ -1481,7 +1496,6 @@ struct x509_crt_verify_string { ...@@ -1481,7 +1496,6 @@ struct x509_crt_verify_string {
const char *string; const char *string;
}; };
#if 0
static const struct x509_crt_verify_string x509_crt_verify_strings[] = { static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
{ MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
{ MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
...@@ -1505,31 +1519,6 @@ static const struct x509_crt_verify_string x509_crt_verify_strings[] = { ...@@ -1505,31 +1519,6 @@ static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
{ MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
{ 0, NULL } { 0, NULL }
}; };
#else
static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
{ MBEDTLS_X509_BADCERT_EXPIRED, NULL },
{ MBEDTLS_X509_BADCERT_REVOKED, NULL },
{ MBEDTLS_X509_BADCERT_CN_MISMATCH, NULL },
{ MBEDTLS_X509_BADCERT_NOT_TRUSTED, NULL },
{ MBEDTLS_X509_BADCRL_NOT_TRUSTED, NULL },
{ MBEDTLS_X509_BADCRL_EXPIRED, NULL },
{ MBEDTLS_X509_BADCERT_MISSING, NULL },
{ MBEDTLS_X509_BADCERT_SKIP_VERIFY, NULL },
{ MBEDTLS_X509_BADCERT_OTHER, NULL },
{ MBEDTLS_X509_BADCERT_FUTURE, NULL },
{ MBEDTLS_X509_BADCRL_FUTURE, NULL },
{ MBEDTLS_X509_BADCERT_KEY_USAGE, NULL },
{ MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, NULL },
{ MBEDTLS_X509_BADCERT_NS_CERT_TYPE, NULL },
{ MBEDTLS_X509_BADCERT_BAD_MD, NULL },
{ MBEDTLS_X509_BADCERT_BAD_PK, NULL },
{ MBEDTLS_X509_BADCERT_BAD_KEY, NULL },
{ MBEDTLS_X509_BADCRL_BAD_MD, NULL },
{ MBEDTLS_X509_BADCRL_BAD_PK, NULL },
{ MBEDTLS_X509_BADCRL_BAD_KEY, NULL },
{ 0, NULL }
};
#endif
int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
uint32_t flags ) uint32_t flags )
...@@ -1640,7 +1629,8 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509 ...@@ -1640,7 +1629,8 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509
} }
/* /*
* Check that the given certificate is valid according to the CRL. * Check that the given certificate is not revoked according to the CRL.
* Skip validation is no CRL for the given CA is present.
*/ */
static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
mbedtls_x509_crl *crl_list, mbedtls_x509_crl *crl_list,
...@@ -1653,12 +1643,6 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, ...@@ -1653,12 +1643,6 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
if( ca == NULL ) if( ca == NULL )
return( flags ); return( flags );
/*
* TODO: What happens if no CRL is present?
* Suggestion: Revocation state should be unknown if no CRL is present.
* For backwards compatibility this is not yet implemented.
*/
while( crl_list != NULL ) while( crl_list != NULL )
{ {
if( crl_list->version == 0 || if( crl_list->version == 0 ||
...@@ -1926,6 +1910,7 @@ static int x509_crt_verify_top( ...@@ -1926,6 +1910,7 @@ static int x509_crt_verify_top(
int check_path_cnt; int check_path_cnt;
unsigned char hash[MBEDTLS_MD_MAX_SIZE]; unsigned char hash[MBEDTLS_MD_MAX_SIZE];
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
mbedtls_x509_crt *future_past_ca = NULL;
if( mbedtls_x509_time_is_past( &child->valid_to ) ) if( mbedtls_x509_time_is_past( &child->valid_to ) )
*flags |= MBEDTLS_X509_BADCERT_EXPIRED; *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
...@@ -1987,6 +1972,20 @@ static int x509_crt_verify_top( ...@@ -1987,6 +1972,20 @@ static int x509_crt_verify_top(
continue; continue;
} }
if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ||
mbedtls_x509_time_is_future( &trust_ca->valid_from ) )
{
if ( future_past_ca == NULL )
future_past_ca = trust_ca;
continue;
}
break;
}
if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL )
{
/* /*
* Top of chain is signed by a trusted CA * Top of chain is signed by a trusted CA
*/ */
...@@ -1994,8 +1993,6 @@ static int x509_crt_verify_top( ...@@ -1994,8 +1993,6 @@ static int x509_crt_verify_top(
if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 )
*flags |= MBEDTLS_X509_BADCERT_BAD_KEY; *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
break;
} }
/* /*
...@@ -2064,8 +2061,8 @@ static int x509_crt_verify_child( ...@@ -2064,8 +2061,8 @@ static int x509_crt_verify_child(
/* path_cnt is 0 for the first intermediate CA */ /* path_cnt is 0 for the first intermediate CA */
if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
{ {
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; /* return immediately as the goal is to avoid unbounded recursion */
return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); return( MBEDTLS_ERR_X509_FATAL_ERROR );
} }
if( mbedtls_x509_time_is_past( &child->valid_to ) ) if( mbedtls_x509_time_is_past( &child->valid_to ) )
...@@ -2209,11 +2206,14 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, ...@@ -2209,11 +2206,14 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
mbedtls_x509_sequence *cur = NULL; mbedtls_x509_sequence *cur = NULL;
mbedtls_pk_type_t pk_type; mbedtls_pk_type_t pk_type;
if( profile == NULL )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
*flags = 0; *flags = 0;
if( profile == NULL )
{
ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
goto exit;
}
if( cn != NULL ) if( cn != NULL )
{ {
name = &crt->subject; name = &crt->subject;
...@@ -2287,7 +2287,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, ...@@ -2287,7 +2287,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
ret = x509_crt_verify_top( crt, parent, ca_crl, profile, ret = x509_crt_verify_top( crt, parent, ca_crl, profile,
pathlen, selfsigned, flags, f_vrfy, p_vrfy ); pathlen, selfsigned, flags, f_vrfy, p_vrfy );
if( ret != 0 ) if( ret != 0 )
return( ret ); goto exit;
} }
else else
{ {
...@@ -2302,17 +2302,30 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, ...@@ -2302,17 +2302,30 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile,
pathlen, selfsigned, flags, f_vrfy, p_vrfy ); pathlen, selfsigned, flags, f_vrfy, p_vrfy );
if( ret != 0 ) if( ret != 0 )
return( ret ); goto exit;
} }
else else
{ {
ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile,
pathlen, selfsigned, flags, f_vrfy, p_vrfy ); pathlen, selfsigned, flags, f_vrfy, p_vrfy );
if( ret != 0 ) if( ret != 0 )
return( ret ); goto exit;
} }
} }
exit:
/* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
* the SSL module for authmode optional, but non-zero return from the
* callback means a fatal error so it shouldn't be ignored */
if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
ret = MBEDTLS_ERR_X509_FATAL_ERROR;
if( ret != 0 )
{
*flags = (uint32_t) -1;
return( ret );
}
if( *flags != 0 ) if( *flags != 0 )
return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
......
...@@ -104,7 +104,7 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, ...@@ -104,7 +104,7 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
/* /*
* Check for valid input * Check for valid input
*/ */
if( csr == NULL || buf == NULL ) if( csr == NULL || buf == NULL || buflen == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
mbedtls_x509_csr_init( csr ); mbedtls_x509_csr_init( csr );
...@@ -168,14 +168,14 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, ...@@ -168,14 +168,14 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
return( ret ); return( ret );
} }
csr->version++; if( csr->version != 0 )
if( csr->version != 1 )
{ {
mbedtls_x509_csr_free( csr ); mbedtls_x509_csr_free( csr );
return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
} }
csr->version++;
/* /*
* subject Name * subject Name
*/ */
...@@ -207,6 +207,13 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, ...@@ -207,6 +207,13 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
/* /*
* attributes [0] Attributes * attributes [0] Attributes
*
* The list of possible attributes is open-ended, though RFC 2985
* (PKCS#9) defines a few in section 5.4. We currently don't support any,
* so we just ignore them. This is a safe thing to do as the worst thing
* that could happen is that we issue a certificate that does not match
* the requester's expectations - this cannot cause a violation of our
* signature policies.
*/ */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
...@@ -214,7 +221,6 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, ...@@ -214,7 +221,6 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
mbedtls_x509_csr_free( csr ); mbedtls_x509_csr_free( csr );
return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
} }
// TODO Parse Attributes / extension requests
p += len; p += len;
...@@ -259,8 +265,8 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, ...@@ -259,8 +265,8 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
*/ */
int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
{ {
int ret;
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
int ret;
size_t use_len; size_t use_len;
mbedtls_pem_context pem; mbedtls_pem_context pem;
#endif #endif
...@@ -268,14 +274,14 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz ...@@ -268,14 +274,14 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
/* /*
* Check for valid input * Check for valid input
*/ */
if( csr == NULL || buf == NULL ) if( csr == NULL || buf == NULL || buflen == 0 )
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 ); 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( buflen == 0 || buf[buflen - 1] != '\0' ) if( buf[buflen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else else
ret = mbedtls_pem_read_buffer( &pem, ret = mbedtls_pem_read_buffer( &pem,
......
...@@ -264,7 +264,7 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, ...@@ -264,7 +264,7 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
} }
static int x509_write_time( unsigned char **p, unsigned char *start, static int x509_write_time( unsigned char **p, unsigned char *start,
const char *time, size_t size ) const char *t, size_t size )
{ {
int ret; int ret;
size_t len = 0; size_t len = 0;
...@@ -272,10 +272,10 @@ static int x509_write_time( unsigned char **p, unsigned char *start, ...@@ -272,10 +272,10 @@ static int x509_write_time( unsigned char **p, unsigned char *start,
/* /*
* write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
*/ */
if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
{ {
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) time + 2, (const unsigned char *) t + 2,
size - 2 ) ); size - 2 ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
...@@ -283,7 +283,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start, ...@@ -283,7 +283,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start,
else else
{ {
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) time, (const unsigned char *) t,
size ) ); size ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
...@@ -413,6 +413,9 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, ...@@ -413,6 +413,9 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf,
MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
sig_oid, sig_oid_len, sig, sig_len ) ); sig_oid, sig_oid_len, sig, sig_len ) );
if( len > (size_t)( c2 - buf ) )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
c2 -= len; c2 -= len;
memcpy( c2, c, len ); memcpy( c2, c, len );
......
...@@ -213,6 +213,9 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s ...@@ -213,6 +213,9 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
sig_oid, sig_oid_len, sig, sig_len ) ); sig_oid, sig_oid_len, sig, sig_len ) );
if( len > (size_t)( c2 - buf ) )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
c2 -= len; c2 -= len;
memcpy( c2, c, len ); memcpy( c2, c, len );
......
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