Commit 1ef83d66 authored by Paul Bakker's avatar Paul Bakker

- Initial bare version of TLS 1.2

parent 570267f0
......@@ -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 );
sha1_starts( &sha1 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_update( &sha1, ssl->in_msg + 4, n );
sha1_finish( &sha1, hash + 16 );
hash_id = SIG_RSA_RAW;
hashlen = 36;
}
else
{
n = ssl->in_hslen - ( end - p ) - 8;
md5_starts( &md5 );
md5_update( &md5, ssl->randbytes, 64 );
md5_update( &md5, ssl->in_msg + 4, n );
md5_finish( &md5, hash );
/*
* 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 + 16 );
sha1_starts( &sha1 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_update( &sha1, ssl->in_msg + 4, n );
sha1_finish( &sha1, hash );
SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
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 );
sha1_starts( &sha1 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_update( &sha1, ssl->out_msg + 4, n );
sha1_finish( &sha1, hash + 16 );
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 );
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, 36 );
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) */
......
This diff is collapsed.
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