gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_99_2-50-gb9dbbec


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_99_2-50-gb9dbbec
Date: Sat, 04 Jun 2011 05:50:47 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=b9dbbec1861b86c9d4b0c2922b430293baa03dc2

The branch, master has been updated
       via  b9dbbec1861b86c9d4b0c2922b430293baa03dc2 (commit)
       via  fef1a0e62ce53e24837e19fe1964c85be33f2130 (commit)
       via  16ee4a4a79cd998982e8248fcabaea1d8a5e201e (commit)
       via  75b493132239e824d671f4b09d1dfd0f7ca6a8b1 (commit)
       via  8020421946266ad6499cadff7a451a39fc36d88e (commit)
       via  c192c6fbf31ae1db05155a8e1b6029c241303938 (commit)
       via  dd6b66f6eebb155cf5ef086f5d6f1c24a6261603 (commit)
      from  82ad8cac4b23990bef76be1de4e0a1740b59241c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b9dbbec1861b86c9d4b0c2922b430293baa03dc2
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 3 21:42:57 2011 +0200

    fixes for http://tools.ietf.org/html/draft-mavrogiannopoulos-tls-dss-00

commit fef1a0e62ce53e24837e19fe1964c85be33f2130
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 3 14:27:10 2011 +0200

    simplified _gnutls_selected_cert_supported_kx().

commit 16ee4a4a79cd998982e8248fcabaea1d8a5e201e
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 3 14:09:45 2011 +0200

    Truncation of ECDSA and DSA signatures moved to _wrap_nettle_pk_sign()
    and _wrap_nettle_pk_verify().

commit 75b493132239e824d671f4b09d1dfd0f7ca6a8b1
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 3 12:28:26 2011 +0200

    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.

commit 8020421946266ad6499cadff7a451a39fc36d88e
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 3 09:55:13 2011 +0200

    Hash algorithms used for DSA and ECDSA correspond to 
draft-mavrogiannopoulos-tls-dss-00.txt.

commit c192c6fbf31ae1db05155a8e1b6029c241303938
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri Jun 3 00:44:05 2011 +0200

    updated

commit dd6b66f6eebb155cf5ef086f5d6f1c24a6261603
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Jun 2 23:20:12 2011 +0200

    Added refint macro to refer to internal -non exported- functions. Used it 
to reference to the gnutls_*_register() functions.

-----------------------------------------------------------------------

Summary of changes:
 doc/cha-internals.texi        |   14 +-
 doc/gnutls.texi               |    5 +
 lib/algorithms.h              |    7 +-
 lib/algorithms/ciphersuites.c |   19 ++-
 lib/algorithms/sign.c         |   10 +-
 lib/auth/cert.h               |    2 +-
 lib/ext/ecc.c                 |   16 +-
 lib/ext/signature.c           |   10 +-
 lib/gnutls_buffers.c          |   57 ------
 lib/gnutls_buffers.h          |   19 --
 lib/gnutls_cert.c             |   15 +-
 lib/gnutls_handshake.c        |  436 +++++++++++------------------------------
 lib/gnutls_int.h              |   24 +--
 lib/gnutls_pubkey.c           |   20 ++-
 lib/gnutls_sig.c              |  103 +++-------
 lib/nettle/pk.c               |   51 ++----
 lib/x509/common.h             |    3 +-
 lib/x509/verify.c             |   42 +++-
 18 files changed, 273 insertions(+), 580 deletions(-)

diff --git a/doc/cha-internals.texi b/doc/cha-internals.texi
index 9981778..0180003 100644
--- a/doc/cha-internals.texi
+++ b/doc/cha-internals.texi
@@ -377,10 +377,10 @@ following functions can be used to register those 
algorithms.
 
 @itemize
 
address@hidden @ref{gnutls_crypto_single_cipher_register2}
address@hidden @refint{gnutls_crypto_single_cipher_register}
 To register a cipher algorithm.
 
address@hidden
address@hidden
 To register a hash (digest) or MAC algorithm.
 
 @end itemize
@@ -395,19 +395,19 @@ them. For this reason the following functions are 
provided.
 
 @itemize
 
address@hidden @ref{gnutls_crypto_cipher_register2}
address@hidden @refint{gnutls_crypto_cipher_register}
 To override the cryptographic algorithms backend.
 
address@hidden @ref{gnutls_crypto_digest_register2}
address@hidden @refint{gnutls_crypto_digest_register}
 To override the digest algorithms backend.
 
address@hidden @ref{gnutls_crypto_rnd_register2}
address@hidden @refint{gnutls_crypto_rnd_register}
 To override the random number generator backend.
 
address@hidden @ref{gnutls_crypto_bigint_register2}
address@hidden @refint{gnutls_crypto_bigint_register}
 To override the big number number operations backend.
 
