summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-06-03 12:28:26 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-06-03 13:32:54 +0200
commit75b493132239e824d671f4b09d1dfd0f7ca6a8b1 (patch)
treeb015640b1ee2f1f1495952e531c028e98d502000
parent8020421946266ad6499cadff7a451a39fc36d88e (diff)
downloadgnutls-75b493132239e824d671f4b09d1dfd0f7ca6a8b1.tar.gz
Simplified the handling of handshake messages to be hashed.
Instead of doing a hash during the handshake process we now keep the data until handshake is over and hash them on demand. This uses more memory but eliminates issues with TLS 1.2 and makes the handling simpler.
-rw-r--r--lib/algorithms.h7
-rw-r--r--lib/algorithms/ciphersuites.c19
-rw-r--r--lib/algorithms/sign.c10
-rw-r--r--lib/ext/signature.c9
-rw-r--r--lib/gnutls_buffers.c57
-rw-r--r--lib/gnutls_buffers.h19
-rw-r--r--lib/gnutls_handshake.c428
-rw-r--r--lib/gnutls_int.h24
-rw-r--r--lib/gnutls_sig.c103
-rw-r--r--lib/nettle/pk.c33
10 files changed, 183 insertions, 526 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h
index a8461ee204..7a436daca8 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -59,6 +59,7 @@ int _gnutls_supported_ciphersuites (gnutls_session_t session,
int _gnutls_supported_ciphersuites_sorted (gnutls_session_t session,
cipher_suite_st ** ciphers);
const char *_gnutls_cipher_suite_get_name (cipher_suite_st * algorithm);
+gnutls_mac_algorithm_t _gnutls_cipher_suite_get_prf (const cipher_suite_st * suite);
gnutls_cipher_algorithm_t _gnutls_cipher_suite_get_cipher_algo (const
cipher_suite_st
* algorithm);
@@ -108,14 +109,14 @@ enum encipher_type _gnutls_kx_encipher_type (gnutls_kx_algorithm_t algorithm);
/* Functions for sign algorithms. */
gnutls_sign_algorithm_t _gnutls_x509_oid2sign_algorithm (const char *oid);
gnutls_sign_algorithm_t _gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk,
- gnutls_mac_algorithm_t mac);
+ gnutls_digest_algorithm_t mac);
gnutls_pk_algorithm_t _gnutls_x509_sign_to_pk (gnutls_sign_algorithm_t sign);
const char *_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t,
- gnutls_mac_algorithm_t mac);
+ gnutls_digest_algorithm_t mac);
gnutls_sign_algorithm_t _gnutls_tls_aid_to_sign (const sign_algorithm_st *
aid);
const sign_algorithm_st* _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign);
-gnutls_mac_algorithm_t
+gnutls_digest_algorithm_t
_gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t);
gnutls_pk_algorithm_t _gnutls_sign_get_pk_algorithm (gnutls_sign_algorithm_t);
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c
index e834e165d7..773d30fe53 100644
--- a/lib/algorithms/ciphersuites.c
+++ b/lib/algorithms/ciphersuites.c
@@ -37,7 +37,11 @@ _gnutls_qsort (gnutls_session_t session, void *_base, size_t nmemb,
/* Cipher SUITES */
#define GNUTLS_CIPHER_SUITE_ENTRY( name, block_algorithm, kx_algorithm, mac_algorithm, min_version, max_version, dtls ) \
- { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, min_version, max_version, dtls}
+ { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, min_version, max_version, dtls, GNUTLS_MAC_SHA256}
+#if 0
+#define GNUTLS_CIPHER_SUITE_ENTRY_PRF( name, block_algorithm, kx_algorithm, mac_algorithm, min_version, max_version, dtls, prf ) \
+ { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, min_version, max_version, dtls, prf}
+#endif
typedef struct
{
@@ -51,6 +55,7 @@ typedef struct
*/
gnutls_protocol_t max_version; /* this cipher suite is not supported after that */
int dtls:1; /* whether this ciphersuite is valid in DTLS */
+ gnutls_mac_algorithm_t prf;
} gnutls_cipher_suite_entry;
/* RSA with NULL cipher and MD5 MAC
@@ -245,7 +250,7 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_128_CBC_SHA1,
GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_DH,
GNUTLS_MAC_SHA1, GNUTLS_SSL3,
- GNUTLS_VERSION_MAX, ),
+ GNUTLS_VERSION_MAX, 1),
GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_256_CBC_SHA1,
GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_DH,
GNUTLS_MAC_SHA1, GNUTLS_SSL3,
@@ -662,6 +667,16 @@ _gnutls_cipher_suite_get_kx_algo (const cipher_suite_st * suite)
}
gnutls_mac_algorithm_t
+_gnutls_cipher_suite_get_prf (const cipher_suite_st * suite)
+{
+ int ret = 0;
+
+ GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->prf);
+ return ret;
+
+}
+
+gnutls_mac_algorithm_t
_gnutls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
{ /* In bytes */
int ret = 0;
diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
index ff99a64a13..414df76af4 100644
--- a/lib/algorithms/sign.c
+++ b/lib/algorithms/sign.c
@@ -35,7 +35,7 @@ struct gnutls_sign_entry
const char *oid;
gnutls_sign_algorithm_t id;
gnutls_pk_algorithm_t pk;
- gnutls_mac_algorithm_t mac;
+ gnutls_digest_algorithm_t mac;
/* See RFC 5246 HashAlgorithm and SignatureAlgorithm
for values to use in aid struct. */
const sign_algorithm_st aid;
@@ -180,7 +180,7 @@ _gnutls_x509_oid2sign_algorithm (const char *oid)
}
gnutls_sign_algorithm_t
-_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_mac_algorithm_t mac)
+_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t mac)
{
gnutls_sign_algorithm_t ret = 0;
@@ -196,7 +196,7 @@ _gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_mac_algorithm_t mac)
const char *
_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
- gnutls_mac_algorithm_t mac)
+ gnutls_digest_algorithm_t mac)
{
gnutls_sign_algorithm_t sign;
const char *ret = NULL;
@@ -209,10 +209,10 @@ _gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
return ret;
}
-gnutls_mac_algorithm_t
+gnutls_digest_algorithm_t
_gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t sign)
{
- gnutls_mac_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
+ gnutls_digest_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
GNUTLS_SIGN_ALG_LOOP (ret = p->mac);
diff --git a/lib/ext/signature.c b/lib/ext/signature.c
index 9ba7350df8..c92f081d8e 100644
--- a/lib/ext/signature.c
+++ b/lib/ext/signature.c
@@ -74,7 +74,7 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data,
size_t max_data_size)
{
opaque *p = data, *len_p;
- int len, i, j, hash;
+ int len, i, j;
const sign_algorithm_st *aid;
if (max_data_size < (session->internals.priorities.sign_algo.algorithms*2) + 2)
@@ -90,13 +90,6 @@ _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data,
for (i = j = 0; j < session->internals.priorities.sign_algo.algorithms; i += 2, j++)
{
- /* In gnutls we keep a state of SHA1 and SHA256 and thus cannot
- * use anything else.
- */
- hash = _gnutls_sign_get_hash_algorithm(session->internals.priorities.sign_algo.priority[j]);
- if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA256)
- continue;
-
aid =
_gnutls_sign_to_tls_aid (session->internals.priorities.
sign_algo.priority[j]);
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 1ca46eed27..b4a95581c7 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -1166,60 +1166,3 @@ _gnutls_handshake_io_recv_int (gnutls_session_t session,
return parse_record_buffered_msgs(session, htype, hsk);
}
-/* Buffer for handshake packets. Keeps the packets in order
- * for finished messages to use them. Used in HMAC calculation
- * and finished messages.
- */
-int
-_gnutls_handshake_hash_buffer_put (gnutls_session_t session, opaque * data,
- size_t length)
-{
-
- if (length == 0)
- return 0;
-
- if ((session->internals.max_handshake_data_buffer_size > 0) &&
- ((length + session->internals.handshake_hash_buffer.length) >
- session->internals.max_handshake_data_buffer_size))
- {
- gnutls_assert ();
- return GNUTLS_E_HANDSHAKE_TOO_LARGE;
- }
-
- _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", (int) length);
- if (_gnutls_buffer_append_data (&session->internals.handshake_hash_buffer,
- data, length) < 0)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- return 0;
-}
-
-int
-_gnutls_handshake_hash_buffer_get_size (gnutls_session_t session)
-{
-
- return session->internals.handshake_hash_buffer.length;
-}
-
-/* this function does not touch the buffer
- * and returns data from it (peek mode!)
- */
-int
-_gnutls_handshake_hash_buffer_get_ptr (gnutls_session_t session,
- opaque ** data_ptr, size_t * length)
-{
- if (length != NULL)
- *length = session->internals.handshake_hash_buffer.length;
-
- _gnutls_buffers_log ("BUF[HSK]: Peeked %d bytes of Data\n",
- (int) session->internals.handshake_hash_buffer.length);
-
- if (data_ptr != NULL)
- *data_ptr = session->internals.handshake_hash_buffer.data;
-
- return 0;
-}
-
diff --git a/lib/gnutls_buffers.h b/lib/gnutls_buffers.h
index 8eb3ac4006..c2a4444a68 100644
--- a/lib/gnutls_buffers.h
+++ b/lib/gnutls_buffers.h
@@ -46,25 +46,6 @@ int _gnutls_io_clear_peeked_data (gnutls_session_t session);
ssize_t _gnutls_io_write_buffered (gnutls_session_t session,
mbuffer_st * bufel, unsigned int mflag);
-int _gnutls_handshake_hash_buffer_get_size (gnutls_session_t session);
-int _gnutls_handshake_hash_buffer_put (gnutls_session_t session, opaque * data,
- size_t length);
-int _gnutls_handshake_hash_buffer_get_ptr (gnutls_session_t session,
- opaque ** data_ptr, size_t * length);
-
-/* Does not free the buffer
- */
-static inline void
-_gnutls_handshake_hash_buffer_empty (gnutls_session_t session)
-{
-
- _gnutls_buffers_log ("BUF[HSK]: Emptied buffer\n");
-
- session->internals.handshake_hash_buffer.length = 0;
- return;
-}
-
-
int _gnutls_handshake_io_cache_int (gnutls_session_t,
gnutls_handshake_description_t,
mbuffer_st * bufel);
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index ff1a6504ba..ff8a3d8774 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -66,7 +66,6 @@
#define TRUE 1
#define FALSE 0
-static int _gnutls_handshake_hash_init (gnutls_session_t session);
static int _gnutls_server_select_comp_method (gnutls_session_t session,
opaque * data, int datalen);
static int
@@ -76,6 +75,19 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session,
gnutls_pk_algorithm_t *pk_algos,
size_t pk_algos_size);
+/* Empties but does not free the buffer
+ */
+static inline void
+_gnutls_handshake_hash_buffer_empty (gnutls_session_t session)
+{
+
+ _gnutls_buffers_log ("BUF[HSK]: Emptied buffer\n");
+
+ session->internals.handshake_hash_buffer_prev_len = 0;
+ session->internals.handshake_hash_buffer.length = 0;
+ return;
+}
+
static int
_gnutls_handshake_hash_add_recvd (gnutls_session_t session,
gnutls_handshake_description_t recv_type,
@@ -83,6 +95,11 @@ _gnutls_handshake_hash_add_recvd (gnutls_session_t session,
opaque * dataptr, uint32_t datalen);
static int
+_gnutls_handshake_hash_add_sent (gnutls_session_t session,
+ gnutls_handshake_description_t type,
+ opaque * dataptr, uint32_t datalen);
+
+static int
_gnutls_recv_hello_verify_request (gnutls_session_t session,
opaque * data, int datalen);
@@ -92,25 +109,7 @@ _gnutls_recv_hello_verify_request (gnutls_session_t session,
void
_gnutls_handshake_hash_buffers_clear (gnutls_session_t session)
{
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_10)
- {
- _gnutls_hash_deinit (&session->internals.handshake_mac_handle.tls10.md5,
- NULL);
- _gnutls_hash_deinit (&session->internals.handshake_mac_handle.tls10.sha,
- NULL);
- }
- else if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
- {
- _gnutls_hash_deinit (&session->internals.handshake_mac_handle.tls12.
- sha256, NULL);
- _gnutls_hash_deinit (&session->internals.handshake_mac_handle.tls12.
- sha1, NULL);
- }
- session->security_parameters.handshake_mac_handle_type = 0;
- session->internals.handshake_mac_handle_init = 0;
-
+ session->internals.handshake_hash_buffer_prev_len = 0;
_gnutls_buffer_clear(&session->internals.handshake_hash_buffer);
}
@@ -185,55 +184,39 @@ _gnutls_set_client_random (gnutls_session_t session, uint8_t * rnd)
#define SSL3_SERVER_MSG "SRVR"
#define SSL_MSG_LEN 4
static int
-_gnutls_ssl3_finished (gnutls_session_t session, int type, opaque * ret)
+_gnutls_ssl3_finished (gnutls_session_t session, int type, opaque * ret, int sending)
{
- const int siz = SSL_MSG_LEN;
digest_hd_st td_md5;
digest_hd_st td_sha;
const char *mesg;
- int rc;
+ int rc, len;
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_10)
- {
- rc =
- _gnutls_hash_copy (&td_md5,
- &session->internals.handshake_mac_handle.tls10.
- md5);
- if (rc < 0)
- {
- gnutls_assert ();
- return rc;
- }
-
- rc =
- _gnutls_hash_copy (&td_sha,
- &session->internals.handshake_mac_handle.tls10.
- sha);
- if (rc < 0)
- {
- gnutls_assert ();
- _gnutls_hash_deinit (&td_md5, NULL);
- return rc;
- }
- }
+ if (sending)
+ len = session->internals.handshake_hash_buffer.length;
else
+ len = session->internals.handshake_hash_buffer_prev_len;
+
+ rc = _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
+ if (rc < 0)
+ return gnutls_assert_val(rc);
+
+ rc = _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
+ if (rc < 0)
{
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
+ _gnutls_hash_deinit (&td_sha, NULL);
+ return gnutls_assert_val(rc);
}
+ _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, len);
+ _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, len);
+
if (type == GNUTLS_SERVER)
- {
- mesg = SSL3_SERVER_MSG;
- }
+ mesg = SSL3_SERVER_MSG;
else
- {
- mesg = SSL3_CLIENT_MSG;
- }
+ mesg = SSL3_CLIENT_MSG;
- _gnutls_hash (&td_md5, mesg, siz);
- _gnutls_hash (&td_sha, mesg, siz);
+ _gnutls_hash (&td_md5, mesg, SSL_MSG_LEN);
+ _gnutls_hash (&td_sha, mesg, SSL_MSG_LEN);
rc = _gnutls_mac_deinit_ssl3_handshake (&td_md5, ret,
session->
@@ -265,58 +248,51 @@ _gnutls_ssl3_finished (gnutls_session_t session, int type, opaque * ret)
#define CLIENT_MSG "client finished"
#define TLS_MSG_LEN 15
static int
-_gnutls_finished (gnutls_session_t session, int type, void *ret)
+_gnutls_finished (gnutls_session_t session, int type, void *ret, int sending)
{
const int siz = TLS_MSG_LEN;
opaque concat[MAX_HASH_SIZE + 16 /*MD5 */ ];
- size_t len = 20 + 16;
+ size_t hash_len = 20 + 16;
const char *mesg;
digest_hd_st td_md5;
digest_hd_st td_sha;
- int rc;
+ int rc, len;
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_10)
+ if (sending)
+ len = session->internals.handshake_hash_buffer.length;
+ else
+ len = session->internals.handshake_hash_buffer_prev_len;
+
+ if (!_gnutls_version_has_selectable_prf (gnutls_protocol_get_version(session)))
{
- rc =
- _gnutls_hash_copy (&td_md5,
- &session->internals.handshake_mac_handle.tls10.
- md5);
+ rc = _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
if (rc < 0)
- {
- gnutls_assert ();
- return rc;
- }
+ return gnutls_assert_val(rc);
- rc =
- _gnutls_hash_copy (&td_sha,
- &session->internals.handshake_mac_handle.tls10.
- sha);
+ rc = _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
if (rc < 0)
{
- gnutls_assert ();
- _gnutls_hash_deinit (&td_md5, NULL);
- return rc;
+ _gnutls_hash_deinit (&td_sha, NULL);
+ return gnutls_assert_val(rc);
}
+ _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, len);
+ _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, len);
_gnutls_hash_deinit (&td_md5, concat);
_gnutls_hash_deinit (&td_sha, &concat[16]);
}
- else if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
+ else
{
- rc =
- _gnutls_hash_copy (&td_sha,
- &session->internals.handshake_mac_handle.tls12.
- sha256);
+ int algorithm = _gnutls_cipher_suite_get_prf(&session->security_parameters.current_cipher_suite);
+
+ rc = _gnutls_hash_init (&td_sha, algorithm);
if (rc < 0)
- {
- gnutls_assert ();
- return rc;
- }
+ return gnutls_assert_val(rc);
+
+ _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, len);
_gnutls_hash_deinit (&td_sha, concat);
- len = _gnutls_hash_get_algo_len (td_sha.algorithm);
+ hash_len = _gnutls_hash_get_algo_len (algorithm);
}
if (type == GNUTLS_SERVER)
@@ -329,7 +305,7 @@ _gnutls_finished (gnutls_session_t session, int type, void *ret)
}
return _gnutls_PRF (session, session->security_parameters.master_secret,
- GNUTLS_MASTER_SIZE, mesg, siz, concat, len, 12, ret);
+ GNUTLS_MASTER_SIZE, mesg, siz, concat, hash_len, 12, ret);
}
/* this function will produce GNUTLS_RANDOM_SIZE==32 bytes of random data
@@ -627,55 +603,6 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data,
return 0;
}
-/* here we hash all pending data.
- */
-inline static int
-_gnutls_handshake_hash_pending (gnutls_session_t session)
-{
- size_t siz;
- int ret;
- opaque *data;
-
- if (session->internals.handshake_mac_handle_init == 0)
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- /* We check if there are pending data to hash.
- */
- if ((ret = _gnutls_handshake_hash_buffer_get_ptr (session, &data, &siz)) < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- if (siz > 0)
- {
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_10)
- {
- _gnutls_hash (&session->internals.handshake_mac_handle.tls10.sha,
- data, siz);
- _gnutls_hash (&session->internals.handshake_mac_handle.tls10.md5,
- data, siz);
- }
- else if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
- {
- _gnutls_hash (&session->internals.handshake_mac_handle.tls12.sha256,
- data, siz);
- _gnutls_hash (&session->internals.handshake_mac_handle.tls12.sha1,
- data, siz);
- }
- }
-
- _gnutls_handshake_hash_buffer_empty (session);
-
- return 0;
-}
-
-
/* This is to be called after sending CHANGE CIPHER SPEC packet
* and initializing encryption. This is the first encrypted message
* we send.
@@ -698,26 +625,17 @@ _gnutls_send_finished (gnutls_session_t session, int again)
}
data = _mbuffer_get_udata_ptr (bufel);
- /* This is needed in order to hash all the required
- * messages.
- */
- if ((ret = _gnutls_handshake_hash_pending (session)) < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
{
ret =
_gnutls_ssl3_finished (session,
- session->security_parameters.entity, data);
+ session->security_parameters.entity, data, 1);
_mbuffer_set_udata_size (bufel, 36);
}
else
{ /* TLS 1.0+ */
ret = _gnutls_finished (session,
- session->security_parameters.entity, data);
+ session->security_parameters.entity, data, 1);
_mbuffer_set_udata_size (bufel, 12);
}
@@ -805,14 +723,14 @@ _gnutls_recv_finished (gnutls_session_t session)
ret =
_gnutls_ssl3_finished (session,
(session->security_parameters.entity + 1) % 2,
- data);
+ data, 0);
}
else
{ /* TLS 1.0 */
ret =
_gnutls_finished (session,
(session->security_parameters.entity +
- 1) % 2, data);
+ 1) % 2, data, 0);
}
if (ret < 0)
@@ -1118,56 +1036,6 @@ _gnutls_send_empty_handshake (gnutls_session_t session,
}
-/* This function will hash the handshake message we sent.
- */
-static int
-_gnutls_handshake_hash_add_sent (gnutls_session_t session,
- gnutls_handshake_description_t type,
- opaque * dataptr, uint32_t datalen)
-{
- int ret;
-
- if (session->security_parameters.entity == GNUTLS_CLIENT
- && type == GNUTLS_HANDSHAKE_CLIENT_HELLO)
- {
- /* do not hash immediatelly since the hash has not yet been initialized */
- if ((ret =
- _gnutls_handshake_hash_buffer_put (session, dataptr, datalen)) < 0)
- {
- gnutls_assert ();
- return ret;
- }
- return 0;
- }
-
- if ((ret = _gnutls_handshake_hash_pending (session)) < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
- {
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_10)
- {
- _gnutls_hash (&session->internals.handshake_mac_handle.tls10.sha,
- dataptr, datalen);
- _gnutls_hash (&session->internals.handshake_mac_handle.tls10.md5,
- dataptr, datalen);
- }
- else if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
- {
- _gnutls_hash (&session->internals.handshake_mac_handle.tls12.sha256,
- dataptr, datalen);
- _gnutls_hash (&session->internals.handshake_mac_handle.tls12.sha1,
- dataptr, datalen);
- }
- }
-
- return 0;
-}
/* This function sends a handshake message of type 'type' containing the
@@ -1272,8 +1140,15 @@ _gnutls_send_handshake (gnutls_session_t session, mbuffer_st * bufel,
return ret;
}
-/* This function will hash the handshake headers and the
- * handshake data.
+#define CHECK_SIZE(ll) \
+ if ((session->internals.max_handshake_data_buffer_size > 0) && \
+ (((ll) + session->internals.handshake_hash_buffer.length) > \
+ session->internals.max_handshake_data_buffer_size)) \
+ return gnutls_assert_val(GNUTLS_E_HANDSHAKE_TOO_LARGE)
+
+/* This function add the handshake headers and the
+ * handshake data to the handshake hash buffers. Needed
+ * for the finished messages calculations.
*/
static int
_gnutls_handshake_hash_add_recvd (gnutls_session_t session,
@@ -1287,37 +1162,48 @@ _gnutls_handshake_hash_add_recvd (gnutls_session_t session,
recv_type == GNUTLS_HANDSHAKE_HELLO_REQUEST)
return 0;
- /* The idea here is to hash the previous message we received,
- * and add the one we just received into the handshake_hash_buffer.
- */
- if ((session->security_parameters.entity == GNUTLS_SERVER
- || recv_type != GNUTLS_HANDSHAKE_SERVER_HELLO)
- && (session->security_parameters.entity == GNUTLS_CLIENT
- || (recv_type != GNUTLS_HANDSHAKE_CLIENT_HELLO && recv_type != GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)))
- {
- if ((ret = _gnutls_handshake_hash_pending (session)) < 0)
- {
- gnutls_assert ();
- return ret;
- }
- }
+ CHECK_SIZE(header_size + datalen);
- /* here we buffer the handshake messages - needed at Finished message */
- if ((ret =
- _gnutls_handshake_hash_buffer_put (session, header, header_size)) < 0)
+ session->internals.handshake_hash_buffer_prev_len = session->internals.handshake_hash_buffer.length;
+
+ ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
+ header, header_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if (datalen > 0)
{
- gnutls_assert ();
- return ret;
+ ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
+ dataptr, datalen);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
}
- if (datalen > 0)
+ return 0;
+}
+
+/* This function will store the handshake message we sent.
+ */
+static int
+_gnutls_handshake_hash_add_sent (gnutls_session_t session,
+ gnutls_handshake_description_t type,
+ opaque * dataptr, uint32_t datalen)
+{
+ int ret;
+
+ /* We don't check for GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST because it
+ * is not sent via that channel.
+ */
+ if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
{
- if ((ret =
- _gnutls_handshake_hash_buffer_put (session, dataptr, datalen)) < 0)
- {
- gnutls_assert ();
- return ret;
- }
+ CHECK_SIZE(datalen);
+
+ ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
+ dataptr, datalen);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 0;
}
return 0;
@@ -1379,14 +1265,6 @@ _gnutls_recv_handshake (gnutls_session_t session,
goto cleanup;
}
- /* initialize the hashes for both - (client will know server's version
- * and server as well at this point) */
- if ((ret = _gnutls_handshake_hash_init (session)) < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
goto cleanup; /* caller doesn't need dataptr */
break;
@@ -2374,82 +2252,6 @@ _gnutls_abort_handshake (gnutls_session_t session, int ret)
}
-/* This function initialized the handshake hash session.
- * required for finished messages.
- */
-static int
-_gnutls_handshake_hash_init (gnutls_session_t session)
-{
- gnutls_protocol_t ver = gnutls_protocol_get_version (session);
-
- if (session->internals.handshake_mac_handle_init == 0)
- {
- int ret;
-
- /* set the hash type for handshake message hashing */
- if (_gnutls_version_has_selectable_prf (ver))
- session->security_parameters.handshake_mac_handle_type =
- HANDSHAKE_MAC_TYPE_12;
- else
- session->security_parameters.handshake_mac_handle_type =
- HANDSHAKE_MAC_TYPE_10;
-
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_10)
- {
- ret =
- _gnutls_hash_init (&session->internals.handshake_mac_handle.tls10.
- md5, GNUTLS_MAC_MD5);
-
- if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- ret =
- _gnutls_hash_init (&session->internals.handshake_mac_handle.tls10.
- sha, GNUTLS_MAC_SHA1);
- if (ret < 0)
- {
- gnutls_assert ();
- _gnutls_hash_deinit (&session->internals.handshake_mac_handle.
- tls10.md5, NULL);
- return GNUTLS_E_MEMORY_ERROR;
- }
- }
- else if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
- {
- /* The algorithm to compute hash over handshake messages must be
- same as the one used as the basis for PRF. By now we use
- SHA256. */
- ret =
- _gnutls_hash_init (&session->internals.handshake_mac_handle.tls12.
- sha256, GNUTLS_DIG_SHA256);
- if (ret < 0)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- ret =
- _gnutls_hash_init (&session->internals.handshake_mac_handle.tls12.
- sha1, GNUTLS_DIG_SHA1);
- if (ret < 0)
- {
- gnutls_assert ();
- _gnutls_hash_deinit (&session->internals.handshake_mac_handle.
- tls12.sha256, NULL);
- return GNUTLS_E_MEMORY_ERROR;
- }
- }
-
- session->internals.handshake_mac_handle_init = 1;
- }
-
- return 0;
-}
static int
_gnutls_send_supplemental (gnutls_session_t session, int again)
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index b2bc5c22be..2db16ec898 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -328,12 +328,6 @@ typedef struct mbuffer_head_st
size_t byte_length;
} mbuffer_head_st;
-typedef enum
-{
- HANDSHAKE_MAC_TYPE_10 = 1, /* TLS 1.0 style */
- HANDSHAKE_MAC_TYPE_12 /* TLS 1.2 style */
-} handshake_mac_type_t;
-
/* Store & Retrieve functions defines:
*/
@@ -454,7 +448,6 @@ typedef struct
{
int entity; /* GNUTLS_SERVER or GNUTLS_CLIENT */
gnutls_kx_algorithm_t kx_algorithm;
- handshake_mac_type_t handshake_mac_handle_type; /* one of HANDSHAKE_TYPE_10 and HANDSHAKE_TYPE_12 */
/* The epoch used to read and write */
uint16_t epoch_read;
@@ -645,23 +638,10 @@ typedef struct
/* holds all the data received by the record layer */
mbuffer_head_st record_buffer;
+ int handshake_hash_buffer_prev_len; /* keeps the length of handshake_hash_buffer, excluding
+ * the last received message */
gnutls_buffer_st handshake_hash_buffer; /* used to keep the last received handshake
* message */
- union
- {
- struct
- {
- digest_hd_st sha; /* hash of the handshake messages */
- digest_hd_st md5; /* hash of the handshake messages */
- } tls10;
- struct
- {
- digest_hd_st sha1; /* hash of the handshake messages for TLS 1.2+ */
- digest_hd_st sha256; /* hash of the handshake messages for TLS 1.2+ */
- } tls12;
- } handshake_mac_handle;
- int handshake_mac_handle_init; /* 1 when the previous union and type were initialized */
-
int resumable:1; /* TRUE or FALSE - if we can resume that session */
handshake_state_t handshake_state; /* holds
* a number which indicates where
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index 0bd76afdb1..17e8cb4f88 100644
--- a/lib/gnutls_sig.c
+++ b/lib/gnutls_sig.c
@@ -416,39 +416,24 @@ _gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
gnutls_sign_algorithm_t sign_algo)
{
int ret;
- opaque concat[MAX_SIG_SIZE];
+ opaque concat[MAX_HASH_SIZE];
digest_hd_st td;
gnutls_datum_t dconcat;
- gnutls_sign_algorithm_t _sign_algo;
gnutls_digest_algorithm_t hash_algo;
- digest_hd_st *handshake_td;
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
- handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
- hash_algo = handshake_td->algorithm;
- _sign_algo =
- _gnutls_x509_pk_to_sign (pk, hash_algo);
-
- if (_sign_algo != sign_algo)
- {
- handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
- hash_algo = handshake_td->algorithm;
- _sign_algo =
- _gnutls_x509_pk_to_sign (pk, hash_algo);
- if (sign_algo != _sign_algo)
- {
- gnutls_assert ();
- return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
- }
- }
-
- ret = _gnutls_hash_copy (&td, handshake_td);
+ ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
if (ret < 0)
- {
- gnutls_assert ();
- return GNUTLS_E_HASH_FAILED;
- }
+ return gnutls_assert_val(ret);
+
+ hash_algo = _gnutls_sign_get_hash_algorithm(sign_algo);
+
+ ret = _gnutls_hash_init(&td, hash_algo);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ _gnutls_hash(&td, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
_gnutls_hash_deinit (&td, concat);
@@ -486,22 +471,13 @@ _gnutls_handshake_verify_cert_vrfy (gnutls_session_t session,
_gnutls_handshake_log ("HSK[%p]: verify cert vrfy: using %s\n",
session, gnutls_sign_algorithm_get_name (sign_algo));
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
- {
- return _gnutls_handshake_verify_cert_vrfy12 (session, cert, signature,
- sign_algo);
- }
- else if (session->security_parameters.handshake_mac_handle_type !=
- HANDSHAKE_MAC_TYPE_10)
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
+
+ if (_gnutls_version_has_selectable_sighash(ver))
+ return _gnutls_handshake_verify_cert_vrfy12 (session, cert, signature,
+ sign_algo);
ret =
- _gnutls_hash_copy (&td_md5,
- &session->internals.handshake_mac_handle.tls10.md5);
+ _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
if (ret < 0)
{
gnutls_assert ();
@@ -509,8 +485,7 @@ _gnutls_handshake_verify_cert_vrfy (gnutls_session_t session,
}
ret =
- _gnutls_hash_copy (&td_sha,
- &session->internals.handshake_mac_handle.tls10.sha);
+ _gnutls_hash_init (&td_sha, GNUTLS_DIG_SHA1);
if (ret < 0)
{
gnutls_assert ();
@@ -518,6 +493,9 @@ _gnutls_handshake_verify_cert_vrfy (gnutls_session_t session,
return GNUTLS_E_HASH_FAILED;
}
+ _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
+ _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer_prev_len);
+
if (ver == GNUTLS_SSL3)
{
ret = _gnutls_generate_master (session, 1);
@@ -582,7 +560,6 @@ _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
digest_hd_st td;
gnutls_sign_algorithm_t sign_algo;
gnutls_digest_algorithm_t hash_algo;
- digest_hd_st *handshake_td;
sign_algo =
_gnutls_session_get_sign_algo (session, cert);
@@ -598,20 +575,15 @@ _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
gnutls_sign_algorithm_get_name (sign_algo),
gnutls_mac_get_name (hash_algo));
- if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha1.algorithm)
- handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
- else if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha256.algorithm)
- handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
- else
- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* too bad we only support SHA1 and SHA256 */
-
- ret = _gnutls_hash_copy (&td, handshake_td);
+ ret = _gnutls_hash_init (&td, hash_algo);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
+ _gnutls_hash(&td, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length);
+
_gnutls_hash_deinit (&td, concat);
dconcat.data = concat;
@@ -649,28 +621,20 @@ _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
gnutls_protocol_t ver = gnutls_protocol_get_version (session);
gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
- if (session->security_parameters.handshake_mac_handle_type ==
- HANDSHAKE_MAC_TYPE_12)
- {
- return _gnutls_handshake_sign_cert_vrfy12 (session, cert, pkey,
+ if (_gnutls_version_has_selectable_sighash(ver))
+ return _gnutls_handshake_sign_cert_vrfy12 (session, cert, pkey,
signature);
- }
- else if (session->security_parameters.handshake_mac_handle_type !=
- HANDSHAKE_MAC_TYPE_10)
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
ret =
- _gnutls_hash_copy (&td_sha,
- &session->internals.handshake_mac_handle.tls10.sha);
+ _gnutls_hash_init (&td_sha, 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);
+
if (ver == GNUTLS_SSL3)
{
ret = _gnutls_generate_master (session, 1);
@@ -700,14 +664,11 @@ _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
{
case GNUTLS_PK_RSA:
ret =
- _gnutls_hash_copy (&td_md5,
- &session->internals.handshake_mac_handle.tls10.
- md5);
+ _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
+ return gnutls_assert_val(ret);
+
+ _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length);
if (ver == GNUTLS_SSL3)
{
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index b286027c09..478851b9bb 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -363,10 +363,10 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
if (hash_len > vdata->size)
{
gnutls_assert ();
- _gnutls_debug_log("Security level of algorithm requires hash %s or better\n", gnutls_mac_get_name(hash));
+ _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
}
- ret = ecc_sign_hash(vdata->data, hash_len,
+ ret = ecc_sign_hash(vdata->data, vdata->size,
&sig, NULL, rnd_func, &priv);
if (ret != 0)
{
@@ -410,7 +410,7 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
ret =
_dsa_sign (&pub, &priv, NULL, rnd_func,
- hash_len, vdata->data, &sig);
+ vdata->size, vdata->data, &sig);
if (ret == 0)
{
gnutls_assert ();
@@ -522,7 +522,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
const gnutls_datum_t * signature,
const gnutls_pk_params_st * pk_params)
{
- int ret, hash;
+ int ret;
bigint_t tmp[2] = { NULL, NULL };
switch (algo)
@@ -531,7 +531,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
{
ecc_key pub;
struct dsa_signature sig;
- int stat, hash_len;
+ int stat;
ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
if (ret < 0)
@@ -544,15 +544,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
memcpy (&sig.r, tmp[0], sizeof (sig.r));
memcpy (&sig.s, tmp[1], sizeof (sig.s));
- hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
- if (vdata->size < hash_len)
- {
- gnutls_assert ();
- ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
- goto ecdsa_fail;
- }
-
- ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub);
+ ret = ecc_verify_hash(&sig, vdata->data, vdata->size, &stat, &pub);
if (ret != 0 || stat != 1)
{
gnutls_assert();
@@ -561,7 +553,6 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
else
ret = 0;
- ecdsa_fail:
_gnutls_mpi_release (&tmp[0]);
_gnutls_mpi_release (&tmp[1]);
break;
@@ -570,7 +561,6 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
{
struct dsa_public_key pub;
struct dsa_signature sig;
- int hash_len;
ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
if (ret < 0)
@@ -583,15 +573,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
memcpy (&sig.r, tmp[0], sizeof (sig.r));
memcpy (&sig.s, tmp[1], sizeof (sig.s));
- hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
- if (vdata->size < hash_len)
- {
- gnutls_assert ();
- ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
- goto dsa_fail;
- }
-
- ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
+ ret = _dsa_verify (&pub, vdata->size, vdata->data, &sig);
if (ret == 0)
{
gnutls_assert();
@@ -600,7 +582,6 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
else
ret = 0;
- dsa_fail:
_gnutls_mpi_release (&tmp[0]);
_gnutls_mpi_release (&tmp[1]);
break;