- Initial bare version of TLS 1.2

diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index fa476b9..18850c2 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -54,7 +54,7 @@
     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 @@
     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 @@
         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:
      *
@@ -390,6 +394,63 @@
 
     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 @@
     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_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 @@
         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 @@
         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 @@
         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;