address@hidden @ref{gnutls_crypto_pk_register2}
address@hidden @refint{gnutls_crypto_pk_register}
 To override the public key encryption backend. This is tight to the
 big number operations so either both of them should be updated or care
 must be taken to use the same format.
diff --git a/doc/gnutls.texi b/doc/gnutls.texi
index 14549b4..144171b 100644
--- a/doc/gnutls.texi
+++ b/doc/gnutls.texi
@@ -57,6 +57,11 @@ Documentation License''.
 @insertcopying
 @end titlepage
 
address@hidden reference to an internal function.
address@hidden refint {func}
address@hidden
address@hidden macro
+
 @macro xcite{ref}
 [\ref\] (@pxref{Bibliography})
 @end macro
diff --git a/lib/algorithms.h b/lib/algorithms.h
index a8461ee..7a436da 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 e834e16..773d30f 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 ff99a64..414df76 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/auth/cert.h b/lib/auth/cert.h
index efcdd85..b019961 100644
--- a/lib/auth/cert.h
+++ b/lib/auth/cert.h
@@ -166,7 +166,7 @@ int certificate_credentials_append_pkey 
(gnutls_certificate_credentials_t res,
                                          gnutls_privkey_t pkey);
 
 int _gnutls_selected_cert_supported_kx (struct gnutls_session_int *session,
-                                        gnutls_kx_algorithm_t ** alg,
+                                        gnutls_kx_algorithm_t * alg,
                                         int *alg_size);
 
 #endif
diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c
index f6d0218..358b3ea 100644
--- a/lib/ext/ecc.c
+++ b/lib/ext/ecc.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2002, 2003, 2004, 2005, 2010 Free Software Foundation,
- * Inc.
+ * Copyright (C) 2011 Free Software Foundation, Inc.
  *
  * Author: Nikos Mavrogiannopoulos
  *
@@ -215,8 +214,8 @@ int data_size = _data_size;
       len = data[0];
       DECR_LEN (data_size, len+1);
 
-      for (i=0;i<len;i++)
-        if (data[1+i] == 0) /* uncompressed */
+      for (i=1;i<=len;i++)
+        if (data[i] == 0) /* uncompressed */
           uncompressed = 1;
       
       if (uncompressed == 0)
@@ -244,9 +243,12 @@ _gnutls_supported_ecc_pf_send_params (gnutls_session_t 
session, gnutls_buffer_st
   if (session->security_parameters.entity == GNUTLS_SERVER && 
!_gnutls_session_is_ecc(session))
     return 0;
   
-  /* this extension is only being sent on client and server side */
-  _gnutls_buffer_append_data(extdata, p, 2);
-  return 2;
+  if (session->internals.priorities.supported_ecc.algorithms > 0)
+    {
+      _gnutls_buffer_append_data(extdata, p, 2);
+      return 2;
+    }
+  return 0;
 }
 
 
diff --git a/lib/ext/signature.c b/lib/ext/signature.c
index d2abd48..c92f081 100644
--- a/lib/ext/signature.c
+++ b/lib/ext/signature.c
@@ -34,7 +34,6 @@
 #include <gnutls_state.h>
 #include <gnutls_num.h>
 #include <algorithms.h>
-#include <x509/common.h> /* dsa_q_to_hash */
 #include <abstract_int.h>
 
 static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
@@ -75,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)
@@ -91,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 1ca46ee..b4a9558 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 8eb3ac4..c2a4444 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_cert.c b/lib/gnutls_cert.c
index f726c7d..9cb6685 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -247,19 +247,17 @@ int ret;
  */
 int
 _gnutls_selected_cert_supported_kx (gnutls_session_t session,
-                                    gnutls_kx_algorithm_t ** alg,
+                                    gnutls_kx_algorithm_t * alg,
                                     int *alg_size)
 {
   gnutls_kx_algorithm_t kx;
   gnutls_pk_algorithm_t pk, cert_pk;
-  gnutls_kx_algorithm_t kxlist[MAX_ALGOS];
   gnutls_pcert_st *cert;
   int i;
 
   if (session->internals.selected_cert_list_length == 0)
     {
       *alg_size = 0;
-      *alg = NULL;
       return 0;
     }
 
@@ -275,8 +273,11 @@ _gnutls_selected_cert_supported_kx (gnutls_session_t 
session,
           /* then check key usage */
           if (_gnutls_check_key_usage (cert, kx) == 0)
             {
-              kxlist[i] = kx;
+              alg[i] = kx;
               i++;
+              
+              if (i > *alg_size)
+                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
             }
         }
     }
