Fixed client certificate handling with TLS 1.2
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 11a7a61..16b3200 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -891,15 +891,19 @@
 static int ssl_parse_certificate_request( ssl_context *ssl )
 {
     int ret;
+    unsigned char *buf, *p;
+    size_t n = 0;
+    size_t cert_type_len = 0, sig_alg_len = 0, dn_len = 0;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
 
     /*
      *     0  .   0   handshake type
      *     1  .   3   handshake length
-     *     4  .   5   SSL version
-     *     6  .   6   cert type count
-     *     7  .. n-1  cert types
+     *     4  .   4   cert type count
+     *     5  .. m-1  cert types
+     *     m  .. m+1  sig alg length (TLS 1.2 only)
+     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)
      *     n  .. n+1  length of all DNs
      *    n+2 .. n+3  length of DN 1
      *    n+4 .. ...  Distinguished Name #1
@@ -926,6 +930,70 @@
     SSL_DEBUG_MSG( 3, ( "got %s certificate request",
                         ssl->client_auth ? "a" : "no" ) );
 
+    if( ssl->client_auth == 0 )
+        goto exit;
+
+    // TODO: handshake_failure alert for an anonymous server to request
+    // client authentication
+
+    buf = ssl->in_msg;
+    
+    // Retrieve cert types
+    //
+    cert_type_len = buf[4];
+    n = cert_type_len;
+
+    if( ssl->in_hslen < 6 + n )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+    }
+
+    p = buf + 4;
+    while( cert_type_len > 0 )
+    {
+        if( *p == SSL_CERT_TYPE_RSA_SIGN )
+        {
+            ssl->handshake->cert_type = SSL_CERT_TYPE_RSA_SIGN;
+            break;
+        }
+
+        cert_type_len--;
+        p++;
+    }
+
+    if( ssl->handshake->cert_type == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "no known cert_type provided" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+    }
+
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        sig_alg_len = ( ( buf[5 + n] <<  8 )
+                      | ( buf[6 + n]       ) );
+
+        p = buf + 7 + n;
+        n += sig_alg_len;
+
+        if( ssl->in_hslen < 6 + n )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+        }
+    } 
+
+    dn_len = ( ( buf[7 + n] <<  8 )
+             | ( buf[8 + n]       ) );
+
+    n += dn_len;
+    if( ssl->in_hslen != 9 + n )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+    }
+
+exit:
     SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
 
     return( 0 );
@@ -1102,25 +1170,6 @@
         return( 0 );
     }
 
-    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
-    {
-        // TODO TLS1.2 Should be based on allowed signature algorithm received in
-        // Certificate Request according to RFC 5246. But OpenSSL only allows
-        // SHA256 and SHA384. Find out why OpenSSL does this.
-        //
-        if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
-            ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
-        {
-            hash_id = SIG_RSA_SHA384;
-            hashlen = 48;
-        }
-        else
-        {
-            hash_id = SIG_RSA_SHA256;
-            hashlen = 32;
-        }
-    }
-
     if( ssl->rsa_key == NULL )
     {
         SSL_DEBUG_MSG( 1, ( "got no private key" ) );
@@ -1132,23 +1181,52 @@
      */
     ssl->handshake->calc_verify( ssl, hash );
 
-    if ( ssl->rsa_key )
-        n = ssl->rsa_key_len ( ssl->rsa_key );
-
-    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
     {
-        // TODO TLS1.2 Should be based on allowed signature algorithm received in
-        // Certificate Request according to RFC 5246. But OpenSSL only allows
-        // SHA256 and SHA384. Find out why OpenSSL does this.
-        //
+        /*
+         * digitally-signed struct {
+         *     opaque md5_hash[16];
+         *     opaque sha_hash[20];
+         * };
+         *
+         * md5_hash
+         *     MD5(handshake_messages);
+         *
+         * sha_hash
+         *     SHA(handshake_messages);
+         */
+        hashlen = 36;
+        hash_id = SIG_RSA_RAW;
+    }
+    else
+    {
+        /*
+         * digitally-signed struct {
+         *     opaque handshake_messages[handshake_messages_length];
+         * };
+         *
+         * Taking shortcut here. We assume that the server always allows the
+         * PRF Hash function and has sent it in the allowed signature
+         * algorithms list received in the Certificate Request message.
+         *
+         * Until we encounter a server that does not, we will take this
+         * shortcut.
+         *
+         * Reason: Otherwise we should have running hashes for SHA512 and SHA224
+         *         in order to satisfy 'weird' needs from the server side.
+         */
         if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
             ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
         {
+            hash_id = SIG_RSA_SHA384;
+            hashlen = 48;
             ssl->out_msg[4] = SSL_HASH_SHA384;
             ssl->out_msg[5] = SSL_SIG_RSA;
         }
         else
         {
+            hash_id = SIG_RSA_SHA256;
+            hashlen = 32;
             ssl->out_msg[4] = SSL_HASH_SHA256;
             ssl->out_msg[5] = SSL_SIG_RSA;
         }
@@ -1156,6 +1234,9 @@
         offset = 2;
     }
 
+    if ( ssl->rsa_key )
+        n = ssl->rsa_key_len ( ssl->rsa_key );
+
     ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
     ssl->out_msg[5 + offset] = (unsigned char)( n      );
 
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 0e27677..79c3a38 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -689,7 +689,7 @@
 static int ssl_write_certificate_request( ssl_context *ssl )
 {
     int ret;
-    size_t n;
+    size_t n = 0, dn_size, total_dn_size;
     unsigned char *buf, *p;
     const x509_cert *crt;
 
@@ -707,7 +707,9 @@
      *     0  .   0   handshake type
      *     1  .   3   handshake length
      *     4  .   4   cert type count
-     *     5  .. n-1  cert types
+     *     5  .. m-1  cert types
+     *     m  .. m+1  sig alg length (TLS 1.2 only)
+     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only) 
      *     n  .. n+1  length of all DNs
      *    n+2 .. n+3  length of DN 1
      *    n+4 .. ...  Distinguished Name #1
@@ -720,30 +722,60 @@
      * At the moment, only RSA certificates are supported
      */
     *p++ = 1;
-    *p++ = 1;
+    *p++ = SSL_CERT_TYPE_RSA_SIGN;
+
+    /*
+     * Add signature_algorithms for verify (TLS 1.2)
+     * Only add current running algorithm that is already required for
+     * requested ciphersuite.
+     *
+     * Length is always 2
+     */
+    if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        ssl->handshake->verify_sig_alg = SSL_HASH_SHA256;
+
+        *p++ = 0;
+        *p++ = 2;
+
+        if( ssl->session_negotiate->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
+            ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+        {
+            ssl->handshake->verify_sig_alg = SSL_HASH_SHA384;
+        }
+        
+        *p++ = ssl->handshake->verify_sig_alg;
+        *p++ = SSL_SIG_RSA;
+
+        n += 4;
+    }
 
     p += 2;
     crt = ssl->ca_chain;
 
+    total_dn_size = 2;
     while( crt != NULL )
     {
         if( p - buf > 4096 )
             break;
 
-        n = crt->subject_raw.len;
-        *p++ = (unsigned char)( n >> 8 );
-        *p++ = (unsigned char)( n      );
-        memcpy( p, crt->subject_raw.p, n );
+        dn_size = crt->subject_raw.len;
+        *p++ = (unsigned char)( dn_size >> 8 );
+        *p++ = (unsigned char)( dn_size      );
+        memcpy( p, crt->subject_raw.p, dn_size );
+        p += dn_size;
 
-        SSL_DEBUG_BUF( 3, "requested DN", p, n );
-        p += n; crt = crt->next;
+        SSL_DEBUG_BUF( 3, "requested DN", p, dn_size );
+
+        total_dn_size += dn_size;
+        crt = crt->next;
     }
 
-    ssl->out_msglen  = n = p - buf;
+    ssl->out_msglen  = p - buf;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = SSL_HS_CERTIFICATE_REQUEST;
-    ssl->out_msg[6]  = (unsigned char)( ( n - 8 ) >> 8 );
-    ssl->out_msg[7]  = (unsigned char)( ( n - 8 )      );
+    ssl->out_msg[6 + n]  = (unsigned char)( total_dn_size  >> 8 );
+    ssl->out_msg[7 + n]  = (unsigned char)( total_dn_size       );
 
     ret = ssl_write_record( ssl );
 
@@ -1170,8 +1202,10 @@
 static int ssl_parse_certificate_verify( ssl_context *ssl )
 {
     int ret;
-    size_t n1, n2;
+    size_t n = 0, n1, n2;
     unsigned char hash[48];
+    int hash_id;
+    unsigned int hashlen;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
 
@@ -1204,17 +1238,49 @@
         return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
     }
 
-    n1 = ssl->session_negotiate->peer_cert->rsa.len;
-    n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+    {
+        /*
+         * As server we know we either have SSL_HASH_SHA384 or
+         * SSL_HASH_SHA256
+         */
+        if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg ||
+            ssl->in_msg[5] != SSL_SIG_RSA )
+        {
+            SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg for verify message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        }
 
-    if( n1 + 6 != ssl->in_hslen || n1 != n2 )
+        if( ssl->handshake->verify_sig_alg == SSL_HASH_SHA384 )
+        {
+            hashlen = 48;
+            hash_id = SIG_RSA_SHA384;
+        }
+        else
+        {
+            hashlen = 32;
+            hash_id = SIG_RSA_SHA256;
+        }
+
+        n += 2;
+    }
+    else
+    {
+        hashlen = 36;
+        hash_id = SIG_RSA_RAW;
+    }
+
+    n1 = ssl->session_negotiate->peer_cert->rsa.len;
+    n2 = ( ssl->in_msg[4 + n] << 8 ) | ssl->in_msg[5 + 2];
+
+    if( n + n1 + 6 != ssl->in_hslen || n1 != n2 )
     {
         SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
     }
 
     ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa, RSA_PUBLIC,
-                            SIG_RSA_RAW, 36, hash, ssl->in_msg + 6 );
+                            hash_id, hashlen, hash, ssl->in_msg + 6 + n );
     if( ret != 0 )
     {
         SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );