]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Improved support of draft-ietf-tls-session-hash-02.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 25 Oct 2014 19:25:11 +0000 (21:25 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 25 Oct 2014 19:27:28 +0000 (21:27 +0200)
Now the session hash is calculated correctly even when a
client certificate is sent. That is, the session hash now
does not take into account the CertificateVerify message.

lib/gnutls_handshake.c
lib/gnutls_int.h

index cb00c821a9f469ac11bf95271d1df902a4f95e1f..2fec7c670fb7208047b1c4f25e77ce8b8a70c2ff 100644 (file)
@@ -116,6 +116,7 @@ recv_hello_verify_request(gnutls_session_t session,
 void _gnutls_handshake_hash_buffers_clear(gnutls_session_t session)
 {
        session->internals.handshake_hash_buffer_prev_len = 0;
+       session->internals.handshake_hash_buffer_client_kx_len = 0;
        _gnutls_buffer_clear(&session->internals.handshake_hash_buffer);
 }
 
@@ -1355,6 +1356,13 @@ handshake_hash_add_recvd(gnutls_session_t session,
                        return gnutls_assert_val(ret);
        }
 
+       /* save the size until client KX. That is because the TLS
+        * session hash is calculated up to this message.
+        */
+       if (recv_type == GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE)
+               session->internals.handshake_hash_buffer_client_kx_len =
+                       session->internals.handshake_hash_buffer.length;
+
        return 0;
 }
 
@@ -1397,6 +1405,10 @@ handshake_hash_add_sent(gnutls_session_t session,
                if (ret < 0)
                        return gnutls_assert_val(ret);
 
+               if (type == GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE)
+                       session->internals.handshake_hash_buffer_client_kx_len =
+                               session->internals.handshake_hash_buffer.length;
+
                return 0;
        }
 
@@ -3591,6 +3603,12 @@ int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
+       if (session->internals.handshake_hash_buffer_client_kx_len == 0 ||
+           (session->internals.handshake_hash_buffer.length <
+           session->internals.handshake_hash_buffer_client_kx_len)) {
+                       return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+       }
+
        if (_gnutls_version_has_selectable_prf(ver)) { /* TLS 1.2+ */
                gnutls_mac_algorithm_t prf;
 
@@ -3604,8 +3622,8 @@ int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t
                    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
                                      session->internals.handshake_hash_buffer.
                                      data,
-                                     session->internals.handshake_hash_buffer.
-                                     length, concat);
+                                     session->internals.handshake_hash_buffer_client_kx_len,
+                                     concat);
                if (ret < 0)
                        return gnutls_assert_val(ret);
 
@@ -3619,7 +3637,7 @@ int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t
 
                _gnutls_hash(&td_sha,
                             session->internals.handshake_hash_buffer.data,
-                            session->internals.handshake_hash_buffer.length);
+                            session->internals.handshake_hash_buffer_client_kx_len);
 
                _gnutls_hash_deinit(&td_sha, &concat[16]);
 
@@ -3631,8 +3649,7 @@ int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t
 
                _gnutls_hash(&td_md5,
                             session->internals.handshake_hash_buffer.data,
-                            session->internals.handshake_hash_buffer.
-                            length);
+                            session->internals.handshake_hash_buffer_client_kx_len);
 
                _gnutls_hash_deinit(&td_md5, concat);
 
index 2782bfc4e5884a43ffb11e2e593973e5ead740b3..7faa5ace05411895e8cc457566de92629cc92fde 100644 (file)
@@ -757,6 +757,8 @@ typedef struct {
 
        int handshake_hash_buffer_prev_len;     /* keeps the length of handshake_hash_buffer, excluding
                                                 * the last received message */
+       unsigned handshake_hash_buffer_client_kx_len;/* if non-zero it is the length of data until the
+                                                * the client key exchange message */
        gnutls_buffer_st handshake_hash_buffer; /* used to keep the last received handshake 
                                                 * message */
        bool resumable; /* TRUE or FALSE - if we can resume that session */