@@ -287,14 +288,8 @@ _gnutls_selected_cert_supported_kx (gnutls_session_t 
session,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  *alg = gnutls_calloc (i, sizeof (gnutls_kx_algorithm_t));
-  if (*alg == NULL)
-    return GNUTLS_E_MEMORY_ERROR;
-
   *alg_size = i;
 
-  memcpy (*alg, kxlist, i * sizeof (gnutls_kx_algorithm_t));
-
   return 0;
 }
 
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index ff1a650..bb2932f 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)
@@ -3271,8 +3073,8 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
   gnutls_certificate_credentials_t cert_cred;
   gnutls_kx_algorithm_t kx;
   int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
-  gnutls_kx_algorithm_t *alg = NULL;
-  int alg_size = 0;
+  gnutls_kx_algorithm_t alg[MAX_ALGOS];
+  int alg_size = MAX_ALGOS;
 
   /* if we should use a specific certificate, 
    * we should remove all algorithms that are not supported
@@ -3304,7 +3106,7 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
    * supported by the X509 certificate parameters.
    */
   if ((ret =
-       _gnutls_selected_cert_supported_kx (session, &alg, &alg_size)) < 0)
+       _gnutls_selected_cert_supported_kx (session, alg, &alg_size)) < 0)
     {
       gnutls_assert ();
       return ret;
@@ -3314,7 +3116,6 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
   if (newSuite == NULL)
     {
       gnutls_assert ();
-      gnutls_free (alg);
       return GNUTLS_E_MEMORY_ERROR;
     }
 
@@ -3387,7 +3188,6 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
         }
     }
 
-  gnutls_free (alg);
   gnutls_free (*cipherSuites);
   *cipherSuites = newSuite;
 
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index b2bc5c2..2db16ec 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_pubkey.c b/lib/gnutls_pubkey.c
index 227036d..5dddae2 100644
--- a/lib/gnutls_pubkey.c
+++ b/lib/gnutls_pubkey.c
@@ -1197,9 +1197,12 @@ gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key,
 int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t pubkey, 
gnutls_protocol_t ver, 
   gnutls_sign_algorithm_t sign)
 {
+int hash_size;
+int hash_algo;
+
   if (pubkey->pk_algorithm == GNUTLS_PK_DSA)
-    { /* override */
-      int hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, 
&pubkey->params);
+    {
+      hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, 
&pubkey->params, &hash_size);
 
       /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
       if (!_gnutls_version_has_selectable_sighash (ver))
@@ -1209,7 +1212,18 @@ int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t 
pubkey, gnutls_protocol_t
         }
       else if (sign != GNUTLS_SIGN_UNKNOWN)
         {
-          if (_gnutls_sign_get_hash_algorithm(sign) != hash_algo)
+          if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) 
!= hash_size)
+            return GNUTLS_E_UNWANTED_ALGORITHM;
+        }
+        
+    }
+  else if (pubkey->pk_algorithm == GNUTLS_PK_ECC)
+    {
+      if (_gnutls_version_has_selectable_sighash (ver) && sign != 
GNUTLS_SIGN_UNKNOWN)
+        {
+          hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, 
&pubkey->params, &hash_size);
+
+          if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) 
!= hash_size)
             return GNUTLS_E_UNWANTED_ALGORITHM;
         }
         
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index 0bd76af..17e8cb4 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 15696cd..d0f2b96 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -359,15 +359,15 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
 
         dsa_signature_init (&sig);
 
-        hash = _gnutls_dsa_q_to_hash (algo, pk_params);
-        hash_len = _gnutls_hash_get_algo_len (hash);
+        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
         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);
+            hash_len = vdata->size;
           }
 
-        ret = ecc_sign_hash(vdata->data, vdata->size, 
+        ret = ecc_sign_hash(vdata->data, hash_len, 
                             &sig, NULL, rnd_func, &priv);
         if (ret != 0)
           {
@@ -402,12 +402,12 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
 
         dsa_signature_init (&sig);
 
-        hash = _gnutls_dsa_q_to_hash (algo, pk_params);
-        hash_len = _gnutls_hash_get_algo_len (hash);
+        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
         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);
+            hash_len = vdata->size;
           }
 
         ret =
@@ -524,7 +524,8 @@ _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;
+  int hash_len;
   bigint_t tmp[2] = { NULL, NULL };
 
   switch (algo)
@@ -546,19 +547,11 @@ _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);
-        if (vdata->size != _gnutls_hash_get_algo_len (hash))
-          {
-            gnutls_assert ();
-            
-            if (vdata->size < 20)
-              {
-                ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
-                goto ecdsa_fail;
-              }
-          }
+        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
+        if (hash_len > vdata->size)
+          hash_len = vdata->size;
 
