summaryrefslogtreecommitdiff
path: root/lib/gnutls_handshake.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-10-08 14:09:30 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-10-08 14:19:59 +0200
commit105b694ef48402f5285eda3f95e2e64e3571610e (patch)
tree642f484240c432fc98a6b4edec9d5a826973dab6 /lib/gnutls_handshake.c
parent04f0459f6eeab641073c2db5cac1cfe04eb837ee (diff)
downloadgnutls-105b694ef48402f5285eda3f95e2e64e3571610e.tar.gz
Added support for the extended master secret calculation
That is performed implicitly unless GNUTLS_NO_EXTENSIONS is specified. The implementation follows draft-ietf-tls-session-hash-02.
Diffstat (limited to 'lib/gnutls_handshake.c')
-rw-r--r--lib/gnutls_handshake.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 28e4a7eafe..9ddcfbce3e 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -3571,3 +3571,69 @@ gnutls_handshake_get_last_out(gnutls_session_t session)
{
return session->internals.last_handshake_out;
}
+
+/* This returns the session hash as in draft-ietf-tls-session-hash-02.
+ *
+ * FIXME: It duplicates some of the actions in _gnutls_handshake_sign_crt_vrfy*.
+ * See whether they can be merged.
+ */
+int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t *shash)
+{
+ const version_entry_st *ver = get_version(session);
+ int ret;
+ const mac_entry_st *me;
+ uint8_t concat[2*MAX_HASH_SIZE];
+ digest_hd_st td_md5;
+ digest_hd_st td_sha;
+
+ if (unlikely(ver == NULL))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ if (_gnutls_version_has_selectable_prf(ver)) { /* TLS 1.2+ */
+ gnutls_mac_algorithm_t prf;
+
+ prf = _gnutls_cipher_suite_get_prf(session->security_parameters.cipher_suite);
+ if (prf == GNUTLS_MAC_UNKNOWN)
+ return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
+ me = mac_to_entry(prf);
+
+ ret =
+ _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
+ session->internals.handshake_hash_buffer.
+ data,
+ session->internals.handshake_hash_buffer.
+ length, concat);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return _gnutls_set_datum(shash, concat, me->output_size);
+ } else {
+ ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ _gnutls_hash(&td_sha,
+ session->internals.handshake_hash_buffer.data,
+ session->internals.handshake_hash_buffer.length);
+
+ _gnutls_hash_deinit(&td_sha, &concat[16]);
+
+ ret =
+ _gnutls_hash_init(&td_md5,
+ hash_to_entry(GNUTLS_DIG_MD5));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ _gnutls_hash(&td_md5,
+ session->internals.handshake_hash_buffer.data,
+ session->internals.handshake_hash_buffer.
+ length);
+
+ _gnutls_hash_deinit(&td_md5, concat);
+
+ return _gnutls_set_datum(shash, concat, 36);
+ }
+}