- Initial bare version of TLS 1.2
This commit is contained in:
parent
570267f01a
commit
1ef83d66dd
@ -34,6 +34,7 @@
|
||||
#include "rsa.h"
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "sha2.h"
|
||||
#include "x509.h"
|
||||
#include "config.h"
|
||||
|
||||
@ -90,6 +91,7 @@
|
||||
#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */
|
||||
#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */
|
||||
#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */
|
||||
#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */
|
||||
|
||||
#define SSL_IS_CLIENT 0
|
||||
#define SSL_IS_SERVER 1
|
||||
@ -130,6 +132,19 @@
|
||||
#define SSL_RSA_CAMELLIA_256_SHA 0x84
|
||||
#define SSL_EDH_RSA_CAMELLIA_256_SHA 0x88
|
||||
|
||||
/*
|
||||
* Supported Signature and Hash algorithms (For TLS 1.2)
|
||||
*/
|
||||
#define SSL_HASH_NONE 0
|
||||
#define SSL_HASH_MD5 1
|
||||
#define SSL_HASH_SHA1 2
|
||||
#define SSL_HASH_SHA224 3
|
||||
#define SSL_HASH_SHA256 4
|
||||
#define SSL_HASH_SHA384 5
|
||||
#define SSL_HASH_SHA512 6
|
||||
|
||||
#define SSL_SIG_RSA 1
|
||||
|
||||
/*
|
||||
* Message, alert and handshake types
|
||||
*/
|
||||
@ -310,6 +325,12 @@ struct _ssl_context
|
||||
dhm_context dhm_ctx; /*!< DHM key exchange */
|
||||
md5_context fin_md5; /*!< Finished MD5 checksum */
|
||||
sha1_context fin_sha1; /*!< Finished SHA-1 checksum */
|
||||
sha2_context fin_sha2; /*!< Finished SHA-256 checksum */
|
||||
|
||||
void (*calc_finished)(ssl_context *, unsigned char *, int);
|
||||
int (*tls_prf)(unsigned char *, size_t, char *,
|
||||
unsigned char *, size_t,
|
||||
unsigned char *, size_t);
|
||||
|
||||
int do_crypt; /*!< en(de)cryption flag */
|
||||
int *ciphersuites; /*!< allowed ciphersuites */
|
||||
@ -578,7 +599,8 @@ int ssl_set_hostname( ssl_context *ssl, const char *hostname );
|
||||
* \param ssl SSL context
|
||||
* \param major Major version number (only SSL_MAJOR_VERSION_3 supported)
|
||||
* \param minor Minor version number (SSL_MINOR_VERSION_0,
|
||||
* SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2 supported)
|
||||
* SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
|
||||
* SSL_MINOR_VERSION_3 supported)
|
||||
*/
|
||||
void ssl_set_max_version( ssl_context *ssl, int major, int minor );
|
||||
|
||||
|
@ -113,12 +113,6 @@ int dhm_read_params( dhm_context *ctx,
|
||||
if( end - *p < 2 )
|
||||
return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
|
||||
|
||||
n = ( (*p)[0] << 8 ) | (*p)[1];
|
||||
(*p) += 2;
|
||||
|
||||
if( end != *p + n )
|
||||
return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ static int ssl_write_client_hello( ssl_context *ssl )
|
||||
if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 )
|
||||
{
|
||||
ssl->max_major_ver = SSL_MAJOR_VERSION_3;
|
||||
ssl->max_minor_ver = SSL_MINOR_VERSION_2;
|
||||
ssl->max_minor_ver = SSL_MINOR_VERSION_3;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -335,9 +335,11 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
int ret;
|
||||
size_t n;
|
||||
unsigned char *p, *end;
|
||||
unsigned char hash[36];
|
||||
unsigned char hash[64];
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
int hash_id = SIG_RSA_RAW;
|
||||
unsigned int hashlen;
|
||||
#endif
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
|
||||
@ -376,6 +378,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 );
|
||||
|
||||
/*
|
||||
* Ephemeral DH parameters:
|
||||
*
|
||||
@ -389,6 +393,63 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
end = ssl->in_msg + ssl->in_hslen;
|
||||
|
||||
if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) );
|
||||
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
}
|
||||
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
// TODO TLS 1.2 Check if valid hash and sig
|
||||
if( p[1] != SSL_SIG_RSA )
|
||||
{
|
||||
SSL_DEBUG_MSG( 2, ( "Server used unsupported SignatureAlgorithm %d", p[1] ) );
|
||||
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
}
|
||||
|
||||
switch( p[0] )
|
||||
{
|
||||
#if defined(POLARSSL_MD5_C)
|
||||
case SSL_HASH_MD5:
|
||||
hash_id = SIG_RSA_MD5;
|
||||
break;
|
||||
#endif
|
||||
#if defined(POLARSSL_SHA1_C)
|
||||
case SSL_HASH_SHA1:
|
||||
hash_id = SIG_RSA_SHA1;
|
||||
break;
|
||||
#endif
|
||||
#if defined(POLARSSL_SHA2_C)
|
||||
case SSL_HASH_SHA224:
|
||||
hash_id = SIG_RSA_SHA224;
|
||||
break;
|
||||
case SSL_HASH_SHA256:
|
||||
hash_id = SIG_RSA_SHA256;
|
||||
break;
|
||||
#endif
|
||||
#if defined(POLARSSL_SHA4_C)
|
||||
case SSL_HASH_SHA384:
|
||||
hash_id = SIG_RSA_SHA384;
|
||||
break;
|
||||
case SSL_HASH_SHA512:
|
||||
hash_id = SIG_RSA_SHA512;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
SSL_DEBUG_MSG( 2, ( "Server used unsupported HashAlgorithm %d", p[1] ) );
|
||||
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
}
|
||||
|
||||
p += 2;
|
||||
}
|
||||
|
||||
n = ( p[0] << 8 ) | p[1];
|
||||
p += 2;
|
||||
|
||||
if( end != p + n )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
@ -410,35 +471,61 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
|
||||
SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
|
||||
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque md5_hash[16];
|
||||
* opaque sha_hash[20];
|
||||
* };
|
||||
*
|
||||
* md5_hash
|
||||
* MD5(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
* sha_hash
|
||||
* SHA(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
*/
|
||||
n = ssl->in_hslen - ( end - p ) - 6;
|
||||
if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque md5_hash[16];
|
||||
* opaque sha_hash[20];
|
||||
* };
|
||||
*
|
||||
* md5_hash
|
||||
* MD5(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
* sha_hash
|
||||
* SHA(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
*/
|
||||
n = ssl->in_hslen - ( end - p ) - 6;
|
||||
|
||||
md5_starts( &md5 );
|
||||
md5_update( &md5, ssl->randbytes, 64 );
|
||||
md5_update( &md5, ssl->in_msg + 4, n );
|
||||
md5_finish( &md5, hash );
|
||||
md5_starts( &md5 );
|
||||
md5_update( &md5, ssl->randbytes, 64 );
|
||||
md5_update( &md5, ssl->in_msg + 4, n );
|
||||
md5_finish( &md5, hash );
|
||||
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->randbytes, 64 );
|
||||
sha1_update( &sha1, ssl->in_msg + 4, n );
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->randbytes, 64 );
|
||||
sha1_update( &sha1, ssl->in_msg + 4, n );
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
|
||||
SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
|
||||
hash_id = SIG_RSA_RAW;
|
||||
hashlen = 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = ssl->in_hslen - ( end - p ) - 8;
|
||||
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque client_random[32];
|
||||
* opaque server_random[32];
|
||||
* ServerDHParams params;
|
||||
* };
|
||||
*/
|
||||
/* TODO TLS1.2 Get Hash algorithm from hash and signature extension! */
|
||||
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->randbytes, 64 );
|
||||
sha1_update( &sha1, ssl->in_msg + 4, n );
|
||||
sha1_finish( &sha1, hash );
|
||||
|
||||
hashlen = 20;
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
|
||||
|
||||
if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
|
||||
SIG_RSA_RAW, 36, hash, p ) ) != 0 )
|
||||
hash_id, hashlen, hash, p ) ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
|
||||
return( ret );
|
||||
@ -643,8 +730,10 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
|
||||
static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
{
|
||||
int ret = 0;
|
||||
size_t n = 0;
|
||||
size_t n = 0, offset = 0;
|
||||
unsigned char hash[36];
|
||||
int hash_id = SIG_RSA_RAW;
|
||||
unsigned int hashlen = 36;
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
|
||||
|
||||
@ -655,6 +744,12 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
hash_id = SIG_RSA_SHA256;
|
||||
hashlen = 32;
|
||||
}
|
||||
|
||||
if( ssl->rsa_key == NULL )
|
||||
{
|
||||
#if defined(POLARSSL_PKCS11_C)
|
||||
@ -680,18 +775,27 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
n = ssl->pkcs11_key->len;
|
||||
#endif /* defined(POLARSSL_PKCS11_C) */
|
||||
|
||||
ssl->out_msg[4] = (unsigned char)( n >> 8 );
|
||||
ssl->out_msg[5] = (unsigned char)( n );
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
// TODO TLS1.2 Base on signature algorithm extension received
|
||||
ssl->out_msg[4] = SSL_HASH_SHA1;
|
||||
ssl->out_msg[5] = SSL_SIG_RSA;
|
||||
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
|
||||
ssl->out_msg[5 + offset] = (unsigned char)( n );
|
||||
|
||||
if( ssl->rsa_key )
|
||||
{
|
||||
ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
|
||||
RSA_PRIVATE, SIG_RSA_RAW,
|
||||
36, hash, ssl->out_msg + 6 );
|
||||
RSA_PRIVATE, hash_id,
|
||||
hashlen, hash, ssl->out_msg + 6 + offset );
|
||||
} else {
|
||||
#if defined(POLARSSL_PKCS11_C)
|
||||
ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, SIG_RSA_RAW,
|
||||
36, hash, ssl->out_msg + 6 );
|
||||
ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, hash_id,
|
||||
hashlen, hash, ssl->out_msg + 6 + offset );
|
||||
#endif /* defined(POLARSSL_PKCS11_C) */
|
||||
}
|
||||
|
||||
@ -701,7 +805,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
ssl->out_msglen = 6 + n;
|
||||
ssl->out_msglen = 6 + n + offset;
|
||||
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
|
||||
ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY;
|
||||
|
||||
|
@ -97,8 +97,8 @@ static int ssl_parse_client_hello( ssl_context *ssl )
|
||||
ssl->max_minor_ver = buf[4];
|
||||
|
||||
ssl->major_ver = SSL_MAJOR_VERSION_3;
|
||||
ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_2 )
|
||||
? buf[4] : SSL_MINOR_VERSION_2;
|
||||
ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_3 )
|
||||
? buf[4] : SSL_MINOR_VERSION_3;
|
||||
|
||||
if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
|
||||
{
|
||||
@ -108,6 +108,7 @@ static int ssl_parse_client_hello( ssl_context *ssl )
|
||||
|
||||
md5_update( &ssl->fin_md5 , buf + 2, n );
|
||||
sha1_update( &ssl->fin_sha1, buf + 2, n );
|
||||
sha2_update( &ssl->fin_sha2, buf + 2, n );
|
||||
|
||||
buf = ssl->in_msg;
|
||||
n = ssl->in_left - 5;
|
||||
@ -228,6 +229,7 @@ static int ssl_parse_client_hello( ssl_context *ssl )
|
||||
|
||||
md5_update( &ssl->fin_md5 , buf, n );
|
||||
sha1_update( &ssl->fin_sha1, buf, n );
|
||||
sha2_update( &ssl->fin_sha2, buf, n );
|
||||
|
||||
/*
|
||||
* SSL layer:
|
||||
@ -263,8 +265,8 @@ static int ssl_parse_client_hello( ssl_context *ssl )
|
||||
}
|
||||
|
||||
ssl->major_ver = SSL_MAJOR_VERSION_3;
|
||||
ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_2 )
|
||||
? buf[5] : SSL_MINOR_VERSION_2;
|
||||
ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_3 )
|
||||
? buf[5] : SSL_MINOR_VERSION_3;
|
||||
|
||||
ssl->max_major_ver = buf[4];
|
||||
ssl->max_minor_ver = buf[5];
|
||||
@ -540,6 +542,8 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
unsigned char hash[36];
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
int hash_id;
|
||||
unsigned int hashlen;
|
||||
#endif
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
|
||||
@ -595,30 +599,55 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
|
||||
SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
|
||||
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque md5_hash[16];
|
||||
* opaque sha_hash[20];
|
||||
* };
|
||||
*
|
||||
* md5_hash
|
||||
* MD5(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
* sha_hash
|
||||
* SHA(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
*/
|
||||
md5_starts( &md5 );
|
||||
md5_update( &md5, ssl->randbytes, 64 );
|
||||
md5_update( &md5, ssl->out_msg + 4, n );
|
||||
md5_finish( &md5, hash );
|
||||
if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque md5_hash[16];
|
||||
* opaque sha_hash[20];
|
||||
* };
|
||||
*
|
||||
* md5_hash
|
||||
* MD5(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
* sha_hash
|
||||
* SHA(ClientHello.random + ServerHello.random
|
||||
* + ServerParams);
|
||||
*/
|
||||
md5_starts( &md5 );
|
||||
md5_update( &md5, ssl->randbytes, 64 );
|
||||
md5_update( &md5, ssl->out_msg + 4, n );
|
||||
md5_finish( &md5, hash );
|
||||
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->randbytes, 64 );
|
||||
sha1_update( &sha1, ssl->out_msg + 4, n );
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->randbytes, 64 );
|
||||
sha1_update( &sha1, ssl->out_msg + 4, n );
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
|
||||
SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
|
||||
hashlen = 36;
|
||||
hash_id = SIG_RSA_RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque client_random[32];
|
||||
* opaque server_random[32];
|
||||
* ServerDHParams params;
|
||||
* };
|
||||
*/
|
||||
/* TODO TLS1.2 Get Hash algorithm from ciphersuite! */
|
||||
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->randbytes, 64 );
|
||||
sha1_update( &sha1, ssl->out_msg + 4, n );
|
||||
sha1_finish( &sha1, hash );
|
||||
|
||||
hashlen = 20;
|
||||
hash_id = SIG_RSA_SHA1;
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
|
||||
|
||||
if ( ssl->rsa_key )
|
||||
rsa_key_len = ssl->rsa_key->len;
|
||||
@ -627,6 +656,15 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
rsa_key_len = ssl->pkcs11_key->len;
|
||||
#endif /* defined(POLARSSL_PKCS11_C) */
|
||||
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
// TODO TLS1.2 Base on signature algorithm extension received
|
||||
ssl->out_msg[4 + n] = SSL_HASH_SHA1;
|
||||
ssl->out_msg[5 + n] = SSL_SIG_RSA;
|
||||
|
||||
n += 2;
|
||||
}
|
||||
|
||||
ssl->out_msg[4 + n] = (unsigned char)( rsa_key_len >> 8 );
|
||||
ssl->out_msg[5 + n] = (unsigned char)( rsa_key_len );
|
||||
|
||||
@ -634,12 +672,12 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
{
|
||||
ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
|
||||
RSA_PRIVATE,
|
||||
SIG_RSA_RAW, 36, hash, ssl->out_msg + 6 + n );
|
||||
hash_id, hashlen, hash, ssl->out_msg + 6 + n );
|
||||
}
|
||||
#if defined(POLARSSL_PKCS11_C)
|
||||
else {
|
||||
ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE,
|
||||
SIG_RSA_RAW, 36, hash, ssl->out_msg + 6 + n );
|
||||
hash_id, hashlen, hash, ssl->out_msg + 6 + n );
|
||||
}
|
||||
#endif /* defined(POLARSSL_PKCS11_C) */
|
||||
|
||||
|
@ -113,6 +113,49 @@ static int tls1_prf( unsigned char *secret, size_t slen, char *label,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int tls_prf_sha256( unsigned char *secret, size_t slen, char *label,
|
||||
unsigned char *random, size_t rlen,
|
||||
unsigned char *dstbuf, size_t dlen )
|
||||
{
|
||||
size_t nb;
|
||||
size_t i, j, k;
|
||||
unsigned char tmp[128];
|
||||
unsigned char h_i[32];
|
||||
|
||||
if( sizeof( tmp ) < 32 + strlen( label ) + rlen )
|
||||
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
nb = strlen( label );
|
||||
memcpy( tmp + 32, label, nb );
|
||||
memcpy( tmp + 32 + nb, random, rlen );
|
||||
nb += rlen;
|
||||
|
||||
/*
|
||||
* Compute P_<hash>(secret, label + random)[0..dlen]
|
||||
*/
|
||||
sha2_hmac( secret, slen, tmp + 32, nb, tmp, 0 );
|
||||
|
||||
for( i = 0; i < dlen; i += 32 )
|
||||
{
|
||||
sha2_hmac( secret, slen, tmp, 32 + nb, h_i, 0 );
|
||||
sha2_hmac( secret, slen, tmp, 32, tmp, 0 );
|
||||
|
||||
k = ( i + 32 > dlen ) ? dlen % 32 : 32;
|
||||
|
||||
for( j = 0; j < k; j++ )
|
||||
dstbuf[i + j] = h_i[j];
|
||||
}
|
||||
|
||||
memset( tmp, 0, sizeof( tmp ) );
|
||||
memset( h_i, 0, sizeof( h_i ) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void ssl_calc_finished_ssl (ssl_context *,unsigned char *,int);
|
||||
static void ssl_calc_finished_tls (ssl_context *,unsigned char *,int);
|
||||
static void ssl_calc_finished_tls1_2(ssl_context *,unsigned char *,int);
|
||||
|
||||
int ssl_derive_keys( ssl_context *ssl )
|
||||
{
|
||||
int i;
|
||||
@ -127,6 +170,24 @@ int ssl_derive_keys( ssl_context *ssl )
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
|
||||
|
||||
/*
|
||||
* Set appropriate PRF function.
|
||||
*/
|
||||
if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
|
||||
ssl->tls_prf = tls1_prf;
|
||||
else
|
||||
ssl->tls_prf = tls_prf_sha256;
|
||||
|
||||
/*
|
||||
* Set appropriate SSL / TLS / TLS1.2 functions
|
||||
*/
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
|
||||
ssl->calc_finished = ssl_calc_finished_ssl;
|
||||
else if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
|
||||
ssl->calc_finished = ssl_calc_finished_tls;
|
||||
else
|
||||
ssl->calc_finished = ssl_calc_finished_tls1_2;
|
||||
|
||||
/*
|
||||
* SSLv3:
|
||||
* master =
|
||||
@ -161,9 +222,9 @@ int ssl_derive_keys( ssl_context *ssl )
|
||||
md5_finish( &md5, ssl->session->master + i * 16 );
|
||||
}
|
||||
}
|
||||
else
|
||||
tls1_prf( ssl->premaster, len, "master secret",
|
||||
ssl->randbytes, 64, ssl->session->master, 48 );
|
||||
else
|
||||
ssl->tls_prf( ssl->premaster, len, "master secret",
|
||||
ssl->randbytes, 64, ssl->session->master, 48 );
|
||||
|
||||
memset( ssl->premaster, 0, sizeof( ssl->premaster ) );
|
||||
}
|
||||
@ -215,8 +276,8 @@ int ssl_derive_keys( ssl_context *ssl )
|
||||
memset( sha1sum, 0, sizeof( sha1sum ) );
|
||||
}
|
||||
else
|
||||
tls1_prf( ssl->session->master, 48, "key expansion",
|
||||
ssl->randbytes, 64, keyblk, 256 );
|
||||
ssl->tls_prf( ssl->session->master, 48, "key expansion",
|
||||
ssl->randbytes, 64, keyblk, 256 );
|
||||
|
||||
SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) );
|
||||
SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 );
|
||||
@ -426,6 +487,7 @@ void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] )
|
||||
{
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
sha2_context sha2;
|
||||
unsigned char pad_1[48];
|
||||
unsigned char pad_2[48];
|
||||
|
||||
@ -433,6 +495,7 @@ void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] )
|
||||
|
||||
memcpy( &md5 , &ssl->fin_md5 , sizeof( md5_context ) );
|
||||
memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
|
||||
memcpy( &sha2, &ssl->fin_sha2, sizeof( sha2_context ) );
|
||||
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
@ -459,11 +522,15 @@ void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] )
|
||||
sha1_update( &sha1, hash + 16, 20 );
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
}
|
||||
else /* TLSv1 */
|
||||
else if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) /* TLSv1 */
|
||||
{
|
||||
md5_finish( &md5, hash );
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
}
|
||||
else
|
||||
{
|
||||
sha2_finish( &sha2, hash );
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
|
||||
SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
|
||||
@ -630,10 +697,10 @@ static int ssl_encrypt_buf( ssl_context *ssl )
|
||||
enc_msg = ssl->out_msg;
|
||||
|
||||
/*
|
||||
* Prepend per-record IV for block cipher in TLS v1.1 as per
|
||||
* Method 1 (6.2.3.2. in RFC4346)
|
||||
* Prepend per-record IV for block cipher in TLS v1.1 and up as per
|
||||
* Method 1 (6.2.3.2. in RFC4346 and RFC5246)
|
||||
*/
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_2 )
|
||||
if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
|
||||
{
|
||||
/*
|
||||
* Generate IV
|
||||
@ -781,9 +848,9 @@ static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
dec_msg_result = ssl->in_msg;
|
||||
|
||||
/*
|
||||
* Initialize for prepended IV for block cipher in TLS v1.1
|
||||
* Initialize for prepended IV for block cipher in TLS v1.1 and up
|
||||
*/
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_2 )
|
||||
if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
|
||||
{
|
||||
dec_msg += ssl->ivlen;
|
||||
dec_msglen -= ssl->ivlen;
|
||||
@ -1053,6 +1120,7 @@ int ssl_write_record( ssl_context *ssl )
|
||||
|
||||
md5_update( &ssl->fin_md5 , ssl->out_msg, len );
|
||||
sha1_update( &ssl->fin_sha1, ssl->out_msg, len );
|
||||
sha2_update( &ssl->fin_sha2, ssl->out_msg, len );
|
||||
}
|
||||
|
||||
if( ssl->do_crypt != 0 )
|
||||
@ -1127,6 +1195,7 @@ int ssl_read_record( ssl_context *ssl )
|
||||
|
||||
md5_update( &ssl->fin_md5 , ssl->in_msg, ssl->in_hslen );
|
||||
sha1_update( &ssl->fin_sha1, ssl->in_msg, ssl->in_hslen );
|
||||
sha2_update( &ssl->fin_sha2, ssl->in_msg, ssl->in_hslen );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -1192,7 +1261,7 @@ int ssl_read_record( ssl_context *ssl )
|
||||
/*
|
||||
* TLS encrypted messages can have up to 256 bytes of padding
|
||||
*/
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_1 &&
|
||||
if( ssl->minor_ver >= SSL_MINOR_VERSION_1 &&
|
||||
ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
@ -1256,6 +1325,7 @@ int ssl_read_record( ssl_context *ssl )
|
||||
|
||||
md5_update( &ssl->fin_md5 , ssl->in_msg, ssl->in_hslen );
|
||||
sha1_update( &ssl->fin_sha1, ssl->in_msg, ssl->in_hslen );
|
||||
sha2_update( &ssl->fin_sha2, ssl->in_msg, ssl->in_hslen );
|
||||
}
|
||||
|
||||
if( ssl->in_msgtype == SSL_MSG_ALERT )
|
||||
@ -1600,17 +1670,21 @@ int ssl_parse_change_cipher_spec( ssl_context *ssl )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void ssl_calc_finished(
|
||||
ssl_context *ssl, unsigned char *buf, int from,
|
||||
md5_context *md5, sha1_context *sha1 )
|
||||
static void ssl_calc_finished_ssl(
|
||||
ssl_context *ssl, unsigned char *buf, int from )
|
||||
{
|
||||
int len = 12;
|
||||
char *sender;
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
|
||||
unsigned char padbuf[48];
|
||||
unsigned char md5sum[16];
|
||||
unsigned char sha1sum[20];
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> calc finished" ) );
|
||||
SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) );
|
||||
|
||||
memcpy( &md5 , &ssl->fin_md5 , sizeof( md5_context ) );
|
||||
memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
|
||||
|
||||
/*
|
||||
* SSLv3:
|
||||
@ -1619,68 +1693,47 @@ static void ssl_calc_finished(
|
||||
* MD5( handshake + sender + master + pad1 ) )
|
||||
* + SHA1( master + pad2 +
|
||||
* SHA1( handshake + sender + master + pad1 ) )
|
||||
*
|
||||
* TLSv1:
|
||||
* hash = PRF( master, finished_label,
|
||||
* MD5( handshake ) + SHA1( handshake ) )[0..11]
|
||||
*/
|
||||
|
||||
SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
|
||||
md5->state, sizeof( md5->state ) );
|
||||
md5.state, sizeof( md5.state ) );
|
||||
|
||||
SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
|
||||
sha1->state, sizeof( sha1->state ) );
|
||||
sha1.state, sizeof( sha1.state ) );
|
||||
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT"
|
||||
: (char *) "SRVR";
|
||||
sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT"
|
||||
: (char *) "SRVR";
|
||||
|
||||
memset( padbuf, 0x36, 48 );
|
||||
memset( padbuf, 0x36, 48 );
|
||||
|
||||
md5_update( md5, (unsigned char *) sender, 4 );
|
||||
md5_update( md5, ssl->session->master, 48 );
|
||||
md5_update( md5, padbuf, 48 );
|
||||
md5_finish( md5, md5sum );
|
||||
md5_update( &md5, (unsigned char *) sender, 4 );
|
||||
md5_update( &md5, ssl->session->master, 48 );
|
||||
md5_update( &md5, padbuf, 48 );
|
||||
md5_finish( &md5, md5sum );
|
||||
|
||||
sha1_update( sha1, (unsigned char *) sender, 4 );
|
||||
sha1_update( sha1, ssl->session->master, 48 );
|
||||
sha1_update( sha1, padbuf, 40 );
|
||||
sha1_finish( sha1, sha1sum );
|
||||
sha1_update( &sha1, (unsigned char *) sender, 4 );
|
||||
sha1_update( &sha1, ssl->session->master, 48 );
|
||||
sha1_update( &sha1, padbuf, 40 );
|
||||
sha1_finish( &sha1, sha1sum );
|
||||
|
||||
memset( padbuf, 0x5C, 48 );
|
||||
memset( padbuf, 0x5C, 48 );
|
||||
|
||||
md5_starts( md5 );
|
||||
md5_update( md5, ssl->session->master, 48 );
|
||||
md5_update( md5, padbuf, 48 );
|
||||
md5_update( md5, md5sum, 16 );
|
||||
md5_finish( md5, buf );
|
||||
md5_starts( &md5 );
|
||||
md5_update( &md5, ssl->session->master, 48 );
|
||||
md5_update( &md5, padbuf, 48 );
|
||||
md5_update( &md5, md5sum, 16 );
|
||||
md5_finish( &md5, buf );
|
||||
|
||||
sha1_starts( sha1 );
|
||||
sha1_update( sha1, ssl->session->master, 48 );
|
||||
sha1_update( sha1, padbuf , 40 );
|
||||
sha1_update( sha1, sha1sum, 20 );
|
||||
sha1_finish( sha1, buf + 16 );
|
||||
sha1_starts( &sha1 );
|
||||
sha1_update( &sha1, ssl->session->master, 48 );
|
||||
sha1_update( &sha1, padbuf , 40 );
|
||||
sha1_update( &sha1, sha1sum, 20 );
|
||||
sha1_finish( &sha1, buf + 16 );
|
||||
|
||||
len += 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
sender = ( from == SSL_IS_CLIENT )
|
||||
? (char *) "client finished"
|
||||
: (char *) "server finished";
|
||||
SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
|
||||
|
||||
md5_finish( md5, padbuf );
|
||||
sha1_finish( sha1, padbuf + 16 );
|
||||
|
||||
tls1_prf( ssl->session->master, 48, sender,
|
||||
padbuf, 36, buf, len );
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
|
||||
|
||||
memset( md5, 0, sizeof( md5_context ) );
|
||||
memset( sha1, 0, sizeof( sha1_context ) );
|
||||
memset( &md5, 0, sizeof( md5_context ) );
|
||||
memset( &sha1, 0, sizeof( sha1_context ) );
|
||||
|
||||
memset( padbuf, 0, sizeof( padbuf ) );
|
||||
memset( md5sum, 0, sizeof( md5sum ) );
|
||||
@ -1689,20 +1742,100 @@ static void ssl_calc_finished(
|
||||
SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
|
||||
}
|
||||
|
||||
int ssl_write_finished( ssl_context *ssl )
|
||||
static void ssl_calc_finished_tls(
|
||||
ssl_context *ssl, unsigned char *buf, int from )
|
||||
{
|
||||
int ret, hash_len;
|
||||
md5_context md5;
|
||||
int len = 12;
|
||||
char *sender;
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
unsigned char padbuf[36];
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
|
||||
SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) );
|
||||
|
||||
memcpy( &md5 , &ssl->fin_md5 , sizeof( md5_context ) );
|
||||
memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
|
||||
|
||||
ssl_calc_finished( ssl, ssl->out_msg + 4,
|
||||
ssl->endpoint, &md5, &sha1 );
|
||||
/*
|
||||
* TLSv1:
|
||||
* hash = PRF( master, finished_label,
|
||||
* MD5( handshake ) + SHA1( handshake ) )[0..11]
|
||||
*/
|
||||
|
||||
SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
|
||||
md5.state, sizeof( md5.state ) );
|
||||
|
||||
SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
|
||||
sha1.state, sizeof( sha1.state ) );
|
||||
|
||||
sender = ( from == SSL_IS_CLIENT )
|
||||
? (char *) "client finished"
|
||||
: (char *) "server finished";
|
||||
|
||||
md5_finish( &md5, padbuf );
|
||||
sha1_finish( &sha1, padbuf + 16 );
|
||||
|
||||
ssl->tls_prf( ssl->session->master, 48, sender,
|
||||
padbuf, 36, buf, len );
|
||||
|
||||
SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
|
||||
|
||||
memset( &md5, 0, sizeof( md5_context ) );
|
||||
memset( &sha1, 0, sizeof( sha1_context ) );
|
||||
|
||||
memset( padbuf, 0, sizeof( padbuf ) );
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
|
||||
}
|
||||
|
||||
static void ssl_calc_finished_tls1_2(
|
||||
ssl_context *ssl, unsigned char *buf, int from )
|
||||
{
|
||||
int len = 12;
|
||||
char *sender;
|
||||
sha2_context sha2;
|
||||
unsigned char padbuf[32];
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> calc finished tls 1.2" ) );
|
||||
|
||||
memcpy( &sha2, &ssl->fin_sha2, sizeof( sha2_context ) );
|
||||
|
||||
/*
|
||||
* TLSv1.2:
|
||||
* hash = PRF( master, finished_label,
|
||||
* Hash( handshake ) )[0.11]
|
||||
*/
|
||||
|
||||
SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *)
|
||||
sha2.state, sizeof( sha2.state ) );
|
||||
|
||||
sender = ( from == SSL_IS_CLIENT )
|
||||
? (char *) "client finished"
|
||||
: (char *) "server finished";
|
||||
|
||||
sha2_finish( &sha2, padbuf );
|
||||
|
||||
ssl->tls_prf( ssl->session->master, 48, sender,
|
||||
padbuf, 32, buf, len );
|
||||
|
||||
SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
|
||||
|
||||
memset( &sha2, 0, sizeof( sha2_context ) );
|
||||
|
||||
memset( padbuf, 0, sizeof( padbuf ) );
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
|
||||
}
|
||||
|
||||
int ssl_write_finished( ssl_context *ssl )
|
||||
{
|
||||
int ret, hash_len;
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
|
||||
|
||||
ssl->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint );
|
||||
|
||||
// TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
|
||||
hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
|
||||
|
||||
ssl->out_msglen = 4 + hash_len;
|
||||
@ -1741,13 +1874,10 @@ int ssl_parse_finished( ssl_context *ssl )
|
||||
int ret;
|
||||
unsigned int hash_len;
|
||||
unsigned char buf[36];
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
|
||||
|
||||
memcpy( &md5 , &ssl->fin_md5 , sizeof( md5_context ) );
|
||||
memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
|
||||
ssl->calc_finished( ssl, buf, ssl->endpoint ^ 1 );
|
||||
|
||||
ssl->do_crypt = 1;
|
||||
|
||||
@ -1763,6 +1893,7 @@ int ssl_parse_finished( ssl_context *ssl )
|
||||
return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
}
|
||||
|
||||
// TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
|
||||
hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
|
||||
|
||||
if( ssl->in_msg[0] != SSL_HS_FINISHED ||
|
||||
@ -1772,8 +1903,6 @@ int ssl_parse_finished( ssl_context *ssl )
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
|
||||
}
|
||||
|
||||
ssl_calc_finished( ssl, buf, ssl->endpoint ^ 1, &md5, &sha1 );
|
||||
|
||||
if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
|
||||
@ -1834,6 +1963,7 @@ int ssl_init( ssl_context *ssl )
|
||||
|
||||
md5_starts( &ssl->fin_md5 );
|
||||
sha1_starts( &ssl->fin_sha1 );
|
||||
sha2_starts( &ssl->fin_sha2, 0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -1879,6 +2009,7 @@ void ssl_session_reset( ssl_context *ssl )
|
||||
|
||||
md5_starts( &ssl->fin_md5 );
|
||||
sha1_starts( &ssl->fin_sha1 );
|
||||
sha2_starts( &ssl->fin_sha2, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2199,6 +2330,9 @@ const char *ssl_get_version( const ssl_context *ssl )
|
||||
case SSL_MINOR_VERSION_2:
|
||||
return( "TLSv1.1" );
|
||||
|
||||
case SSL_MINOR_VERSION_3:
|
||||
return( "TLSv1.2" );
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user