From 23f36808985e6fb2a22136ed672847cf8bbf6f45 Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Fri, 28 Sep 2012 14:15:14 +0000
Subject: [PATCH] - Added proper support for TLS 1.2 signature_algorithm
extension on server side - Minor const changes to other extension parsing
functions
---
include/polarssl/ssl.h | 1 +
library/ssl_cli.c | 2 +-
library/ssl_srv.c | 185 ++++++++++++++++++++++++++++++++++++-----
library/ssl_tls.c | 3 +-
4 files changed, 170 insertions(+), 21 deletions(-)
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index c48a89dbc5..c1f5ebe415 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -350,6 +350,7 @@ struct _ssl_handshake_params
/*
* Handshake specific crypto variables
*/
+ int sig_alg; /*!< Signature algorithm */
#if defined(POLARSSL_DHM_C)
dhm_context dhm_ctx; /*!< DHM key exchange */
#endif
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 07b31d979d..4c49639af9 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -701,7 +701,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
{
if( p[1] != SSL_SIG_RSA )
{
- SSL_DEBUG_MSG( 2, ( "Server used unsupported SignatureAlgorithm %d", p[1] ) );
+ 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 );
}
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 408d510faf..f6b21886c3 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -35,12 +35,12 @@
#include
static int ssl_parse_servername_ext( ssl_context *ssl,
- unsigned char *buf,
+ const unsigned char *buf,
size_t len )
{
int ret;
size_t servername_list_size, hostname_len;
- unsigned char *p;
+ const unsigned char *p;
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( servername_list_size + 2 != len )
@@ -72,13 +72,20 @@ static int ssl_parse_servername_ext( ssl_context *ssl,
}
servername_list_size -= hostname_len + 3;
+ p += hostname_len + 3;
+ }
+
+ if( servername_list_size != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
return( 0 );
}
static int ssl_parse_renegotiation_info( ssl_context *ssl,
- unsigned char *buf,
+ const unsigned char *buf,
size_t len )
{
int ret;
@@ -115,6 +122,71 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl,
return( 0 );
}
+static int ssl_parse_signature_algorithms_ext( ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ size_t sig_alg_list_size;
+ const unsigned char *p;
+
+ sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
+ if( sig_alg_list_size + 2 != len ||
+ sig_alg_list_size %2 != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ p = buf + 2;
+ while( sig_alg_list_size > 0 )
+ {
+ if( p[1] != SSL_SIG_RSA )
+ continue;
+#if defined(POLARSSL_SHA4_C)
+ if( p[0] == SSL_HASH_SHA512 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA512;
+ break;
+ }
+ if( p[0] == SSL_HASH_SHA384 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA384;
+ break;
+ }
+#endif
+#if defined(POLARSSL_SHA2_C)
+ if( p[0] == SSL_HASH_SHA256 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA256;
+ break;
+ }
+ if( p[0] == SSL_HASH_SHA224 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA224;
+ break;
+ }
+#endif
+ if( p[0] == SSL_HASH_SHA1 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_SHA1;
+ break;
+ }
+ if( p[0] == SSL_HASH_MD5 )
+ {
+ ssl->handshake->sig_alg = SSL_HASH_MD5;
+ break;
+ }
+
+ sig_alg_list_size -= 2;
+ p += 2;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
+ ssl->handshake->sig_alg ) );
+
+ return( 0 );
+}
+
static int ssl_parse_client_hello( ssl_context *ssl )
{
int ret;
@@ -399,9 +471,19 @@ have_ciphersuite:
SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
renegotiation_info_seen = 1;
- if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ) ) != 0 )
+ ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
+ if( ret != 0 )
return( ret );
+ break;
+ case TLS_EXT_SIG_ALG:
+ SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
+ if( ssl->renegotiation == SSL_RENEGOTIATION )
+ break;
+
+ ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
+ if( ret != 0 )
+ return( ret );
break;
default:
@@ -671,9 +753,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
#if defined(POLARSSL_DHM_C)
int ret;
size_t n, rsa_key_len = 0;
- unsigned char hash[48];
- md5_context md5;
- sha1_context sha1;
+ unsigned char hash[64];
int hash_id;
unsigned int hashlen;
#endif
@@ -741,6 +821,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
{
+ md5_context md5;
+ sha1_context sha1;
+
/*
* digitally-signed struct {
* opaque md5_hash[16];
@@ -776,17 +859,82 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
* ServerDHParams params;
* };
*/
- /* TODO TLS1.2 Get a supported hash algorithm from the
- * signature_algorithms extension, Otherwise SHA1 + RSA!
- */
-
- sha1_starts( &sha1 );
- sha1_update( &sha1, ssl->handshake->randbytes, 64 );
- sha1_update( &sha1, ssl->out_msg + 4, n );
- sha1_finish( &sha1, hash );
+#if defined(POLARSSL_SHA4_C)
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA512 )
+ {
+ sha4_context sha4;
- hashlen = 20;
- hash_id = SIG_RSA_SHA1;
+ sha4_starts( &sha4, 0 );
+ sha4_update( &sha4, ssl->handshake->randbytes, 64 );
+ sha4_update( &sha4, ssl->out_msg + 4, n );
+ sha4_finish( &sha4, hash );
+
+ hashlen = 64;
+ hash_id = SIG_RSA_SHA512;
+ }
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA384 )
+ {
+ sha4_context sha4;
+
+ sha4_starts( &sha4, 1 );
+ sha4_update( &sha4, ssl->handshake->randbytes, 64 );
+ sha4_update( &sha4, ssl->out_msg + 4, n );
+ sha4_finish( &sha4, hash );
+
+ hashlen = 48;
+ hash_id = SIG_RSA_SHA384;
+ }
+#endif
+#if defined(POLARSSL_SHA2_C)
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA256 )
+ {
+ sha2_context sha2;
+
+ sha2_starts( &sha2, 0 );
+ sha2_update( &sha2, ssl->handshake->randbytes, 64 );
+ sha2_update( &sha2, ssl->out_msg + 4, n );
+ sha2_finish( &sha2, hash );
+
+ hashlen = 32;
+ hash_id = SIG_RSA_SHA256;
+ }
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA224 )
+ {
+ sha2_context sha2;
+
+ sha2_starts( &sha2, 1 );
+ sha2_update( &sha2, ssl->handshake->randbytes, 64 );
+ sha2_update( &sha2, ssl->out_msg + 4, n );
+ sha2_finish( &sha2, hash );
+
+ hashlen = 24;
+ hash_id = SIG_RSA_SHA224;
+ }
+#endif
+ if( ssl->handshake->sig_alg == SSL_HASH_SHA1 )
+ {
+ sha1_context sha1;
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->handshake->randbytes, 64 );
+ sha1_update( &sha1, ssl->out_msg + 4, n );
+ sha1_finish( &sha1, hash );
+
+ hashlen = 20;
+ hash_id = SIG_RSA_SHA1;
+ }
+ if( ssl->handshake->sig_alg == SSL_HASH_MD5 )
+ {
+ md5_context md5;
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->handshake->randbytes, 64 );
+ md5_update( &md5, ssl->out_msg + 4, n );
+ md5_finish( &md5, hash );
+
+ hashlen = 16;
+ hash_id = SIG_RSA_MD5;
+ }
}
SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
@@ -796,8 +944,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
{
- // TODO TLS1.2 Base on selection above (SHA1 + RSA is default choice)
- ssl->out_msg[4 + n] = SSL_HASH_SHA1;
+ ssl->out_msg[4 + n] = ssl->handshake->sig_alg;
ssl->out_msg[5 + n] = SSL_SIG_RSA;
n += 2;
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index b66e046106..f5fcba47b7 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2834,7 +2834,8 @@ int ssl_handshake_init( ssl_context *ssl )
sha4_starts( &ssl->handshake->fin_sha4, 1 );
ssl->handshake->update_checksum = ssl_update_checksum_start;
-
+ ssl->handshake->sig_alg = SSL_HASH_SHA1;
+
return( 0 );
}