-        ret = ecc_verify_hash(&sig, vdata->data, vdata->size, &stat, &pub);
+        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub);
         if (ret != 0 || stat != 1)
           {
             gnutls_assert();
@@ -567,7 +560,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;
@@ -588,19 +580,11 @@ _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);
-        if (vdata->size != _gnutls_hash_get_algo_len (hash))
-          {
-            gnutls_assert ();
-            
-            if (vdata->size < 20)
-              {
-                ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
-                goto dsa_fail;
-              }
-          }
+        _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
+        if (hash_len > vdata->size)
+          hash_len = vdata->size;
 
-        ret = _dsa_verify (&pub, vdata->size, vdata->data, &sig);
+        ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
         if (ret == 0)
           {
             gnutls_assert();
@@ -609,7 +593,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;
diff --git a/lib/x509/common.h b/lib/x509/common.h
index b025162..0e96337 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -140,7 +140,8 @@ int _gnutls_x509_get_signed_data (ASN1_TYPE src, const char 
*src_name,
 int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name,
                                 gnutls_datum_t * signature);
 
-gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, 
const gnutls_pk_params_st* params);
+gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, 
+  const gnutls_pk_params_st* params, int* hash_len);
 
 int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
                           gnutls_pk_params_st * params);
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 1170c04..4ae9706 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -827,7 +827,7 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
 /* Hashes input data and verifies a signature.
  */
 static int
-verify_sig (const gnutls_datum_t * text,
+dsa_verify_sig (const gnutls_datum_t * text,
                 const gnutls_datum_t * hash,
                 const gnutls_datum_t * signature,
                 gnutls_pk_algorithm_t pk,
@@ -838,21 +838,23 @@ verify_sig (const gnutls_datum_t * text,
   gnutls_datum_t digest;
   digest_hd_st hd;
   gnutls_digest_algorithm_t algo;
+  int hash_len;
 
-  algo = _gnutls_dsa_q_to_hash (pk, params);
+  algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len);
   if (hash)
     {
       /* SHA1 or better allowed */
-      if (!hash->data || hash->size != _gnutls_hash_get_algo_len(algo))
+      if (!hash->data || hash->size < hash_len)
         {
           gnutls_assert();
-          _gnutls_debug_log("Hash size (%d) does not correspond to hash 
%s.\n", (int)hash->size, gnutls_mac_get_name(algo));
+          _gnutls_debug_log("Hash size (%d) does not correspond to hash %s(%d) 
or better.\n", (int)hash->size, gnutls_mac_get_name(algo), hash_len);
           
-          if (hash->size < 20)
+          if (hash->size != 20) /* SHA1 is allowed */
             return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
         }
 
-      digest = *hash;
+      digest.data = hash->data;
+      digest.size = hash->size;
     }
   else
     {
@@ -902,7 +904,7 @@ pubkey_verify_sig (const gnutls_datum_t * tbs,
 
     case GNUTLS_PK_ECC:
     case GNUTLS_PK_DSA:
-      if (verify_sig(tbs, hash, signature, pk, issuer_params) != 0)
+      if (dsa_verify_sig(tbs, hash, signature, pk, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -918,7 +920,7 @@ pubkey_verify_sig (const gnutls_datum_t * tbs,
 }
 
 gnutls_digest_algorithm_t
-_gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* 
params)
+_gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* 
params, int* hash_len)
 {
   int bits = 0;
   
@@ -929,16 +931,34 @@ _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const 
gnutls_pk_params_st* pa
 
   if (bits <= 160)
     {
+      if (hash_len) *hash_len = 20;
       return GNUTLS_DIG_SHA1;
     }
+  else if (bits <= 192)
+    {
+      if (hash_len) *hash_len = 24;
+      return GNUTLS_DIG_SHA256;
+    }
   else if (bits <= 224)
     {
-      return GNUTLS_DIG_SHA224;
+      if (hash_len) *hash_len = 28;
+      return GNUTLS_DIG_SHA256;
     }
-  else
+  else if (bits <= 256)
     {
+      if (hash_len) *hash_len = 32;
       return GNUTLS_DIG_SHA256;
     }
+  else if (bits <= 384)
+    {
+      if (hash_len) *hash_len = 48;
+      return GNUTLS_DIG_SHA384;
+    }
+  else
+    {
+      if (hash_len) *hash_len = 64;
+      return GNUTLS_DIG_SHA512;
+    }
 }
 
 /* This will return the appropriate hash to verify the given signature.
@@ -962,7 +982,7 @@ _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * 
hash,
     case GNUTLS_PK_ECC:
 
       if (hash)
-        *hash = _gnutls_dsa_q_to_hash (pk, issuer_params);
+        *hash = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL);
 
       ret = 0;
       break;


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]