diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-10-08 14:09:30 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-10-08 14:19:59 +0200 |
commit | 105b694ef48402f5285eda3f95e2e64e3571610e (patch) | |
tree | 642f484240c432fc98a6b4edec9d5a826973dab6 /lib/gnutls_handshake.c | |
parent | 04f0459f6eeab641073c2db5cac1cfe04eb837ee (diff) | |
download | gnutls-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.c | 66 |
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); + } +} |