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_9_9-29-g46b51ce


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_9_9-29-g46b51ce
Date: Sat, 05 Dec 2009 11:25:23 +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=46b51ce1f8054761d51cb149a338fae2068fe0c5

The branch, master has been updated
       via  46b51ce1f8054761d51cb149a338fae2068fe0c5 (commit)
       via  0d3a8537747e8460459a9a97a6f68c1510a65c1f (commit)
       via  e64d8f55e46fe0638191e1c01f6bde303753d91b (commit)
       via  73d29186d2c962ec53aae56e0d1aeb2cab073628 (commit)
      from  8d7fd3776ca104cf92a8ebae05ef7a270bd8e95b (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 46b51ce1f8054761d51cb149a338fae2068fe0c5
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat Dec 5 13:24:42 2009 +0200

    use C99 initializations

commit 0d3a8537747e8460459a9a97a6f68c1510a65c1f
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat Dec 5 11:47:33 2009 +0200

    Reverted all previous changes to combine hashes with MAC algorithms.
    It is now permissible to register a hash algorithm separately from
    a MAC.

commit e64d8f55e46fe0638191e1c01f6bde303753d91b
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat Dec 5 10:08:22 2009 +0200

    Revert "Merged the two internal hash API functions, to simplify and reduce 
code."
    
    This reverts commit bc3e43d5f121e404aa32212dcfcc5027de807056.
    
    Conflicts:
    
        lib/crypto.c
        lib/gnutls_cipher.c
        lib/gnutls_hash_int.c
        lib/gnutls_hash_int.h
        lib/includes/gnutls/crypto.h
        lib/mac-libgcrypt.c

commit 73d29186d2c962ec53aae56e0d1aeb2cab073628
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat Dec 5 09:58:55 2009 +0200

    Revert "Added plain MD5 hash check and corrected gnutls_hash_fast() usage 
in openssl.c"
    
    This reverts commit 54486afbfcf3398846d5c20d3094bdb7d0a43ff2.

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

Summary of changes:
 NEWS                            |    9 +-
 lib/Makefile.am                 |    2 +-
 lib/compat.c                    |   47 -------
 lib/crypto-api.c                |   67 +++++++++--
 lib/crypto.c                    |  100 ++++++++++++++--
 lib/crypto.h                    |    3 +-
 lib/ext_session_ticket.c        |   16 ++--
 lib/gnutls_algorithms.c         |   54 ++++----
 lib/gnutls_algorithms.h         |   16 ++--
 lib/gnutls_cipher.c             |   37 ++++--
 lib/gnutls_cipher_int.h         |    2 +-
 lib/gnutls_constate.c           |    8 +-
 lib/gnutls_constate.h           |    4 +-
 lib/gnutls_handshake.c          |   16 ++--
 lib/gnutls_hash_int.c           |  264 +++++++++++++++++++++++++++++----------
 lib/gnutls_hash_int.h           |   45 +++++---
 lib/gnutls_int.h                |   14 +-
 lib/gnutls_priority.c           |    2 +-
 lib/gnutls_psk_netconf.c        |    6 +-
 lib/gnutls_sig.c                |   34 +++---
 lib/gnutls_srp.c                |   10 +-
 lib/gnutls_state.c              |   30 +++---
 lib/gnutls_ui.c                 |    4 +-
 lib/includes/gnutls/crypto.h    |   68 +++++++----
 lib/includes/gnutls/gnutls.h.in |   54 ++++----
 lib/libgnutls.map               |    9 +-
 lib/mac-libgcrypt.c             |   71 +++++++++--
 lib/opencdk/dummy.c             |    2 +-
 lib/opencdk/filters.h           |    6 +-
 lib/opencdk/hash.c              |    2 +-
 lib/opencdk/kbnode.c            |    2 +-
 lib/opencdk/main.h              |   12 +-
 lib/opencdk/opencdk.h           |    4 +-
 lib/opencdk/pubkey.c            |    4 +-
 lib/opencdk/sig-check.c         |   14 +-
 lib/opencdk/verify.c            |    4 +-
 lib/x509/crq.c                  |    4 +-
 lib/x509/pbkdf2-sha1.c          |    4 +-
 lib/x509/pkcs12.c               |   16 ++--
 lib/x509/pkcs12_encr.c          |    6 +-
 lib/x509/privkey.c              |    4 +-
 lib/x509/sign.c                 |   10 +-
 lib/x509/verify.c               |   14 +-
 lib/x509/x509.c                 |    6 +-
 lib/x509/x509_int.h             |    2 +-
 libextra/fipsmd5.c              |   91 +++++++++++---
 libextra/gnutls_openssl.c       |   12 +-
 src/benchmark.c                 |   57 ++++++++-
 tests/gc.c                      |   16 ---
 49 files changed, 848 insertions(+), 436 deletions(-)
 delete mode 100644 lib/compat.c

diff --git a/NEWS b/NEWS
index 69a5703..eee6dd6 100644
--- a/NEWS
+++ b/NEWS
@@ -30,12 +30,17 @@ gnutls_cipher_encrypt: Added
 gnutls_cipher_decrypt: Added
 gnutls_cipher_deinit: Added
 gnutls_hash_init: Added
-gnutls_hash_get_algo_len: Added
+gnutls_hash_get_len: Added
 gnutls_hash: Added
 gnutls_hash_fast: Added
 gnutls_hash_deinit: Added
 gnutls_hash_output: Added
-gnutls_hash_reset: Added
+gnutls_hmac_init: Added
+gnutls_hmac_get_len: Added
+gnutls_hmac: Added
+gnutls_hmac_fast: Added
+gnutls_hmac_deinit: Added
+gnutls_hmac_output: Added
 
 * Version 2.9.9 (released 2009-11-09)
 
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 8ebfd7b..54a91b7 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -81,7 +81,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c 
gnutls_cipher.c  \
        auth_dh_common.c gnutls_helper.c gnutls_supplemental.c          \
        crypto.c random.c pk-libgcrypt.c mpi-libgcrypt.c cryptodev.c    \
        rnd-libgcrypt.c cipher-libgcrypt.c mac-libgcrypt.c ext_signature.c \
-       crypto-api.c compat.c
+       crypto-api.c
 
 if ENABLE_OPRFI
 COBJECTS += $(OPRFI_COBJECTS)
diff --git a/lib/compat.c b/lib/compat.c
deleted file mode 100644
index 1b78f10..0000000
--- a/lib/compat.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2009 Free Software Foundation
- *
- * Author: Nikos Mavrogiannopoulos
- *
- * This file is part of GNUTLS.
- *
- * The GNUTLS library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- */
-
-#include <gnutls_errors.h>
-#include <gnutls_int.h>
-#include <gnutls/crypto.h>
-#include <crypto.h>
-#include <gnutls_mpi.h>
-#include <gnutls_pk.h>
-#include <random.h>
-#include <gnutls_cipher_int.h>
-
-int gnutls_crypto_single_mac_register2 (int priority, ...);
-int gnutls_crypto_mac_register2 (int priority, ...);
-
-int
-gnutls_crypto_single_mac_register2 (int priority, ...)
-{
-      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
-int gnutls_crypto_mac_register2 (int priority, ...)
-{
-      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-}
-
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index 4f9025a..8eb4179 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -60,39 +60,86 @@ gnutls_cipher_deinit (gnutls_cipher_hd_t handle)
   return _gnutls_cipher_deinit((cipher_hd_st*)handle);
 }
 
+
 /* HMAC */
 int
-gnutls_hash_init (gnutls_hash_hd_t * dig, gnutls_digest_algorithm_t algorithm,
+gnutls_hmac_init (gnutls_hmac_hd_t * dig, gnutls_digest_algorithm_t algorithm,
                   const void *key, int keylen)
 {
-  *dig = gnutls_malloc(sizeof(hash_hd_st));
+  *dig = gnutls_malloc(sizeof(digest_hd_st));
   if (*dig == NULL) {
     gnutls_assert();
     return GNUTLS_E_MEMORY_ERROR;
   }
   
-  return _gnutls_hash_init(((hash_hd_st*)*dig), algorithm, key, keylen);
+  return _gnutls_hmac_init(((digest_hd_st*)*dig), algorithm, key, keylen);
 }
 
-int gnutls_hash (gnutls_hash_hd_t handle, const void *text, size_t textlen)
+int gnutls_hmac (gnutls_hmac_hd_t handle, const void *text, size_t textlen)
 {
-  return _gnutls_hash((hash_hd_st*)handle, text, textlen);
+  return _gnutls_hmac((digest_hd_st*)handle, text, textlen);
 }
 
 void
-gnutls_hash_output (gnutls_hash_hd_t handle, void *digest)
+gnutls_hmac_output (gnutls_hmac_hd_t handle, void *digest)
 {
-  return _gnutls_hash_output((hash_hd_st*)handle, digest);
+  return _gnutls_hmac_output((digest_hd_st*)handle, digest);
 }
 
 void
-gnutls_hash_reset (gnutls_hash_hd_t handle)
+gnutls_hmac_deinit (gnutls_hmac_hd_t handle, void *digest)
+{
+  _gnutls_hmac_deinit((digest_hd_st*)handle, digest);
+}
+
+int gnutls_hmac_get_len( gnutls_mac_algorithm_t algorithm)
+{
+  return _gnutls_hmac_get_algo_len(algorithm);
+}
+
+int gnutls_hmac_fast( gnutls_mac_algorithm_t algorithm, const void* key, int 
keylen, 
+       const void* text, size_t textlen, void* digest)
 {
-  _gnutls_hash_reset((hash_hd_st*)handle);
+  return _gnutls_hmac_fast(algorithm, key, keylen, text, textlen, digest);
+}
+
+/* HASH */
+int
+gnutls_hash_init (gnutls_hash_hd_t * dig, gnutls_digest_algorithm_t algorithm)
+{
+  *dig = gnutls_malloc(sizeof(digest_hd_st));
+  if (*dig == NULL) {
+    gnutls_assert();
+    return GNUTLS_E_MEMORY_ERROR;
+  }
+  
+  return _gnutls_hash_init(((digest_hd_st*)*dig), algorithm);
+}
+
+int gnutls_hash (gnutls_hash_hd_t handle, const void *text, size_t textlen)
+{
+  return _gnutls_hash((digest_hd_st*)handle, text, textlen);
+}
+
+void
+gnutls_hash_output (gnutls_hash_hd_t handle, void *digest)
+{
+  return _gnutls_hash_output((digest_hd_st*)handle, digest);
 }
 
 void
 gnutls_hash_deinit (gnutls_hash_hd_t handle, void *digest)
 {
-  _gnutls_hash_deinit((hash_hd_st*)handle, digest);
+  _gnutls_hash_deinit((digest_hd_st*)handle, digest);
+}
+
+int gnutls_hash_get_len( gnutls_digest_algorithm_t algorithm)
+{
+  return _gnutls_hash_get_algo_len(algorithm);
+}
+
+int gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
+                   const void *text, size_t textlen, void *digest)
+{
+  return _gnutls_hash_fast(algorithm, text, textlen, digest);
 }
diff --git a/lib/crypto.c b/lib/crypto.c
index a2db9e0..6a201e5 100644
--- a/lib/crypto.c
+++ b/lib/crypto.c
@@ -225,7 +225,7 @@ gnutls_crypto_rnd_register2 (int priority, int version,
 }
 
 /**
- * gnutls_crypto_single_digest_register2 - register a MAC algorithm
+ * gnutls_crypto_single_mac_register2 - register a MAC algorithm
  * @algorithm: is the gnutls algorithm identifier
  * @priority: is the priority of the algorithm
  * @version: should be set to %GNUTLS_CRYPTO_API_VERSION
@@ -239,16 +239,16 @@ gnutls_crypto_rnd_register2 (int priority, int version,
  * This function should be called before gnutls_global_init().
  *
  * For simplicity you can use the convenience
- * gnutls_crypto_single_digest_register() macro.
+ * gnutls_crypto_single_mac_register() macro.
  *
  * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
  *
  * Since: 2.6.0
  **/
 int
-gnutls_crypto_single_digest_register2 (gnutls_digest_algorithm_t algorithm,
+gnutls_crypto_single_mac_register2 (gnutls_mac_algorithm_t algorithm,
                                    int priority, int version,
-                                   const gnutls_crypto_digest_st * s)
+                                   const gnutls_crypto_mac_st * s)
 {
   if (version != GNUTLS_CRYPTO_API_VERSION)
     {
@@ -259,13 +259,55 @@ gnutls_crypto_single_digest_register2 
(gnutls_digest_algorithm_t algorithm,
   return _algo_register (&glob_ml, algorithm, priority, s);
 }
 
-const gnutls_crypto_digest_st *
-_gnutls_get_crypto_mac (gnutls_digest_algorithm_t algo)
+const gnutls_crypto_mac_st *
+_gnutls_get_crypto_mac (gnutls_mac_algorithm_t algo)
 {
   return _get_algo (&glob_ml, algo);
 }
 
 /**
+ * gnutls_crypto_single_digest_register2 - register a digest algorithm
+ * @algorithm: is the gnutls algorithm identifier
+ * @priority: is the priority of the algorithm
+ * @version: should be set to %GNUTLS_CRYPTO_API_VERSION
+ * @s: is a structure holding new algorithms's data
+ *
+ * This function will register a digest (hash) algorithm to be used by
+ * gnutls.  Any algorithm registered will override the included
+ * algorithms and by convention kernel implemented algorithms have
+ * priority of 90.  The algorithm with the lowest priority will be
+ * used by gnutls.
+ *
+ * This function should be called before gnutls_global_init().
+ *
+ * For simplicity you can use the convenience
+ * gnutls_crypto_single_digest_register() macro.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ *
+ * Since: 2.6.0
+ **/
+int
+gnutls_crypto_single_digest_register2 (gnutls_digest_algorithm_t algorithm,
+                                      int priority, int version,
+                                      const gnutls_crypto_digest_st * s)
+{
+  if (version != GNUTLS_CRYPTO_API_VERSION)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+    }
+
+  return _algo_register (&glob_dl, algorithm, priority, s);
+}
+
+const gnutls_crypto_digest_st *
+_gnutls_get_crypto_digest (gnutls_digest_algorithm_t algo)
+{
+  return _get_algo (&glob_dl, algo);
+}
+
+/**
  * gnutls_crypto_bigint_register2 - register a bigint interface
  * @priority: is the priority of the interface
  * @version: should be set to %GNUTLS_CRYPTO_API_VERSION
@@ -395,7 +437,7 @@ gnutls_crypto_cipher_register2 (int priority, int version,
 }
 
 /**
- * gnutls_crypto_digest_register2 - register a mac interface
+ * gnutls_crypto_mac_register2 - register a mac interface
  * @priority: is the priority of the mac interface
  * @version: should be set to %GNUTLS_CRYPTO_API_VERSION
  * @s: is a structure holding new interface's data
@@ -416,8 +458,8 @@ gnutls_crypto_cipher_register2 (int priority, int version,
  * Since: 2.6.0
  **/
 int
-gnutls_crypto_digest_register2 (int priority, int version,
-                            const gnutls_crypto_digest_st * s)
+gnutls_crypto_mac_register2 (int priority, int version,
+                            const gnutls_crypto_mac_st * s)
 {
   if (version != GNUTLS_CRYPTO_API_VERSION)
     {
@@ -435,3 +477,43 @@ gnutls_crypto_digest_register2 (int priority, int version,
   return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
 }
 
+/**
+ * gnutls_crypto_digest_register2 - register a digest interface
+ * @priority: is the priority of the digest interface
+ * @version: should be set to %GNUTLS_CRYPTO_API_VERSION
+ * @s: is a structure holding new interface's data
+ *
+ * This function will register a digest interface to be used by
+ * gnutls. Any interface registered will override the included engine
+ * and by convention kernel implemented interfaces should have
+ * priority of 90. The interface with the lowest priority will be used
+ * by gnutls.
+ *
+ * This function should be called before gnutls_global_init().
+ *
+ * For simplicity you can use the convenience
+ * gnutls_crypto_digest_register() macro.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ *
+ * Since: 2.6.0
+ **/
+int
+gnutls_crypto_digest_register2 (int priority, int version,
+                               const gnutls_crypto_digest_st * s)
+{
+  if (version != GNUTLS_CRYPTO_API_VERSION)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+    }
+
+  if (crypto_digest_prio > priority)
+    {
+      memcpy (&_gnutls_digest_ops, s, sizeof (*s));
+      crypto_digest_prio = priority;
+      return 0;
+    }
+
+  return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
+}
diff --git a/lib/crypto.h b/lib/crypto.h
index 31be199..508fce6 100644
--- a/lib/crypto.h
+++ b/lib/crypto.h
@@ -26,7 +26,8 @@
 # define CRYPTO_H
 
 const gnutls_crypto_cipher_st *_gnutls_get_crypto_cipher( 
gnutls_cipher_algorithm_t algo);
-const gnutls_crypto_digest_st *_gnutls_get_crypto_mac( 
gnutls_digest_algorithm_t algo);
+const gnutls_crypto_digest_st *_gnutls_get_crypto_digest( 
gnutls_digest_algorithm_t algo);
+const gnutls_crypto_mac_st *_gnutls_get_crypto_mac( gnutls_mac_algorithm_t 
algo);
 void _gnutls_crypto_deregister(void);
 
 #endif /* CRYPTO_H */
diff --git a/lib/ext_session_ticket.c b/lib/ext_session_ticket.c
index 42ffadd..e7a2891 100644
--- a/lib/ext_session_ticket.c
+++ b/lib/ext_session_ticket.c
@@ -55,24 +55,24 @@ static int
 digest_ticket (const gnutls_datum_t * key, struct ticket *ticket,
               opaque * digest)
 {
-  hash_hd_st digest_hd;
+  digest_hd_st digest_hd;
   uint16_t length16;
   int ret;
 
-  ret = _gnutls_hash_init (&digest_hd, GNUTLS_MAC_SHA256, key->data,
+  ret = _gnutls_hmac_init (&digest_hd, GNUTLS_MAC_SHA256, key->data,
                           key->size);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
-  _gnutls_hash (&digest_hd, ticket->key_name, KEY_NAME_SIZE);
-  _gnutls_hash (&digest_hd, ticket->IV, IV_SIZE);
+  _gnutls_hmac (&digest_hd, ticket->key_name, KEY_NAME_SIZE);
+  _gnutls_hmac (&digest_hd, ticket->IV, IV_SIZE);
   length16 = _gnutls_conv_uint16 (ticket->encrypted_state_len);
-  _gnutls_hash (&digest_hd, &length16, 2);
-  _gnutls_hash (&digest_hd, ticket->encrypted_state,
+  _gnutls_hmac (&digest_hd, &length16, 2);
+  _gnutls_hmac (&digest_hd, ticket->encrypted_state,
                ticket->encrypted_state_len);
-  _gnutls_hash_deinit (&digest_hd, digest);
+  _gnutls_hmac_deinit (&digest_hd, digest);
 
   return 0;
 }
@@ -461,7 +461,7 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, 
int again)
   struct ticket ticket;
   uint16_t ticket_len;
   gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
-  gnutls_digest_algorithm_t write_mac_algorithm;
+  gnutls_mac_algorithm_t write_mac_algorithm;
   gnutls_compression_method_t write_compression_algorithm;
 
 #define SAVE_WRITE_SECURITY_PARAMETERS                                 \
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index d9a0d83..0faf4ac 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -222,7 +222,7 @@ struct gnutls_hash_entry
 {
   const char *name;
   const char *oid;
-  gnutls_digest_algorithm_t id;
+  gnutls_mac_algorithm_t id;
   size_t key_size;             /* in case of mac */
 };
 typedef struct gnutls_hash_entry gnutls_hash_entry;
@@ -240,7 +240,7 @@ static const gnutls_hash_entry hash_algorithms[] = {
 };
 
 /* Keep the contents of this struct the same as the previous one. */
-static const gnutls_digest_algorithm_t supported_macs[] = {
+static const gnutls_mac_algorithm_t supported_macs[] = {
   GNUTLS_MAC_SHA1,
   GNUTLS_MAC_MD5,
   GNUTLS_MAC_SHA256,
@@ -346,7 +346,7 @@ typedef struct
   cipher_suite_st id;
   gnutls_cipher_algorithm_t block_algorithm;
   gnutls_kx_algorithm_t kx_algorithm;
-  gnutls_digest_algorithm_t mac_algorithm;
+  gnutls_mac_algorithm_t mac_algorithm;
   gnutls_protocol_t version;   /* this cipher suite is supported
                                 * from 'version' and above;
                                 */
@@ -677,7 +677,7 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
 
 int
 _gnutls_mac_priority (gnutls_session_t session,
-                     gnutls_digest_algorithm_t algorithm)
+                     gnutls_mac_algorithm_t algorithm)
 {                              /* actually returns the priority */
   unsigned int i;
   for (i = 0; i < session->internals.priorities.mac.algorithms; i++)
@@ -692,13 +692,13 @@ _gnutls_mac_priority (gnutls_session_t session,
  * gnutls_mac_get_name - Returns a string with the name of the specified mac 
algorithm
  * @algorithm: is a MAC algorithm
  *
- * Convert a #gnutls_digest_algorithm_t value to a string.
+ * Convert a #gnutls_mac_algorithm_t value to a string.
  *
  * Returns: a string that contains the name of the specified MAC
  *   algorithm, or %NULL.
  **/
 const char *
-gnutls_mac_get_name (gnutls_digest_algorithm_t algorithm)
+gnutls_mac_get_name (gnutls_mac_algorithm_t algorithm)
 {
   const char *ret = NULL;
 
@@ -712,16 +712,16 @@ gnutls_mac_get_name (gnutls_digest_algorithm_t algorithm)
  * gnutls_mac_get_id - Returns the gnutls id of the specified in string 
algorithm
  * @name: is a MAC algorithm name
  *
- * Convert a string to a #gnutls_digest_algorithm_t value.  The names are
+ * Convert a string to a #gnutls_mac_algorithm_t value.  The names are
  * compared in a case insensitive way.
  *
- * Returns: a #gnutls_digest_algorithm_t id of the specified MAC
+ * Returns: a #gnutls_mac_algorithm_t id of the specified MAC
  *   algorithm string, or %GNUTLS_MAC_UNKNOWN on failures.
  **/
-gnutls_digest_algorithm_t
+gnutls_mac_algorithm_t
 gnutls_mac_get_id (const char *name)
 {
-  gnutls_digest_algorithm_t ret = GNUTLS_MAC_UNKNOWN;
+  gnutls_mac_algorithm_t ret = GNUTLS_MAC_UNKNOWN;
 
   GNUTLS_HASH_LOOP (if (strcasecmp (p->name, name) == 0) ret = p->id);
 
@@ -738,7 +738,7 @@ gnutls_mac_get_id (const char *name)
  *   given MAC algorithm is invalid.
  **/
 size_t
-gnutls_mac_get_key_size (gnutls_digest_algorithm_t algorithm)
+gnutls_mac_get_key_size (gnutls_mac_algorithm_t algorithm)
 {
   size_t ret = 0;
 
@@ -756,17 +756,17 @@ gnutls_mac_get_key_size (gnutls_digest_algorithm_t 
algorithm)
  * example, MD2 is not supported as a cipher suite, but is supported
  * for other purposes (e.g., X.509 signature verification or similar).
  *
- * Returns: Return a zero-terminated list of #gnutls_digest_algorithm_t
+ * Returns: Return a zero-terminated list of #gnutls_mac_algorithm_t
  *   integers indicating the available MACs.
  **/
-const gnutls_digest_algorithm_t *
+const gnutls_mac_algorithm_t *
 gnutls_mac_list (void)
 {
   return supported_macs;
 }
 
 const char *
-_gnutls_x509_mac_to_oid (gnutls_digest_algorithm_t algorithm)
+_gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t algorithm)
 {
   const char *ret = NULL;
 
@@ -776,10 +776,10 @@ _gnutls_x509_mac_to_oid (gnutls_digest_algorithm_t 
algorithm)
   return ret;
 }
 
-gnutls_digest_algorithm_t
+gnutls_mac_algorithm_t
 _gnutls_x509_oid2mac_algorithm (const char *oid)
 {
-  gnutls_digest_algorithm_t ret = 0;
+  gnutls_mac_algorithm_t ret = 0;
 
   GNUTLS_HASH_LOOP (if (p->oid && strcmp (oid, p->oid) == 0)
                    {
@@ -793,7 +793,7 @@ _gnutls_x509_oid2mac_algorithm (const char *oid)
 
 
 int
-_gnutls_mac_is_ok (gnutls_digest_algorithm_t algorithm)
+_gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm)
 {
   ssize_t ret = -1;
   GNUTLS_HASH_ALG_LOOP (ret = p->id);
@@ -1327,7 +1327,7 @@ _gnutls_cipher_suite_get_kx_algo (const cipher_suite_st * 
suite)
 
 }
 
-gnutls_digest_algorithm_t
+gnutls_mac_algorithm_t
 _gnutls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
 {                              /* In bytes */
   int ret = 0;
@@ -1362,7 +1362,7 @@ _gnutls_cipher_suite_get_name (cipher_suite_st * suite)
 const char *
 gnutls_cipher_suite_get_name (gnutls_kx_algorithm_t kx_algorithm,
                              gnutls_cipher_algorithm_t cipher_algorithm,
-                             gnutls_digest_algorithm_t mac_algorithm)
+                             gnutls_mac_algorithm_t mac_algorithm)
 {
   const char *ret = NULL;
 
@@ -1398,7 +1398,7 @@ gnutls_cipher_suite_info (size_t idx,
                          char *cs_id,
                          gnutls_kx_algorithm_t * kx,
                          gnutls_cipher_algorithm_t * cipher,
-                         gnutls_digest_algorithm_t * mac,
+                         gnutls_mac_algorithm_t * mac,
                          gnutls_protocol_t * version)
 {
   if (idx >= CIPHER_SUITES_COUNT)
@@ -1529,9 +1529,9 @@ _gnutls_compare_algo (gnutls_session_t session, const 
void *i_A1,
     _gnutls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A1);
   gnutls_cipher_algorithm_t cA2 =
     _gnutls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A2);
-  gnutls_digest_algorithm_t mA1 =
+  gnutls_mac_algorithm_t mA1 =
     _gnutls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A1);
-  gnutls_digest_algorithm_t mA2 =
+  gnutls_mac_algorithm_t mA2 =
     _gnutls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A2);
 
   int p1 = (_gnutls_kx_priority (session, kA1) + 1) * 64;
@@ -1811,7 +1811,7 @@ struct gnutls_sign_entry
   const char *oid;
   gnutls_sign_algorithm_t id;
   gnutls_pk_algorithm_t pk;
-  gnutls_digest_algorithm_t mac;
+  gnutls_mac_algorithm_t mac;
   /* See RFC 5246 HashAlgorithm and SignatureAlgorithm
      for values to use in aid struct. */
   sign_algorithm_st aid;
@@ -1960,7 +1960,7 @@ _gnutls_x509_oid2sign_algorithm (const char *oid)
 }
 
 gnutls_sign_algorithm_t
-_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t 
mac)
+_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_mac_algorithm_t mac)
 {
   gnutls_sign_algorithm_t ret = 0;
 
@@ -1976,7 +1976,7 @@ _gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, 
gnutls_digest_algorithm_t mac
 
 const char *
 _gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
-                         gnutls_digest_algorithm_t mac)
+                         gnutls_mac_algorithm_t mac)
 {
   gnutls_sign_algorithm_t sign;
   const char *ret = NULL;
@@ -1989,10 +1989,10 @@ _gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
   return ret;
 }
 
-gnutls_digest_algorithm_t
+gnutls_mac_algorithm_t
 _gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t sign)
 {
-  gnutls_digest_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
+  gnutls_mac_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
 
   GNUTLS_SIGN_ALG_LOOP (ret = p->mac);
 
diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h
index aa9038a..2b59908 100644
--- a/lib/gnutls_algorithms.h
+++ b/lib/gnutls_algorithms.h
@@ -46,9 +46,9 @@ int _gnutls_version_has_explicit_iv (gnutls_protocol_t 
version);
 int _gnutls_version_has_variable_padding (gnutls_protocol_t version);
 
 /* Functions for MACs. */
-int _gnutls_mac_is_ok (gnutls_digest_algorithm_t algorithm);
-gnutls_digest_algorithm_t _gnutls_x509_oid2mac_algorithm (const char *oid);
-const char *_gnutls_x509_mac_to_oid (gnutls_digest_algorithm_t mac);
+int _gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm);
+gnutls_mac_algorithm_t _gnutls_x509_oid2mac_algorithm (const char *oid);
+const char *_gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t mac);
 
 /* Functions for cipher suites. */
 int _gnutls_supported_ciphersuites (gnutls_session_t session,
@@ -61,7 +61,7 @@ gnutls_cipher_algorithm_t 
_gnutls_cipher_suite_get_cipher_algo (const
                                                                * algorithm);
 gnutls_kx_algorithm_t _gnutls_cipher_suite_get_kx_algo (const cipher_suite_st
                                                        * algorithm);
-gnutls_digest_algorithm_t _gnutls_cipher_suite_get_mac_algo (const
+gnutls_mac_algorithm_t _gnutls_cipher_suite_get_mac_algo (const
                                                          cipher_suite_st *
                                                          algorithm);
 gnutls_protocol_t _gnutls_cipher_suite_get_version (const cipher_suite_st *
@@ -101,17 +101,17 @@ 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_digest_algorithm_t mac);
+                                                gnutls_mac_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_digest_algorithm_t mac);
+                                     gnutls_mac_algorithm_t mac);
 gnutls_sign_algorithm_t _gnutls_tls_aid_to_sign (const sign_algorithm_st* aid);
 sign_algorithm_st _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign);
-gnutls_digest_algorithm_t _gnutls_sign_get_hash_algorithm 
(gnutls_sign_algorithm_t);
+gnutls_mac_algorithm_t _gnutls_sign_get_hash_algorithm 
(gnutls_sign_algorithm_t);
 gnutls_pk_algorithm_t _gnutls_sign_get_pk_algorithm (gnutls_sign_algorithm_t);
 
 int _gnutls_mac_priority (gnutls_session_t session,
-                         gnutls_digest_algorithm_t algorithm);
+                         gnutls_mac_algorithm_t algorithm);
 int _gnutls_cipher_priority (gnutls_session_t session,
                             gnutls_cipher_algorithm_t algorithm);
 int _gnutls_kx_priority (gnutls_session_t session,
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index 746a58b..5eb71bd 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -193,8 +193,8 @@ _gnutls_decrypt (gnutls_session_t session, opaque * 
ciphertext,
   return ret;
 }
 
-inline static int
-mac_init (hash_hd_st * td, gnutls_digest_algorithm_t mac, opaque * secret,
+static inline int
+mac_init (digest_hd_st * td, gnutls_mac_algorithm_t mac, opaque * secret,
          int secret_size, int ver)
 {
   int ret = 0;
@@ -210,14 +210,27 @@ mac_init (hash_hd_st * td, gnutls_digest_algorithm_t mac, 
opaque * secret,
     }
   else
     {                          /* TLS 1.x */
-      ret = _gnutls_hash_init (td, mac, secret, secret_size);
+      ret = _gnutls_hmac_init (td, mac, secret, secret_size);
     }
 
   return ret;
 }
 
-static void
-mac_deinit (hash_hd_st * td, opaque * res, int ver)
+static inline void
+mac_hash (digest_hd_st * td, void * data, int data_size, int ver)
+{
+  if (ver == GNUTLS_SSL3)
+    {                          /* SSL 3.0 */
+      _gnutls_hash (td, data, data_size);
+    }
+  else
+    {
+      _gnutls_hmac (td, data, data_size);
+    }
+}
+
+static inline void
+mac_deinit (digest_hd_st * td, opaque * res, int ver)
 {
   if (ver == GNUTLS_SSL3)
     {                          /* SSL 3.0 */
@@ -225,7 +238,7 @@ mac_deinit (hash_hd_st * td, opaque * res, int ver)
     }
   else
     {
-      _gnutls_hash_deinit (td, res);
+      _gnutls_hmac_deinit (td, res);
     }
 }
 
@@ -344,7 +357,7 @@ _gnutls_compressed2ciphertext (gnutls_session_t session,
 
   if (session->security_parameters.write_mac_algorithm != GNUTLS_MAC_NULL)
     {                          /* actually when the algorithm in not the NULL 
one */
-      hash_hd_st td;
+      digest_hd_st td;
 
       ret = mac_init (&td, session->security_parameters.write_mac_algorithm,
                  session->connection_state.write_mac_secret.data,
@@ -356,8 +369,8 @@ _gnutls_compressed2ciphertext (gnutls_session_t session,
           return ret;
         }
       preamble_size = make_preamble( UINT64DATA 
(session->connection_state.write_sequence_number), type, c_length, ver, 
preamble);
-      _gnutls_hash (&td, preamble, preamble_size);
-      _gnutls_hash (&td, compressed.data, compressed.size);
+      mac_hash (&td, preamble, preamble_size, ver);
+      mac_hash (&td, compressed.data, compressed.size, ver);
       mac_deinit (&td, MAC, ver);
     }
 
@@ -541,7 +554,7 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
    */
   if (session->security_parameters.read_mac_algorithm != GNUTLS_MAC_NULL)
     {
-      hash_hd_st td;
+      digest_hd_st td;
 
       ret = mac_init (&td, session->security_parameters.read_mac_algorithm,
                  session->connection_state.read_mac_secret.data,
@@ -554,9 +567,9 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
         }
 
       preamble_size = make_preamble( UINT64DATA 
(session->connection_state.read_sequence_number), type, c_length, ver, 
preamble);
-      _gnutls_hash (&td, preamble, preamble_size);
+      mac_hash (&td, preamble, preamble_size, ver);
       if (length > 0)
-       _gnutls_hash (&td, ciphertext.data, length);
+       mac_hash (&td, ciphertext.data, length, ver);
 
       mac_deinit (&td, MAC, ver);
     }
diff --git a/lib/gnutls_cipher_int.h b/lib/gnutls_cipher_int.h
index d6c3018..ab6db04 100644
--- a/lib/gnutls_cipher_int.h
+++ b/lib/gnutls_cipher_int.h
@@ -31,7 +31,7 @@ extern int crypto_cipher_prio;
 extern gnutls_crypto_cipher_st _gnutls_cipher_ops;
 
 typedef struct {
-  const gnutls_crypto_cipher_st* cc;
+  const gnutls_crypto_single_cipher_st* cc;
   void* ctx;
 } reg_hd;
 
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index 4dbc44d..d3fd256 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -345,7 +345,7 @@ _gnutls_set_read_keys (gnutls_session_t session)
   int IV_size;
   int key_size, export_flag;
   gnutls_cipher_algorithm_t algo;
-  gnutls_digest_algorithm_t mac_algo;
+  gnutls_mac_algorithm_t mac_algo;
 
   mac_algo = session->security_parameters.read_mac_algorithm;
   algo = session->security_parameters.read_bulk_cipher_algorithm;
@@ -366,7 +366,7 @@ _gnutls_set_write_keys (gnutls_session_t session)
   int IV_size;
   int key_size, export_flag;
   gnutls_cipher_algorithm_t algo;
-  gnutls_digest_algorithm_t mac_algo;
+  gnutls_mac_algorithm_t mac_algo;
 
   mac_algo = session->security_parameters.write_mac_algorithm;
   algo = session->security_parameters.write_bulk_cipher_algorithm;
@@ -934,7 +934,7 @@ _gnutls_set_kx (gnutls_session_t session, 
gnutls_kx_algorithm_t algo)
 
 /* Sets the specified mac algorithm into pending session */
 int
-_gnutls_set_read_mac (gnutls_session_t session, gnutls_digest_algorithm_t algo)
+_gnutls_set_read_mac (gnutls_session_t session, gnutls_mac_algorithm_t algo)
 {
 
   if (_gnutls_mac_is_ok (algo) == 0)
@@ -958,7 +958,7 @@ _gnutls_set_read_mac (gnutls_session_t session, 
gnutls_digest_algorithm_t algo)
 }
 
 int
-_gnutls_set_write_mac (gnutls_session_t session, gnutls_digest_algorithm_t 
algo)
+_gnutls_set_write_mac (gnutls_session_t session, gnutls_mac_algorithm_t algo)
 {
 
   if (_gnutls_mac_is_ok (algo) == 0)
diff --git a/lib/gnutls_constate.h b/lib/gnutls_constate.h
index 771c03a..f58c8b1 100644
--- a/lib/gnutls_constate.h
+++ b/lib/gnutls_constate.h
@@ -28,11 +28,11 @@ int _gnutls_write_connection_state_init (gnutls_session_t 
session);
 int _gnutls_set_write_cipher (gnutls_session_t session,
                              gnutls_cipher_algorithm_t algo);
 int _gnutls_set_write_mac (gnutls_session_t session,
-                          gnutls_digest_algorithm_t algo);
+                          gnutls_mac_algorithm_t algo);
 int _gnutls_set_read_cipher (gnutls_session_t session,
                             gnutls_cipher_algorithm_t algo);
 int _gnutls_set_read_mac (gnutls_session_t session,
-                         gnutls_digest_algorithm_t algo);
+                         gnutls_mac_algorithm_t algo);
 int _gnutls_set_read_compression (gnutls_session_t session,
                                  gnutls_compression_method_t algo);
 int _gnutls_set_write_compression (gnutls_session_t session,
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 300ee28..aca1aab 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -166,8 +166,8 @@ static int
 _gnutls_ssl3_finished (gnutls_session_t session, int type, opaque * ret)
 {
   const int siz = SSL_MSG_LEN;
-  hash_hd_st td_md5;
-  hash_hd_st td_sha;
+  digest_hd_st td_md5;
+  digest_hd_st td_sha;
   const char *mesg;
   int rc;
 
@@ -235,8 +235,8 @@ _gnutls_finished (gnutls_session_t session, int type, void 
*ret)
   opaque concat[MAX_HASH_SIZE + 16 /*MD5 */ ];
   size_t len = 20 + 16;
   const char *mesg;
-  hash_hd_st td_md5;
-  hash_hd_st td_sha;
+  digest_hd_st td_md5;
+  digest_hd_st td_sha;
   int rc;
 
   if (session->security_parameters.handshake_mac_handle_type ==
@@ -2301,7 +2301,7 @@ _gnutls_handshake_hash_init (gnutls_session_t session)
        {
          ret =
            _gnutls_hash_init (&session->internals.handshake_mac_handle.
-                              tls10.md5, GNUTLS_MAC_MD5, NULL, 0);
+                              tls10.md5, GNUTLS_MAC_MD5);
 
          if (ret < 0)
            {
@@ -2311,7 +2311,7 @@ _gnutls_handshake_hash_init (gnutls_session_t session)
 
          ret =
            _gnutls_hash_init (&session->internals.handshake_mac_handle.
-                              tls10.sha, GNUTLS_MAC_SHA1, NULL, 0);
+                              tls10.sha, GNUTLS_MAC_SHA1);
          if (ret < 0)
            {
              gnutls_assert ();
@@ -2328,7 +2328,7 @@ _gnutls_handshake_hash_init (gnutls_session_t session)
             SHA256. */
          ret =
            _gnutls_hash_init (&session->internals.handshake_mac_handle.
-                              tls12.sha256, GNUTLS_DIG_SHA256, NULL, 0);
+                              tls12.sha256, GNUTLS_DIG_SHA256);
          if (ret < 0)
            {
              gnutls_assert ();
@@ -2337,7 +2337,7 @@ _gnutls_handshake_hash_init (gnutls_session_t session)
 
          ret =
            _gnutls_hash_init (&session->internals.handshake_mac_handle.
-                              tls12.sha1, GNUTLS_DIG_SHA1, NULL, 0);
+                              tls12.sha1, GNUTLS_DIG_SHA1);
          if (ret < 0)
            {
              gnutls_assert ();
diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c
index 682cb23..288de91 100644
--- a/lib/gnutls_hash_int.c
+++ b/lib/gnutls_hash_int.c
@@ -57,8 +57,45 @@ digest_length (gnutls_digest_algorithm_t algo)
     }
 }
 
-/* HMAC interface */
+int
+_gnutls_hash_init (digest_hd_st * dig, gnutls_digest_algorithm_t algorithm)
+{
+  int result;
+  const gnutls_crypto_digest_st *cc = NULL;
+
+  dig->algorithm = algorithm;
+
+  /* check if a digest has been registered 
+   */
+  cc = _gnutls_get_crypto_digest (algorithm);
+  if (cc != NULL)
+    {
+      dig->registered = 1;
+      dig->hd.rh.cc = cc;
+      if (cc->init (algorithm, &dig->hd.rh.ctx) < 0)
+       {
+         gnutls_assert ();
+         return GNUTLS_E_HASH_FAILED;
+       }
+      dig->active = 1;
+      return 0;
+    }
+
+  dig->registered = 0;
 
+  result = _gnutls_digest_ops.init (algorithm, &dig->hd.gc);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+  dig->active = 1;
+  return 0;
+}
+
+/* returns the output size of the given hash/mac algorithm
+ */
 int
 _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t algorithm)
 {
@@ -66,13 +103,97 @@ _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t 
algorithm)
 }
 
 int
-_gnutls_hash_fast (gnutls_digest_algorithm_t algorithm, const void *key,
-                  int keylen, const void *text, size_t textlen, void *digest)
+_gnutls_hash (digest_hd_st * handle, const void *text, size_t textlen)
+{
+  if (textlen > 0)
+    {
+      if (handle->registered)
+       {
+         return handle->hd.rh.cc->hash (handle->hd.rh.ctx, text, textlen);
+       }
+      return _gnutls_digest_ops.hash (handle->hd.gc, text, textlen);
+    }
+  return 0;
+}
+
+int
+_gnutls_hash_copy (digest_hd_st * dst, digest_hd_st * src)
+{
+  int result;
+
+  memset (dst, 0, sizeof (*dst));
+  dst->algorithm = src->algorithm;
+  dst->registered = src->registered;
+  dst->active = 1;
+
+  if (src->registered)
+    {
+      dst->hd.rh.cc = src->hd.rh.cc;
+      return src->hd.rh.cc->copy (&dst->hd.rh.ctx, src->hd.rh.ctx);
+    }
+
+  result = _gnutls_digest_ops.copy (&dst->hd.gc, src->hd.gc);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+  return 0;
+}
+
+/* when the current output is needed without calling deinit
+ */
+void
+_gnutls_hash_output (digest_hd_st * handle, void *digest)
+{
+  size_t maclen;
+
+  maclen = _gnutls_hash_get_algo_len (handle->algorithm);
+
+  if (handle->registered && handle->hd.rh.ctx != NULL)
+    {
+      if (digest != NULL)
+       handle->hd.rh.cc->output (handle->hd.rh.ctx, digest, maclen);
+      return;
+    }
+
+  if (digest != NULL)
+    {
+      _gnutls_digest_ops.output (handle->hd.gc, digest, maclen);
+    }
+}
+
+void
+_gnutls_hash_deinit (digest_hd_st * handle, void *digest)
 {
-  hash_hd_st dig;
+  if (handle->active != 1)
+    {
+      return;
+    }
+
+  if (digest != NULL)
+    _gnutls_hash_output (handle, digest);
+
+  handle->active = 0;
+
+  if (handle->registered && handle->hd.rh.ctx != NULL)
+    {
+      handle->hd.rh.cc->deinit (handle->hd.rh.ctx);
+      return;
+    }
+
+  _gnutls_digest_ops.deinit (handle->hd.gc);
+}
+
+int
+_gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
+                  const void *text, size_t textlen, void *digest)
+{
+  digest_hd_st dig;
   int ret;
 
-  ret = _gnutls_hash_init (&dig, algorithm, key, keylen);
+  ret = _gnutls_hash_init (&dig, algorithm);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -91,12 +212,47 @@ _gnutls_hash_fast (gnutls_digest_algorithm_t algorithm, 
const void *key,
   return 0;
 }
 
+
+/* HMAC interface */
+
+int
+_gnutls_hmac_get_algo_len (gnutls_mac_algorithm_t algorithm)
+{
+  return digest_length (algorithm);
+}
+
+int
+_gnutls_hmac_fast (gnutls_mac_algorithm_t algorithm, const void *key,
+                  int keylen, const void *text, size_t textlen, void *digest)
+{
+  digest_hd_st dig;
+  int ret;
+
+  ret = _gnutls_hmac_init (&dig, algorithm, key, keylen);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      return ret;
+    }
+
+  ret = _gnutls_hmac (&dig, text, textlen);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      _gnutls_hmac_deinit (&dig, NULL);
+      return ret;
+    }
+
+  _gnutls_hmac_deinit (&dig, digest);
+  return 0;
+}
+
 int
-_gnutls_hash_init (hash_hd_st * dig, gnutls_digest_algorithm_t algorithm,
+_gnutls_hmac_init (digest_hd_st * dig, gnutls_mac_algorithm_t algorithm,
                   const void *key, int keylen)
 {
   int result;
-  const gnutls_crypto_digest_st *cc = NULL;
+  const gnutls_crypto_mac_st *cc = NULL;
 
   dig->algorithm = algorithm;
   dig->key = key;
@@ -110,31 +266,40 @@ _gnutls_hash_init (hash_hd_st * dig, 
gnutls_digest_algorithm_t algorithm,
       dig->registered = 1;
 
       dig->hd.rh.cc = cc;
-      if (cc->init (algorithm, &dig->hd.rh.ctx, key, keylen) < 0)
+      if (cc->init (algorithm, &dig->hd.rh.ctx) < 0)
        {
          gnutls_assert ();
          return GNUTLS_E_HASH_FAILED;
        }
 
+      if (cc->setkey (dig->hd.rh.ctx, key, keylen) < 0)
+       {
+         gnutls_assert ();
+         cc->deinit (dig->hd.rh.ctx);
+         return GNUTLS_E_HASH_FAILED;
+       }
+
       dig->active = 1;
       return 0;
     }
 
   dig->registered = 0;
 
-  result = _gnutls_mac_ops.init (algorithm, &dig->hd.gc, key, keylen);
+  result = _gnutls_mac_ops.init (algorithm, &dig->hd.gc);
   if (result < 0)
     {
       gnutls_assert ();
       return result;
     }
 
+  _gnutls_mac_ops.setkey (dig->hd.gc, key, keylen);
+
   dig->active = 1;
   return 0;
 }
 
 int
-_gnutls_hash (hash_hd_st * handle, const void *text, size_t textlen)
+_gnutls_hmac (digest_hd_st * handle, const void *text, size_t textlen)
 {
   if (textlen > 0)
     {
@@ -148,11 +313,11 @@ _gnutls_hash (hash_hd_st * handle, const void *text, 
size_t textlen)
 }
 
 void
-_gnutls_hash_output (hash_hd_st * handle, void *digest)
+_gnutls_hmac_output (digest_hd_st * handle, void *digest)
 {
   int maclen;
 
-  maclen = _gnutls_hash_get_algo_len (handle->algorithm);
+  maclen = _gnutls_hmac_get_algo_len (handle->algorithm);
 
   if (handle->registered && handle->hd.rh.ctx != NULL)
     {
@@ -167,45 +332,8 @@ _gnutls_hash_output (hash_hd_st * handle, void *digest)
     }
 }
 
-int
-_gnutls_hash_copy (hash_hd_st * dst, hash_hd_st * src)
-{
-  int result;
-
-  memset (dst, 0, sizeof (*dst));
-  dst->algorithm = src->algorithm;
-  dst->registered = src->registered;
-  dst->active = 1;
-
-  if (src->registered)
-   {
-      dst->hd.rh.cc = src->hd.rh.cc;
-      return src->hd.rh.cc->copy (&dst->hd.rh.ctx, src->hd.rh.ctx);
-    }
-
-  result = _gnutls_mac_ops.copy (&dst->hd.gc, src->hd.gc);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      return result;
-    }
-
-  return 0;
-}
-
-void _gnutls_hash_reset (hash_hd_st * handle)
-{
-  if (handle->registered && handle->hd.rh.ctx != NULL)
-    {
-      handle->hd.rh.cc->reset (handle->hd.rh.ctx);
-      return;
-    }
-
-    _gnutls_mac_ops.reset (handle->hd.gc);
-}
-
 void
-_gnutls_hash_deinit (hash_hd_st * handle, void *digest)
+_gnutls_hmac_deinit (digest_hd_st * handle, void *digest)
 {
   if (handle->active != 1)
     {
@@ -213,7 +341,7 @@ _gnutls_hash_deinit (hash_hd_st * handle, void *digest)
     }
 
   if (digest)
-    _gnutls_hash_output (handle, digest);
+    _gnutls_hmac_output (handle, digest);
 
   handle->active = 0;
   if (handle->registered && handle->hd.rh.ctx != NULL)
@@ -226,7 +354,7 @@ _gnutls_hash_deinit (hash_hd_st * handle, void *digest)
 }
 
 inline static int
-get_padsize (gnutls_digest_algorithm_t algorithm)
+get_padsize (gnutls_mac_algorithm_t algorithm)
 {
   switch (algorithm)
     {
@@ -244,7 +372,7 @@ get_padsize (gnutls_digest_algorithm_t algorithm)
  */
 
 int
-_gnutls_mac_init_ssl3 (hash_hd_st * ret, gnutls_digest_algorithm_t algorithm,
+_gnutls_mac_init_ssl3 (digest_hd_st * ret, gnutls_mac_algorithm_t algorithm,
                       void *key, int keylen)
 {
   opaque ipad[48];
@@ -259,7 +387,7 @@ _gnutls_mac_init_ssl3 (hash_hd_st * ret, 
gnutls_digest_algorithm_t algorithm,
 
   memset (ipad, 0x36, padsize);
 
-  result = _gnutls_hash_init (ret, algorithm, NULL, 0);
+  result = _gnutls_hash_init (ret, algorithm);
   if (result < 0)
     {
       gnutls_assert ();
@@ -277,10 +405,10 @@ _gnutls_mac_init_ssl3 (hash_hd_st * ret, 
gnutls_digest_algorithm_t algorithm,
 }
 
 void
-_gnutls_mac_deinit_ssl3 (hash_hd_st * handle, void *digest)
+_gnutls_mac_deinit_ssl3 (digest_hd_st * handle, void *digest)
 {
   opaque ret[MAX_HASH_SIZE];
-  hash_hd_st td;
+  digest_hd_st td;
   opaque opad[48];
   int padsize;
   int block, rc;
@@ -295,7 +423,7 @@ _gnutls_mac_deinit_ssl3 (hash_hd_st * handle, void *digest)
 
   memset (opad, 0x5C, padsize);
 
-  rc = _gnutls_hash_init (&td, handle->algorithm, NULL, 0);
+  rc = _gnutls_hash_init (&td, handle->algorithm);
   if (rc < 0)
     {
       gnutls_assert ();
@@ -307,7 +435,7 @@ _gnutls_mac_deinit_ssl3 (hash_hd_st * handle, void *digest)
     _gnutls_hash (&td, handle->key, handle->keysize);
 
   _gnutls_hash (&td, opad, padsize);
-  block = _gnutls_hash_get_algo_len (handle->algorithm);
+  block = _gnutls_hmac_get_algo_len (handle->algorithm);
   _gnutls_hash_deinit (handle, ret);   /* get the previous hash */
   _gnutls_hash (&td, ret, block);
 
@@ -317,12 +445,12 @@ _gnutls_mac_deinit_ssl3 (hash_hd_st * handle, void 
*digest)
 }
 
 void
-_gnutls_mac_deinit_ssl3_handshake (hash_hd_st * handle,
+_gnutls_mac_deinit_ssl3_handshake (digest_hd_st * handle,
                                   void *digest, opaque * key,
                                   uint32_t key_size)
 {
   opaque ret[MAX_HASH_SIZE];
-  hash_hd_st td;
+  digest_hd_st td;
   opaque opad[48];
   opaque ipad[48];
   int padsize;
@@ -338,7 +466,7 @@ _gnutls_mac_deinit_ssl3_handshake (hash_hd_st * handle,
   memset (opad, 0x5C, padsize);
   memset (ipad, 0x36, padsize);
 
-  rc = _gnutls_hash_init (&td, handle->algorithm, NULL, 0);
+  rc = _gnutls_hash_init (&td, handle->algorithm);
   if (rc < 0)
     {
       gnutls_assert ();
@@ -349,7 +477,7 @@ _gnutls_mac_deinit_ssl3_handshake (hash_hd_st * handle,
     _gnutls_hash (&td, key, key_size);
 
   _gnutls_hash (&td, opad, padsize);
-  block = _gnutls_hash_get_algo_len (handle->algorithm);
+  block = _gnutls_hmac_get_algo_len (handle->algorithm);
 
   if (key_size > 0)
     _gnutls_hash (handle, key, key_size);
@@ -370,14 +498,14 @@ ssl3_sha (int i, opaque * secret, int secret_len,
   int j, ret;
   opaque text1[26];
 
-  hash_hd_st td;
+  digest_hd_st td;
 
   for (j = 0; j < i + 1; j++)
     {
       text1[j] = 65 + i;       /* A==65 */
     }
 
-  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1, NULL, 0);
+  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -397,10 +525,10 @@ ssl3_md5 (int i, opaque * secret, int secret_len,
          opaque * rnd, int rnd_len, void *digest)
 {
   opaque tmp[MAX_HASH_SIZE];
-  hash_hd_st td;
+  digest_hd_st td;
   int ret;
 
-  ret = _gnutls_hash_init (&td, GNUTLS_MAC_MD5, NULL, 0);
+  ret = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -429,11 +557,11 @@ _gnutls_ssl3_hash_md5 (const void *first, int first_len,
                       int ret_len, opaque * ret)
 {
   opaque digest[MAX_HASH_SIZE];
-  hash_hd_st td;
+  digest_hd_st td;
   int block = _gnutls_hash_get_algo_len (GNUTLS_MAC_MD5);
   int rc;
 
-  rc = _gnutls_hash_init (&td, GNUTLS_MAC_MD5, NULL, 0);
+  rc = _gnutls_hash_init (&td, GNUTLS_MAC_MD5);
   if (rc < 0)
     {
       gnutls_assert ();
diff --git a/lib/gnutls_hash_int.h b/lib/gnutls_hash_int.h
index bc39a1a..7041665 100644
--- a/lib/gnutls_hash_int.h
+++ b/lib/gnutls_hash_int.h
@@ -32,10 +32,13 @@
 /* for message digests */
 
 extern int crypto_mac_prio;
-extern gnutls_crypto_digest_st _gnutls_mac_ops;
+extern gnutls_crypto_mac_st _gnutls_mac_ops;
+
+extern int crypto_digest_prio;
+extern gnutls_crypto_digest_st _gnutls_digest_ops;
 
 typedef struct {
-  const gnutls_crypto_digest_st* cc;
+  const gnutls_crypto_mac_st* cc;
   void* ctx;
 } digest_reg_hd;
 
@@ -46,28 +49,40 @@ typedef struct
     void* gc; /* when not registered */
     digest_reg_hd rh; /* when registered */
   } hd;
-  gnutls_digest_algorithm_t algorithm;
+  gnutls_mac_algorithm_t algorithm;
   const void *key;
   int keysize;
   int active;
-} hash_hd_st;
+} digest_hd_st;
 
 /* basic functions */
-int _gnutls_hash_init (hash_hd_st*, gnutls_digest_algorithm_t algorithm,
+int _gnutls_hmac_init (digest_hd_st*, gnutls_mac_algorithm_t algorithm,
                            const void *key, int keylen);
-int _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t algorithm);
-int _gnutls_hash (hash_hd_st * handle, const void *text, size_t textlen);
-int _gnutls_hash_fast( gnutls_digest_algorithm_t algorithm, const void* key, 
int keylen, 
+int _gnutls_hmac_get_algo_len (gnutls_mac_algorithm_t algorithm);
+int _gnutls_hmac (digest_hd_st* handle, const void *text,
+                 size_t textlen);
+
+int _gnutls_hmac_fast( gnutls_mac_algorithm_t algorithm, const void* key, int 
keylen, 
        const void* text, size_t textlen, void* digest);
 
-void _gnutls_hash_deinit (hash_hd_st* handle, void *digest);
-void _gnutls_hash_output (hash_hd_st* handle, void *digest);
-void _gnutls_hash_reset (hash_hd_st * handle);
+void _gnutls_hmac_deinit (digest_hd_st* handle, void *digest);
+void _gnutls_hmac_output (digest_hd_st* handle, void *digest);
+
+int _gnutls_hash_init (digest_hd_st*, gnutls_digest_algorithm_t algorithm);
+int _gnutls_hash_get_algo_len (gnutls_digest_algorithm_t algorithm);
+int _gnutls_hash (digest_hd_st* handle, const void *text,
+                 size_t textlen);
+void _gnutls_hash_deinit (digest_hd_st* handle, void *digest);
+void _gnutls_hash_output (digest_hd_st* handle, void *digest);
 
+int
+_gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
+                   const void *text, size_t textlen, void *digest);
+                   
 /* help functions */
-int _gnutls_mac_init_ssl3 (hash_hd_st*, gnutls_digest_algorithm_t algorithm, 
void *key,
+int _gnutls_mac_init_ssl3 (digest_hd_st*, gnutls_mac_algorithm_t algorithm, 
void *key,
                                int keylen);
-void _gnutls_mac_deinit_ssl3 (hash_hd_st* handle, void *digest);
+void _gnutls_mac_deinit_ssl3 (digest_hd_st* handle, void *digest);
 
 int _gnutls_ssl3_generate_random (void *secret, int secret_len,
                                  void *rnd, int random_len, int bytes,
@@ -76,9 +91,9 @@ int _gnutls_ssl3_hash_md5 (const void *first, int first_len,
                           const void *second, int second_len,
                           int ret_len, opaque * ret);
 
-void _gnutls_mac_deinit_ssl3_handshake (hash_hd_st* handle, void *digest,
+void _gnutls_mac_deinit_ssl3_handshake (digest_hd_st* handle, void *digest,
                                        opaque * key, uint32_t key_size);
 
-int _gnutls_hash_copy (hash_hd_st* dst_handle, hash_hd_st * src_handle);
+int _gnutls_hash_copy (digest_hd_st* dst_handle, digest_hd_st * src_handle);
 
 #endif /* GNUTLS_HASH_INT_H */
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index c2ad8f5..a097bea 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -133,7 +133,7 @@ typedef struct
 #define DECR_LENGTH_RET(len, x, RET) do { len-=x; if (len<0) {gnutls_assert(); 
return RET;} } while (0)
 #define DECR_LENGTH_COM(len, x, COM) do { len-=x; if (len<0) {gnutls_assert(); 
COM;} } while (0)
 
-#define HASH2MAC(x) ((gnutls_digest_algorithm_t)x)
+#define HASH2MAC(x) ((gnutls_mac_algorithm_t)x)
 
 #define GNUTLS_POINTER_TO_INT(_) ((int) GNUTLS_POINTER_TO_INT_CAST (_))
 #define GNUTLS_INT_TO_POINTER(_) ((void*) GNUTLS_POINTER_TO_INT_CAST (_))
@@ -366,11 +366,11 @@ typedef struct
    * null cipher and we don't
    */
   gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
-  gnutls_digest_algorithm_t read_mac_algorithm;
+  gnutls_mac_algorithm_t read_mac_algorithm;
   gnutls_compression_method_t read_compression_algorithm;
 
   gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
-  gnutls_digest_algorithm_t write_mac_algorithm;
+  gnutls_mac_algorithm_t write_mac_algorithm;
   gnutls_compression_method_t write_compression_algorithm;
   handshake_mac_type_t handshake_mac_handle_type; /* one of HANDSHAKE_TYPE_10 
and HANDSHAKE_TYPE_12 */
 
@@ -491,13 +491,13 @@ typedef struct
     {
       struct 
         {
-          hash_hd_st sha;      /* hash of the handshake messages */
-          hash_hd_st md5;      /* hash of the handshake messages */
+          digest_hd_st sha;    /* hash of the handshake messages */
+          digest_hd_st md5;    /* hash of the handshake messages */
         } tls10;
       struct
         {
-          hash_hd_st sha1;     /* hash of the handshake messages for TLS 1.2+ 
*/
-          hash_hd_st sha256;   /* hash of the handshake messages for TLS 1.2+ 
*/
+          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 */
diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c
index 4c21564..7fab2c7 100644
--- a/lib/gnutls_priority.c
+++ b/lib/gnutls_priority.c
@@ -111,7 +111,7 @@ gnutls_kx_set_priority (gnutls_session_t session, const int 
*list)
 /**
   * gnutls_mac_set_priority - Sets the priority on the mac algorithms 
supported by gnutls.
   * @session: is a #gnutls_session_t structure.
-  * @list: is a 0 terminated list of gnutls_digest_algorithm_t elements.
+  * @list: is a 0 terminated list of gnutls_mac_algorithm_t elements.
   *
   * Sets the priority on the mac algorithms supported by gnutls.
   * Priority is higher for elements specified before others.
diff --git a/lib/gnutls_psk_netconf.c b/lib/gnutls_psk_netconf.c
index 85978d9..967a964 100644
--- a/lib/gnutls_psk_netconf.c
+++ b/lib/gnutls_psk_netconf.c
@@ -54,7 +54,7 @@ gnutls_psk_netconf_derive_key (const char *password,
   const char netconf_key_pad[] = "Key Pad for Netconf";
   size_t sha1len = _gnutls_hash_get_algo_len (GNUTLS_DIG_SHA1);
   size_t hintlen = strlen (psk_identity_hint);
-  hash_hd_st dig;
+  digest_hd_st dig;
   char *inner;
   size_t innerlen;
   int rc;
@@ -65,7 +65,7 @@ gnutls_psk_netconf_derive_key (const char *password,
    *
    */
 
-  rc = _gnutls_hash_init (&dig, GNUTLS_DIG_SHA1, NULL, 0);
+  rc = _gnutls_hash_init (&dig, GNUTLS_DIG_SHA1);
   if (rc < 0)
     {
       gnutls_assert ();
@@ -107,7 +107,7 @@ gnutls_psk_netconf_derive_key (const char *password,
 
   memcpy (inner + sha1len, psk_identity_hint, hintlen);
 
-  rc = _gnutls_hash_init (&dig, GNUTLS_DIG_SHA1, NULL, 0);
+  rc = _gnutls_hash_init (&dig, GNUTLS_DIG_SHA1);
   if (rc < 0)
     {
       gnutls_assert ();
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index d7d6d11..f75a705 100644
--- a/lib/gnutls_sig.c
+++ b/lib/gnutls_sig.c
@@ -57,7 +57,7 @@ _gnutls_tls_sign (gnutls_session_t session,
  * See RFC 5246 DigitallySigned for the actual format.
  */
 static int
-_gnutls_rsa_encode_sig (gnutls_digest_algorithm_t algo,
+_gnutls_rsa_encode_sig (gnutls_mac_algorithm_t algo,
                        const gnutls_datum_t * hash,
                        gnutls_datum_t * signature)
 {
@@ -132,7 +132,7 @@ _gnutls_handshake_sign_data (gnutls_session_t session, 
gnutls_cert * cert,
 {
   gnutls_datum_t dconcat;
   int ret;
-  hash_hd_st td_sha;
+  digest_hd_st td_sha;
   opaque concat[MAX_SIG_SIZE];
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
   gnutls_digest_algorithm_t hash_algo;
@@ -146,7 +146,7 @@ _gnutls_handshake_sign_data (gnutls_session_t session, 
gnutls_cert * cert,
       return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
     }
 
-  ret = _gnutls_hash_init (&td_sha, hash_algo, NULL, 0);
+  ret = _gnutls_hash_init (&td_sha, hash_algo);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -164,9 +164,9 @@ _gnutls_handshake_sign_data (gnutls_session_t session, 
gnutls_cert * cert,
     case GNUTLS_PK_RSA:
       if (!_gnutls_version_has_selectable_prf (ver))
        {
-         hash_hd_st td_md5;
+         digest_hd_st td_md5;
 
-         ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5, NULL, 0);
+         ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
          if (ret < 0)
            {
              gnutls_assert ();
@@ -386,8 +386,8 @@ _gnutls_handshake_verify_data (gnutls_session_t session, 
gnutls_cert * cert,
 {
   gnutls_datum_t dconcat;
   int ret;
-  hash_hd_st td_md5;
-  hash_hd_st td_sha;
+  digest_hd_st td_md5;
+  digest_hd_st td_sha;
   opaque concat[MAX_SIG_SIZE];
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
   gnutls_digest_algorithm_t hash_algo = GNUTLS_DIG_SHA1;
@@ -401,7 +401,7 @@ _gnutls_handshake_verify_data (gnutls_session_t session, 
gnutls_cert * cert,
 
   if (!_gnutls_version_has_selectable_prf (ver))
     {
-      ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5, NULL, 0);
+      ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -418,7 +418,7 @@ _gnutls_handshake_verify_data (gnutls_session_t session, 
gnutls_cert * cert,
   if (algo != GNUTLS_SIGN_UNKNOWN)
     hash_algo = _gnutls_sign_get_hash_algorithm (algo);
 
-  ret = _gnutls_hash_init (&td_sha, hash_algo, NULL, 0);
+  ret = _gnutls_hash_init (&td_sha, hash_algo);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -481,11 +481,11 @@ _gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t 
session,
 {
   int ret;
   opaque concat[MAX_SIG_SIZE];
-  hash_hd_st td;
+  digest_hd_st td;
   gnutls_datum_t dconcat;
   gnutls_sign_algorithm_t _sign_algo;
   gnutls_digest_algorithm_t hash_algo;
-  hash_hd_st *handshake_td;
+  digest_hd_st *handshake_td;
 
   handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
   hash_algo = handshake_td->algorithm;
@@ -541,8 +541,8 @@ _gnutls_handshake_verify_cert_vrfy (gnutls_session_t 
session,
 {
   int ret;
   opaque concat[MAX_SIG_SIZE];
-  hash_hd_st td_md5;
-  hash_hd_st td_sha;
+  digest_hd_st td_md5;
+  digest_hd_st td_sha;
   gnutls_datum_t dconcat;
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
 
@@ -626,10 +626,10 @@ _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t 
session,
   gnutls_datum_t dconcat;
   int ret;
   opaque concat[MAX_SIG_SIZE];
-  hash_hd_st td;
+  digest_hd_st td;
   gnutls_sign_algorithm_t sign_algo;
   gnutls_digest_algorithm_t hash_algo;
-  hash_hd_st *handshake_td;
+  digest_hd_st *handshake_td;
 
   handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
   hash_algo = handshake_td->algorithm;
@@ -707,8 +707,8 @@ _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
   gnutls_datum_t dconcat;
   int ret;
   opaque concat[MAX_SIG_SIZE];
-  hash_hd_st td_md5;
-  hash_hd_st td_sha;
+  digest_hd_st td_md5;
+  digest_hd_st td_sha;
   gnutls_protocol_t ver = gnutls_protocol_get_version (session);
 
   if (session->security_parameters.handshake_mac_handle_type ==
diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c
index 4e2a270..3131083 100644
--- a/lib/gnutls_srp.c
+++ b/lib/gnutls_srp.c
@@ -166,7 +166,7 @@ _gnutls_calc_srp_u (bigint_t A, bigint_t B, bigint_t n)
   size_t b_size, a_size;
   opaque *holder, hd[MAX_HASH_SIZE];
   size_t holder_size, hash_size, n_size;
-  hash_hd_st td;
+  digest_hd_st td;
   int ret;
   bigint_t res;
 
@@ -191,7 +191,7 @@ _gnutls_calc_srp_u (bigint_t A, bigint_t B, bigint_t n)
   _gnutls_mpi_print (A, &holder[n_size - a_size], &a_size);
   _gnutls_mpi_print (B, &holder[n_size + n_size - b_size], &b_size);
 
-  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1, NULL, 0);
+  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
   if (ret < 0)
     {
       gnutls_free (holder);
@@ -289,13 +289,13 @@ _gnutls_calc_srp_sha (const char *username, const char 
*password,
                      opaque * salt, int salt_size, size_t * size,
                      void *digest)
 {
-  hash_hd_st td;
+  digest_hd_st td;
   opaque res[MAX_HASH_SIZE];
   int ret;
 
   *size = 20;
 
-  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1, NULL, 0);
+  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
   if (ret < 0)
     {
       return GNUTLS_E_MEMORY_ERROR;
@@ -306,7 +306,7 @@ _gnutls_calc_srp_sha (const char *username, const char 
*password,
 
   _gnutls_hash_deinit (&td, res);
 
-  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1, NULL, 0);
+  ret = _gnutls_hash_init (&td, GNUTLS_MAC_SHA1);
   if (ret < 0)
     {
       return GNUTLS_E_MEMORY_ERROR;
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index a1f574f..3ba533b 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -113,9 +113,9 @@ gnutls_kx_get (gnutls_session_t session)
  * Get currently used MAC algorithm.
  *
  * Returns: the currently used mac algorithm, a
- *   #gnutls_digest_algorithm_t value.
+ *   #gnutls_mac_algorithm_t value.
  **/
-gnutls_digest_algorithm_t
+gnutls_mac_algorithm_t
 gnutls_mac_get (gnutls_session_t session)
 {
   return session->security_parameters.read_mac_algorithm;
@@ -761,22 +761,22 @@ gnutls_handshake_set_private_extensions (gnutls_session_t 
session, int allow)
 }
 
 inline static int
-_gnutls_cal_PRF_A (gnutls_digest_algorithm_t algorithm,
+_gnutls_cal_PRF_A (gnutls_mac_algorithm_t algorithm,
                   const void *secret, int secret_size,
                   const void *seed, int seed_size, void *result)
 {
-  hash_hd_st td1;
+  digest_hd_st td1;
   int ret;
 
-  ret = _gnutls_hash_init (&td1, algorithm, secret, secret_size);
+  ret = _gnutls_hmac_init (&td1, algorithm, secret, secret_size);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  _gnutls_hash (&td1, seed, seed_size);
-  _gnutls_hash_deinit (&td1, result);
+  _gnutls_hmac (&td1, seed, seed_size);
+  _gnutls_hmac_deinit (&td1, result);
 
   return 0;
 }
@@ -787,13 +787,13 @@ _gnutls_cal_PRF_A (gnutls_digest_algorithm_t algorithm,
  * (used in the PRF function)
  */
 static int
-_gnutls_P_hash (gnutls_digest_algorithm_t algorithm,
+_gnutls_P_hash (gnutls_mac_algorithm_t algorithm,
                const opaque * secret, int secret_size,
                const opaque * seed, int seed_size,
                int total_bytes, opaque * ret)
 {
 
-  hash_hd_st td2;
+  digest_hd_st td2;
   int i, times, how, blocksize, A_size;
   opaque final[MAX_HASH_SIZE], Atmp[MAX_SEED_SIZE];
   int output_bytes, result;
@@ -804,7 +804,7 @@ _gnutls_P_hash (gnutls_digest_algorithm_t algorithm,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  blocksize = _gnutls_hash_get_algo_len (algorithm);
+  blocksize = _gnutls_hmac_get_algo_len (algorithm);
 
   output_bytes = 0;
   do
@@ -822,7 +822,7 @@ _gnutls_P_hash (gnutls_digest_algorithm_t algorithm,
 
   for (i = 0; i < times; i++)
     {
-      result = _gnutls_hash_init (&td2, algorithm, secret, secret_size);
+      result = _gnutls_hmac_init (&td2, algorithm, secret, secret_size);
       if (result < 0)
        {
          gnutls_assert ();
@@ -835,15 +835,15 @@ _gnutls_P_hash (gnutls_digest_algorithm_t algorithm,
                              A_size, Atmp)) < 0)
        {
          gnutls_assert ();
-         _gnutls_hash_deinit (&td2, final);
+         _gnutls_hmac_deinit (&td2, final);
          return result;
        }
 
       A_size = blocksize;
 
-      _gnutls_hash (&td2, Atmp, A_size);
-      _gnutls_hash (&td2, seed, seed_size);
-      _gnutls_hash_deinit (&td2, final);
+      _gnutls_hmac (&td2, Atmp, A_size);
+      _gnutls_hmac (&td2, seed, seed_size);
+      _gnutls_hmac_deinit (&td2, final);
 
       if ((1 + i) * blocksize < total_bytes)
        {
diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c
index 66bac34..baed5fa 100644
--- a/lib/gnutls_ui.c
+++ b/lib/gnutls_ui.c
@@ -557,7 +557,7 @@ gnutls_fingerprint (gnutls_digest_algorithm_t algo,
                    const gnutls_datum_t * data, void *result,
                    size_t * result_size)
 {
-  hash_hd_st td;
+  digest_hd_st td;
   int hash_len = _gnutls_hash_get_algo_len (HASH2MAC (algo));
 
   if (hash_len < 0 || (unsigned) hash_len > *result_size || result == NULL)
@@ -569,7 +569,7 @@ gnutls_fingerprint (gnutls_digest_algorithm_t algo,
 
   if (result)
     {
-      int ret = _gnutls_hash_init (&td, HASH2MAC (algo), NULL, 0);
+      int ret = _gnutls_hash_init (&td, HASH2MAC (algo));
       if (ret < 0)
        {
          gnutls_assert ();
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index ac67386..e7a3281 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -36,26 +36,35 @@ int gnutls_cipher_decrypt (const gnutls_cipher_hd_t handle, 
void *ciphertext,
 void gnutls_cipher_deinit (gnutls_cipher_hd_t handle);
 int gnutls_cipher_get_block_size (gnutls_cipher_algorithm_t algorithm);
 
-/* HMAC */
-typedef struct hash_hd_st* gnutls_hash_hd_t;
 
-/* if key is non null then HMAC instead of hash */
-int gnutls_hash_init (gnutls_hash_hd_t*, gnutls_mac_algorithm_t algorithm,
-                          const void *key, int keylen);
-int gnutls_hash_get_algo_len (gnutls_mac_algorithm_t algorithm);
-int gnutls_hash (gnutls_hash_hd_t handle, const void *text,
-                size_t textlen);
-int gnutls_hash_fast( gnutls_mac_algorithm_t algorithm, const void* key, int 
keylen,
-      const void* text, size_t textlen, void* digest);
-void gnutls_hash_deinit (gnutls_hash_hd_t handle, void *digest);
+typedef struct hash_hd_st* gnutls_hash_hd_t;
+typedef struct hmac_hd_st* gnutls_hmac_hd_t;
+
+int gnutls_hmac_init (gnutls_hmac_hd_t * dig, gnutls_digest_algorithm_t 
algorithm,
+                  const void *key, int keylen);
+int gnutls_hmac (gnutls_hmac_hd_t handle, const void *text, size_t textlen);
+void gnutls_hmac_output (gnutls_hmac_hd_t handle, void *digest);
+void gnutls_hmac_deinit (gnutls_hmac_hd_t handle, void *digest);
+int gnutls_hmac_get_len( gnutls_mac_algorithm_t algorithm);
+int gnutls_hmac_fast( gnutls_mac_algorithm_t algorithm, const void* key, int 
keylen, 
+       const void* text, size_t textlen, void* digest);
+
+int gnutls_hash_init (gnutls_hash_hd_t * dig, gnutls_digest_algorithm_t 
algorithm);
+int gnutls_hash (gnutls_hash_hd_t handle, const void *text, size_t textlen);
 void gnutls_hash_output (gnutls_hash_hd_t handle, void *digest);
-void gnutls_hash_reset (gnutls_hash_hd_t handle);
-
+void gnutls_hash_deinit (gnutls_hash_hd_t handle, void *digest);
+int gnutls_hash_get_len( gnutls_digest_algorithm_t algorithm);
+int gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
+                   const void *text, size_t textlen, void *digest);
 
 /* register ciphers */
 
 #define GNUTLS_CRYPTO_API_VERSION 0x02
 
+#define gnutls_crypto_single_cipher_st gnutls_crypto_cipher_st
+#define gnutls_crypto_single_mac_st gnutls_crypto_mac_st
+#define gnutls_crypto_single_digest_st gnutls_crypto_digest_st
+
 typedef struct
 {
   int (*init) (gnutls_cipher_algorithm_t, void **ctx);
@@ -70,13 +79,16 @@ typedef struct
 
 typedef struct
 {
-  int (*init) (gnutls_mac_algorithm_t, void **ctx, const void* key, size_t 
keysize);
+  int (*init) (gnutls_mac_algorithm_t, void **ctx);
+  int (*setkey) (void *ctx, const void *key, size_t keysize);
   int (*hash) (void *ctx, const void *text, size_t textsize);
   int (*copy) (void **dst_ctx, void *src_ctx);
   int (*output) (void *src_ctx, void *digest, size_t digestsize);
-  void (*reset) (void *ctx);
   void (*deinit) (void *ctx);
-} gnutls_crypto_digest_st;
+} gnutls_crypto_mac_st;
+
+/* the same... setkey should be null */
+typedef gnutls_crypto_mac_st gnutls_crypto_digest_st;
 
 typedef enum gnutls_rnd_level
 {
@@ -250,26 +262,36 @@ typedef struct gnutls_crypto_pk
 # define gnutls_crypto_single_cipher_register(algo, prio, st)          \
   gnutls_crypto_single_cipher_register2 (algo, prio, \
                                         GNUTLS_CRYPTO_API_VERSION, st)
-# define gnutls_crypto_single_digest_register(algo, prio, st)          \
-  gnutls_crypto_single_digest_register2 (algo, prio, \
+# define gnutls_crypto_single_mac_register(algo, prio, st)             \
+  gnutls_crypto_single_mac_register2 (algo, prio, \
                                      GNUTLS_CRYPTO_API_VERSION, st)
+# define gnutls_crypto_single_digest_register(algo, prio, st)          \
+  gnutls_crypto_single_digest_register2(algo, prio,                    \
+                                       GNUTLS_CRYPTO_API_VERSION, st)
 
 int gnutls_crypto_single_cipher_register2 (gnutls_cipher_algorithm_t algorithm,
                                           int priority, int version,
-                                          const gnutls_crypto_cipher_st *s);
-int gnutls_crypto_single_digest_register2 (gnutls_mac_algorithm_t algorithm,
+                                          const gnutls_crypto_single_cipher_st 
*s);
+int gnutls_crypto_single_mac_register2 (gnutls_mac_algorithm_t algorithm,
                                        int priority, int version,
-                                       const gnutls_crypto_digest_st * s);
+                                       const gnutls_crypto_single_mac_st * s);
+int gnutls_crypto_single_digest_register2 (gnutls_digest_algorithm_t algorithm,
+                                          int priority, int version,
+                                          const gnutls_crypto_single_digest_st 
*s);
 
 # define gnutls_crypto_cipher_register(prio, st)                       \
   gnutls_crypto_cipher_register2 (prio, GNUTLS_CRYPTO_API_VERSION, st)
-# define gnutls_crypto_digest_register(prio, st)                               
\
+# define gnutls_crypto_mac_register(prio, st)                          \
+  gnutls_crypto_mac_register2 (prio, GNUTLS_CRYPTO_API_VERSION, st)
+# define gnutls_crypto_digest_register(prio, st)                       \
   gnutls_crypto_digest_register2 (prio, GNUTLS_CRYPTO_API_VERSION, st)
 
 int gnutls_crypto_cipher_register2 (int priority, int version,
                                    const gnutls_crypto_cipher_st * s);
+int gnutls_crypto_mac_register2 (int priority, int version,
+                                const gnutls_crypto_mac_st * s);
 int gnutls_crypto_digest_register2 (int priority, int version,
-                                const gnutls_crypto_digest_st * s);
+                                   const gnutls_crypto_digest_st * s);
 
 # define gnutls_crypto_rnd_register(prio, st)                          \
   gnutls_crypto_rnd_register2 (prio, GNUTLS_CRYPTO_API_VERSION, st)
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 375669e..f148c16 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -127,34 +127,36 @@ extern "C" {
 
   typedef enum
   {
-    GNUTLS_DIG_UNKNOWN = 0,
-    GNUTLS_DIG_NULL = 1,
-    GNUTLS_DIG_MD5,
-    GNUTLS_DIG_SHA1,
-    GNUTLS_DIG_RMD160,
-    GNUTLS_DIG_MD2,
-    GNUTLS_DIG_SHA256,
-    GNUTLS_DIG_SHA384,
-    GNUTLS_DIG_SHA512,
-    GNUTLS_DIG_SHA224, /* unsupported in TLS */
+    GNUTLS_MAC_UNKNOWN = 0,
+    GNUTLS_MAC_NULL = 1,
+    GNUTLS_MAC_MD5,
+    GNUTLS_MAC_SHA1,
+    GNUTLS_MAC_RMD160,
+    GNUTLS_MAC_MD2,
+    GNUTLS_MAC_SHA256,
+    GNUTLS_MAC_SHA384,
+    GNUTLS_MAC_SHA512,
+    GNUTLS_MAC_SHA224, /* unused as MAC */
     /* If you add anything here, make sure you align with
-       gnutls_digest_algorithm_t, in particular SHA-224. */
-  } gnutls_digest_algorithm_t;
+       gnutls_digest_algorithm_t. */
+  } gnutls_mac_algorithm_t;
 
-  /* These are compatibility definitions.
+  /* The enumerations here should have the same value with
+     gnutls_mac_algorithm_t.
    */
-#define gnutls_mac_algorithm_t gnutls_digest_algorithm_t
-
-#define GNUTLS_MAC_UNKNOWN GNUTLS_DIG_UNKNOWN
-#define GNUTLS_MAC_NULL GNUTLS_DIG_NULL
-#define GNUTLS_MAC_MD5 GNUTLS_DIG_MD5
-#define GNUTLS_MAC_SHA1 GNUTLS_DIG_SHA1
-#define GNUTLS_MAC_RMD160 GNUTLS_DIG_RMD160
-#define GNUTLS_MAC_MD2 GNUTLS_DIG_MD2
-#define GNUTLS_MAC_SHA256 GNUTLS_DIG_SHA256
-#define GNUTLS_MAC_SHA384 GNUTLS_DIG_SHA384
-#define GNUTLS_MAC_SHA512 GNUTLS_DIG_SHA512
-#define GNUTLS_MAC_SHA224 GNUTLS_DIG_SHA224
+  typedef enum
+  {
+    GNUTLS_DIG_UNKNOWN = GNUTLS_MAC_UNKNOWN,
+    GNUTLS_DIG_NULL = GNUTLS_MAC_NULL,
+    GNUTLS_DIG_MD5 = GNUTLS_MAC_MD5,
+    GNUTLS_DIG_SHA1 = GNUTLS_MAC_SHA1,
+    GNUTLS_DIG_RMD160 = GNUTLS_MAC_RMD160,
+    GNUTLS_DIG_MD2 = GNUTLS_MAC_MD2,
+    GNUTLS_DIG_SHA256 = GNUTLS_MAC_SHA256,
+    GNUTLS_DIG_SHA384 = GNUTLS_MAC_SHA384,
+    GNUTLS_DIG_SHA512 = GNUTLS_MAC_SHA512,
+    GNUTLS_DIG_SHA224
+  } gnutls_digest_algorithm_t;
 
   /* exported for other gnutls headers. This is the maximum number of
    * algorithms (ciphers, kx or macs).
@@ -936,7 +938,7 @@ extern "C" {
 /* fingerprint 
  * Actually this function returns the hash of the given data.
  */
-  int gnutls_fingerprint (gnutls_mac_algorithm_t algo,
+  int gnutls_fingerprint (gnutls_digest_algorithm_t algo,
                          const gnutls_datum_t * data, void *result,
                          size_t * result_size);
 
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 5e73768..a937a92 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -586,12 +586,17 @@ GNUTLS_2_10
     gnutls_cipher_deinit;
     gnutls_cipher_get_block_size;
     gnutls_hash_init;
-    gnutls_hash_get_algo_len;
+    gnutls_hash_get_len;
     gnutls_hash;
     gnutls_hash_fast;
     gnutls_hash_deinit;
     gnutls_hash_output;
-    gnutls_hash_reset;
+    gnutls_hmac_init;
+    gnutls_hmac_get_len;
+    gnutls_hmac;
+    gnutls_hmac_fast;
+    gnutls_hmac_deinit;
+    gnutls_hmac_output;
 } GNUTLS_2_8;
 
 GNUTLS_PRIVATE {
diff --git a/lib/mac-libgcrypt.c b/lib/mac-libgcrypt.c
index 75f5fcc..e51ea70 100644
--- a/lib/mac-libgcrypt.c
+++ b/lib/mac-libgcrypt.c
@@ -31,12 +31,10 @@
 #include <gcrypt.h>
 
 static int
-wrap_gcry_mac_init (gnutls_digest_algorithm_t algo, void **ctx, const void* 
key, size_t keylen)
+wrap_gcry_mac_init (gnutls_mac_algorithm_t algo, void **ctx)
 {
   int err;
-  unsigned int flags = 0;
-  
-  if (key) flags = GCRY_MD_FLAG_HMAC;
+  unsigned int flags = GCRY_MD_FLAG_HMAC;
 
   switch (algo)
     {
@@ -66,9 +64,6 @@ wrap_gcry_mac_init (gnutls_digest_algorithm_t algo, void 
**ctx, const void* key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  if (key)
-    gcry_md_setkey ((gcry_md_hd_t) *ctx, key, keylen);
-
   if (err == 0)
     return 0;
 
@@ -77,6 +72,12 @@ wrap_gcry_mac_init (gnutls_digest_algorithm_t algo, void 
**ctx, const void* key,
 }
 
 static int
+wrap_gcry_md_setkey (void *ctx, const void *key, size_t keylen)
+{
+  return gcry_md_setkey ((gcry_md_hd_t) ctx, key, keylen);
+}
+
+static int
 wrap_gcry_md_write (void *ctx, const void *text, size_t textsize)
 {
   gcry_md_write (ctx, text, textsize);
@@ -96,6 +97,50 @@ wrap_gcry_md_close (void *hd)
 }
 
 static int
+wrap_gcry_hash_init (gnutls_mac_algorithm_t algo, void **ctx)
+{
+  int err;
+  unsigned int flags = 0;
+
+  switch (algo)
+    {
+    case GNUTLS_DIG_MD5:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_MD5, flags);
+      break;
+    case GNUTLS_DIG_SHA1:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_SHA1, flags);
+      break;
+    case GNUTLS_DIG_RMD160:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_RMD160, flags);
+      break;
+    case GNUTLS_DIG_MD2:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_MD2, flags);
+      break;
+    case GNUTLS_DIG_SHA256:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_SHA256, flags);
+      break;
+    case GNUTLS_DIG_SHA224:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_SHA224, flags);
+      break;
+    case GNUTLS_DIG_SHA384:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_SHA384, flags);
+      break;
+    case GNUTLS_DIG_SHA512:
+      err = gcry_md_open ((gcry_md_hd_t *) ctx, GCRY_MD_SHA512, flags);
+      break;
+    default:
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  if (err == 0)
+    return 0;
+
+  gnutls_assert ();
+  return GNUTLS_E_ENCRYPTION_FAILED;
+}
+
+static int
 wrap_gcry_mac_output (void *src_ctx, void *digest, size_t digestsize)
 {
   opaque *_digest = gcry_md_read (src_ctx, 0);
@@ -116,11 +161,21 @@ wrap_gcry_mac_output (void *src_ctx, void *digest, size_t 
digestsize)
 
 int crypto_mac_prio = INT_MAX;
 
-gnutls_crypto_digest_st _gnutls_mac_ops = {
+gnutls_crypto_mac_st _gnutls_mac_ops = {
   .init = wrap_gcry_mac_init,
+  .setkey = wrap_gcry_md_setkey,
   .hash = wrap_gcry_md_write,
   .copy = wrap_gcry_md_copy,
   .output = wrap_gcry_mac_output,
   .deinit = wrap_gcry_md_close,
 };
 
+int crypto_digest_prio = INT_MAX;
+
+gnutls_crypto_digest_st _gnutls_digest_ops = {
+  .init = wrap_gcry_hash_init,
+  .hash = wrap_gcry_md_write,
+  .copy = wrap_gcry_md_copy,
+  .output = wrap_gcry_mac_output,
+  .deinit = wrap_gcry_md_close,
+};
diff --git a/lib/opencdk/dummy.c b/lib/opencdk/dummy.c
index 6ee043a..0ede7ed 100644
--- a/lib/opencdk/dummy.c
+++ b/lib/opencdk/dummy.c
@@ -9,7 +9,7 @@
 cdk_error_t
 _cdk_proc_packets (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t data,
                   const char *output, cdk_stream_t outstream,
-                  hash_hd_st * md)
+                  digest_hd_st * md)
 {
   return 0;
 }
diff --git a/lib/opencdk/filters.h b/lib/opencdk/filters.h
index d110085..d5a63af 100644
--- a/lib/opencdk/filters.h
+++ b/lib/opencdk/filters.h
@@ -32,7 +32,7 @@ enum {
 
 typedef struct {
   cipher_hd_st hd;
-  hash_hd_st mdc;
+  digest_hd_st mdc;
   int mdc_method;
   u32 datalen;
   struct {
@@ -45,7 +45,7 @@ typedef struct {
 
 typedef struct {
   int digest_algo;
-  hash_hd_st md;
+  digest_hd_st md;
   int md_initialized;
 } md_filter_t;
 
@@ -61,7 +61,7 @@ typedef struct {
   cdk_lit_format_t mode;
   char *orig_filename; /* This original name of the input file. */
   char *filename;
-  hash_hd_st md;
+  digest_hd_st md;
   int md_initialized;
   struct {
     size_t on;
diff --git a/lib/opencdk/hash.c b/lib/opencdk/hash.c
index 320744f..21e0d4f 100644
--- a/lib/opencdk/hash.c
+++ b/lib/opencdk/hash.c
@@ -49,7 +49,7 @@ hash_encode (void *data, FILE * in, FILE * out)
 
   if (!mfx->md_initialized)
     {
-      err = _gnutls_hash_init (&mfx->md, mfx->digest_algo, NULL, 0);
+      err = _gnutls_hash_init (&mfx->md, mfx->digest_algo);
       if (err < 0)
        {
          gnutls_assert ();
diff --git a/lib/opencdk/kbnode.c b/lib/opencdk/kbnode.c
index f3e8c9a..cd8e939 100644
--- a/lib/opencdk/kbnode.c
+++ b/lib/opencdk/kbnode.c
@@ -578,7 +578,7 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte * buf, 
size_t * r_nbytes)
  * is extracted from it.
  **/
 cdk_error_t
-cdk_kbnode_hash (cdk_kbnode_t node, hash_hd_st * md, int is_v4,
+cdk_kbnode_hash (cdk_kbnode_t node, digest_hd_st * md, int is_v4,
                 cdk_packet_type_t pkttype, int flags)
 {
   cdk_packet_t pkt;
diff --git a/lib/opencdk/main.h b/lib/opencdk/main.h
index ca3c609..613bc94 100644
--- a/lib/opencdk/main.h
+++ b/lib/opencdk/main.h
@@ -108,7 +108,7 @@ FILE *_cdk_tmpfile (void);
 cdk_error_t _cdk_proc_packets (cdk_ctx_t hd, cdk_stream_t inp,
                               cdk_stream_t data,
                               const char *output, cdk_stream_t outstream,
-                              hash_hd_st*md);
+                              digest_hd_st*md);
 cdk_error_t _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx);
 
 /*-- pubkey.c --*/
@@ -125,10 +125,10 @@ void _cdk_pkt_detach_free (cdk_packet_t pkt, int 
*r_pkttype, void **ctx);
 
 /*-- sig-check.c --*/
 cdk_error_t _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
-                           hash_hd_st*digest, int * r_expired);
-cdk_error_t _cdk_hash_sig_data (cdk_pkt_signature_t sig, hash_hd_st*hd);
-cdk_error_t _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, 
hash_hd_st*md);
-cdk_error_t _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, hash_hd_st *md, 
+                           digest_hd_st*digest, int * r_expired);
+cdk_error_t _cdk_hash_sig_data (cdk_pkt_signature_t sig, digest_hd_st*hd);
+cdk_error_t _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, 
digest_hd_st*md);
+cdk_error_t _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, digest_hd_st *md, 
                              int use_fpr);
 cdk_error_t _cdk_pk_check_sig (cdk_keydb_hd_t hd,
                               cdk_kbnode_t knode, 
@@ -159,7 +159,7 @@ int _cdk_sig_hash_for (cdk_pkt_pubkey_t pk);
 void _cdk_trim_string (char * s, int canon);
 cdk_error_t _cdk_sig_create (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig);
 cdk_error_t _cdk_sig_complete (cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk,
-                              hash_hd_st *hd);
+                              digest_hd_st *hd);
 
 /*-- stream.c --*/
 void _cdk_stream_set_compress_algo (cdk_stream_t s, int algo);   
diff --git a/lib/opencdk/opencdk.h b/lib/opencdk/opencdk.h
index da0f0aa..0ba17af 100644
--- a/lib/opencdk/opencdk.h
+++ b/lib/opencdk/opencdk.h
@@ -960,7 +960,7 @@ cdk_kbnode_t cdk_kbnode_find_prev (cdk_kbnode_t root, 
cdk_kbnode_t node,
                                   cdk_packet_type_t pkttype);
 cdk_kbnode_t cdk_kbnode_find_next (cdk_kbnode_t node,
                                   cdk_packet_type_t pkttype);
-cdk_error_t cdk_kbnode_hash (cdk_kbnode_t node, hash_hd_st * md, int is_v4,
+cdk_error_t cdk_kbnode_hash (cdk_kbnode_t node, digest_hd_st * md, int is_v4,
                             cdk_packet_type_t pkttype, int flags);
 
 /* Check each signature in the key node and return a summary of the
@@ -989,7 +989,7 @@ cdk_error_t cdk_sklist_build (cdk_keylist_t * ret_skl,
                              int unlock, unsigned int use);
 void cdk_sklist_release (cdk_keylist_t skl);
 cdk_error_t cdk_sklist_write (cdk_keylist_t skl, cdk_stream_t outp,
-                             hash_hd_st * mdctx, int sigclass, int sigver);
+                             digest_hd_st * mdctx, int sigclass, int sigver);
 cdk_error_t cdk_sklist_write_onepass (cdk_keylist_t skl, cdk_stream_t outp,
                                      int sigclass, int mdalgo);
 
diff --git a/lib/opencdk/pubkey.c b/lib/opencdk/pubkey.c
index c37391f..0ee122b 100644
--- a/lib/opencdk/pubkey.c
+++ b/lib/opencdk/pubkey.c
@@ -421,7 +421,7 @@ _cdk_sk_get_csum (cdk_pkt_seckey_t sk)
 cdk_error_t
 cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr)
 {
-  hash_hd_st hd;
+  digest_hd_st hd;
   int md_algo;
   int dlen = 0;
   int err;
@@ -434,7 +434,7 @@ cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr)
   else
     md_algo = GNUTLS_DIG_SHA1;
   dlen = _gnutls_hash_get_algo_len (md_algo);
-  err = _gnutls_hash_init (&hd, md_algo, NULL, 0);
+  err = _gnutls_hash_init (&hd, md_algo);
   if (err < 0)
     return map_gnutls_error (err);
   _cdk_hash_pubkey (pk, &hd, 1);
diff --git a/lib/opencdk/sig-check.c b/lib/opencdk/sig-check.c
index c189947..5dc9da6 100644
--- a/lib/opencdk/sig-check.c
+++ b/lib/opencdk/sig-check.c
@@ -36,7 +36,7 @@
 /* Hash all multi precision integers of the key PK with the given
    message digest context MD. */
 static int
-hash_mpibuf (cdk_pubkey_t pk, hash_hd_st * md, int usefpr)
+hash_mpibuf (cdk_pubkey_t pk, digest_hd_st * md, int usefpr)
 {
   byte buf[MAX_MPI_BYTES];     /* FIXME: do not use hardcoded length. */
   size_t nbytes;
@@ -66,7 +66,7 @@ hash_mpibuf (cdk_pubkey_t pk, hash_hd_st * md, int usefpr)
    MD. The @usefpr param is only valid for version 3 keys because of
    the different way to calculate the fingerprint. */
 cdk_error_t
-_cdk_hash_pubkey (cdk_pubkey_t pk, hash_hd_st * md, int usefpr)
+_cdk_hash_pubkey (cdk_pubkey_t pk, digest_hd_st * md, int usefpr)
 {
   byte buf[12];
   size_t i, n, npkey;
@@ -113,7 +113,7 @@ _cdk_hash_pubkey (cdk_pubkey_t pk, hash_hd_st * md, int 
usefpr)
 /* Hash the user ID @uid with the given message digest @md.
    Use openpgp mode if @is_v4 is 1. */
 cdk_error_t
-_cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, hash_hd_st * md)
+_cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, digest_hd_st * md)
 {
   const byte *data;
   byte buf[5];
@@ -144,7 +144,7 @@ _cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, 
hash_hd_st * md)
 /* Hash all parts of the signature which are needed to derive
    the correct message digest to verify the sig. */
 cdk_error_t
-_cdk_hash_sig_data (cdk_pkt_signature_t sig, hash_hd_st * md)
+_cdk_hash_sig_data (cdk_pkt_signature_t sig, digest_hd_st * md)
 {
   byte buf[4];
   byte tmp;
@@ -227,7 +227,7 @@ cache_sig_result (cdk_pkt_signature_t sig, int res)
    Use the digest handle @digest. */
 cdk_error_t
 _cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
-               hash_hd_st * digest, int *r_expired)
+               digest_hd_st * digest, int *r_expired)
 {
   cdk_error_t rc;
   byte md[MAX_DIGEST_LEN];
@@ -272,7 +272,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
                   cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig,
                   char **ret_uid)
 {
-  hash_hd_st md;
+  digest_hd_st md;
   int err;
   cdk_pubkey_t pk;
   cdk_pkt_signature_t sig;
@@ -297,7 +297,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
   pk = knode->pkt->pkt.public_key;
   sig = snode->pkt->pkt.signature;
 
-  err = _gnutls_hash_init (&md, sig->digest_algo, NULL, 0);
+  err = _gnutls_hash_init (&md, sig->digest_algo);
   if (err < 0)
     {
       gnutls_assert ();
diff --git a/lib/opencdk/verify.c b/lib/opencdk/verify.c
index b2d046e..1b17940 100644
--- a/lib/opencdk/verify.c
+++ b/lib/opencdk/verify.c
@@ -170,7 +170,7 @@ static cdk_error_t
 file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
 {
   cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
-  hash_hd_st md;
+  digest_hd_st md;
   char buf[512], chk[512];
   const char *s;
   int i, is_signed = 0, nbytes;
@@ -241,7 +241,7 @@ file_verify_clearsign (cdk_ctx_t hd, const char *file, 
const char *output)
   if (!digest_algo)
     digest_algo = GNUTLS_DIG_MD5;
 
-  err = _gnutls_hash_init (&md, digest_algo, NULL, 0);
+  err = _gnutls_hash_init (&md, digest_algo);
   if (err < 0)
     {
       rc = map_gnutls_error (err);
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index a069be4..0702a2c 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -2293,7 +2293,7 @@ rsadsa_crq_get_key_id (gnutls_x509_crq_t crq, int pk,
   int params_size = MAX_PUBLIC_PARAMS_SIZE;
   int i, result = 0;
   gnutls_datum_t der = { NULL, 0 };
-  hash_hd_st hd;
+  digest_hd_st hd;
 
   result = _gnutls_x509_crq_get_mpis (crq, params, &params_size);
   if (result < 0)
@@ -2323,7 +2323,7 @@ rsadsa_crq_get_key_id (gnutls_x509_crq_t crq, int pk,
   else
     return GNUTLS_E_INTERNAL_ERROR;
 
-  result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1, NULL, 0);
+  result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (result < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/pbkdf2-sha1.c b/lib/x509/pbkdf2-sha1.c
index f45f4d5..f63a23f 100644
--- a/lib/x509/pbkdf2-sha1.c
+++ b/lib/x509/pbkdf2-sha1.c
@@ -172,10 +172,10 @@ _gnutls_pbkdf2_sha1 (const char *P, size_t Plen,
              tmp[Slen + 3] = (i & 0x000000ff) >> 0;
 
              rc =
-               _gnutls_hash_fast (GNUTLS_MAC_SHA1, P, Plen, tmp, tmplen, U);
+               _gnutls_hmac_fast (GNUTLS_MAC_SHA1, P, Plen, tmp, tmplen, U);
            }
          else
-           rc = _gnutls_hash_fast (GNUTLS_MAC_SHA1, P, Plen, U, hLen, U);
+           rc = _gnutls_hmac_fast (GNUTLS_MAC_SHA1, P, Plen, U, hLen, U);
 
          if (rc < 0)
            {
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index 6e04795..18d455d 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -871,7 +871,7 @@ gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const 
char *pass)
   opaque salt[8], key[20];
   int result;
   const int iter = 1;
-  hash_hd_st td1;
+  digest_hd_st td1;
   gnutls_datum_t tmp = { NULL, 0 };
   opaque sha_mac[20];
 
@@ -937,17 +937,17 @@ gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const 
char *pass)
 
   /* MAC the data
    */
-  result = _gnutls_hash_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
+  result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
   if (result < 0)
     {
       gnutls_assert ();
       goto cleanup;
     }
 
-  _gnutls_hash (&td1, tmp.data, tmp.size);
+  _gnutls_hmac (&td1, tmp.data, tmp.size);
   _gnutls_free_datum (&tmp);
 
-  _gnutls_hash_deinit (&td1, sha_mac);
+  _gnutls_hmac_deinit (&td1, sha_mac);
 
 
   result =
@@ -1005,7 +1005,7 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const 
char *pass)
   int result;
   unsigned int iter;
   int len;
-  hash_hd_st td1;
+  digest_hd_st td1;
   gnutls_datum_t tmp = { NULL, 0 }, salt =
   {
   NULL, 0};
@@ -1063,17 +1063,17 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const 
char *pass)
 
   /* MAC the data
    */
-  result = _gnutls_hash_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
+  result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
   if (result < 0)
     {
       gnutls_assert ();
       goto cleanup;
     }
 
-  _gnutls_hash (&td1, tmp.data, tmp.size);
+  _gnutls_hmac (&td1, tmp.data, tmp.size);
   _gnutls_free_datum (&tmp);
 
-  _gnutls_hash_deinit (&td1, sha_mac);
+  _gnutls_hmac_deinit (&td1, sha_mac);
 
   len = sizeof (sha_mac_orig);
   result =
diff --git a/lib/x509/pkcs12_encr.c b/lib/x509/pkcs12_encr.c
index e1ab6bb..5569eba 100644
--- a/lib/x509/pkcs12_encr.c
+++ b/lib/x509/pkcs12_encr.c
@@ -60,7 +60,7 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const opaque * 
salt,
 {
   int rc;
   unsigned int i, j;
-  hash_hd_st md;
+  digest_hd_st md;
   bigint_t num_b1 = NULL, num_ij = NULL;
   bigint_t mpi512 = NULL;
   unsigned int pwlen;
@@ -121,7 +121,7 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const opaque 
* salt,
 
   for (;;)
     {
-      rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1, NULL, 0);
+      rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
       if (rc < 0)
        {
          gnutls_assert ();
@@ -136,7 +136,7 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const opaque 
* salt,
       _gnutls_hash_deinit (&md, hash);
       for (i = 1; i < iter; i++)
        {
-         rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1, NULL, 0);
+         rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
          if (rc < 0)
            {
              gnutls_assert ();
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index c713e77..517e287 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -1402,7 +1402,7 @@ gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key,
                                size_t * output_data_size)
 {
   int result;
-  hash_hd_st hd;
+  digest_hd_st hd;
   gnutls_datum_t der = { NULL, 0 };
 
   if (key == NULL || key->crippled)
@@ -1442,7 +1442,7 @@ gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key,
   else
     return GNUTLS_E_INTERNAL_ERROR;
 
-  result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1, NULL, 0);
+  result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (result < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/sign.c b/lib/x509/sign.c
index 1b83dde..53e223c 100644
--- a/lib/x509/sign.c
+++ b/lib/x509/sign.c
@@ -52,7 +52,7 @@ encode_ber_digest_info (gnutls_digest_algorithm_t hash,
   int result;
   const char *algo;
 
-  algo = _gnutls_x509_mac_to_oid ((gnutls_digest_algorithm_t) hash);
+  algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
   if (algo == NULL)
     {
       gnutls_assert ();
@@ -133,10 +133,10 @@ pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const 
gnutls_datum_t * text,
 {
   int ret;
   opaque _digest[MAX_HASH_SIZE];
-  hash_hd_st hd;
+  digest_hd_st hd;
   gnutls_datum_t digest, info;
 
-  ret = _gnutls_hash_init (&hd, HASH2MAC (hash), NULL, 0);
+  ret = _gnutls_hash_init (&hd, HASH2MAC (hash));
   if (ret < 0)
     {
       gnutls_assert ();
@@ -177,10 +177,10 @@ dsa_sign (const gnutls_datum_t * text,
 {
   int ret;
   opaque _digest[MAX_HASH_SIZE];
-  hash_hd_st hd;
+  digest_hd_st hd;
   gnutls_datum_t digest;
 
-  ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1, NULL, 0);
+  ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 4b78480..2f8bc5c 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -553,7 +553,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
  */
 static int
 decode_ber_digest_info (const gnutls_datum_t * info,
-                       gnutls_digest_algorithm_t * hash,
+                       gnutls_mac_algorithm_t * hash,
                        opaque * digest, int *digest_size)
 {
   ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
@@ -635,11 +635,11 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
                       const gnutls_datum_t * signature, bigint_t * params,
                       int params_len)
 {
-  gnutls_digest_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
+  gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
   int ret;
   opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
   int digest_size;
-  hash_hd_st hd;
+  digest_hd_st hd;
   gnutls_datum_t decrypted;
 
   ret =
@@ -682,7 +682,7 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
          return GNUTLS_E_INVALID_REQUEST;
        }
 
-      ret = _gnutls_hash_init (&hd, hash, NULL, 0);
+      ret = _gnutls_hash_init (&hd, hash);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -715,7 +715,7 @@ dsa_verify_sig (const gnutls_datum_t * text,
   int ret;
   opaque _digest[MAX_HASH_SIZE];
   gnutls_datum_t digest;
-  hash_hd_st hd;
+  digest_hd_st hd;
 
   if (hash && hash->data && hash->size == 20)
     {
@@ -723,7 +723,7 @@ dsa_verify_sig (const gnutls_datum_t * text,
     }
   else
     {
-      ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1, NULL, 0);
+      ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -785,7 +785,7 @@ verify_sig (const gnutls_datum_t * tbs,
 }
 
 int
-_gnutls_x509_verify_algorithm (gnutls_digest_algorithm_t * hash,
+_gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
                               const gnutls_datum_t * signature,
                               const gnutls_x509_crt_t issuer)
 {
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 172a64b..dfd5787 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -2213,7 +2213,7 @@ rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
   int params_size = MAX_PUBLIC_PARAMS_SIZE;
   int i, result = 0;
   gnutls_datum_t der = { NULL, 0 };
-  hash_hd_st hd;
+  digest_hd_st hd;
 
   result = _gnutls_x509_crt_get_mpis (crt, params, &params_size);
   if (result < 0)
@@ -2243,7 +2243,7 @@ rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
   else
     return GNUTLS_E_INTERNAL_ERROR;
 
-  result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1, NULL, 0);
+  result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (result < 0)
     {
       gnutls_assert ();
@@ -2496,7 +2496,7 @@ gnutls_x509_crt_get_verify_algorithm (gnutls_x509_crt_t 
crt,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  return _gnutls_x509_verify_algorithm ((gnutls_digest_algorithm_t *) hash,
+  return _gnutls_x509_verify_algorithm ((gnutls_mac_algorithm_t *) hash,
                                        signature, crt);
 }
 
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index f3b3016..c749123 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -184,7 +184,7 @@ int _gnutls_parse_general_name (ASN1_TYPE src, const char 
*src_name,
 /* verify.c */
 int gnutls_x509_crt_is_issuer (gnutls_x509_crt_t cert,
                               gnutls_x509_crt_t issuer);
-int _gnutls_x509_verify_algorithm(gnutls_digest_algorithm_t *hash,
+int _gnutls_x509_verify_algorithm(gnutls_mac_algorithm_t *hash,
                                  const gnutls_datum_t * signature,
                                  const gnutls_x509_crt_t crt);
 int _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
diff --git a/libextra/fipsmd5.c b/libextra/fipsmd5.c
index a0853ba..d9e153a 100644
--- a/libextra/fipsmd5.c
+++ b/libextra/fipsmd5.c
@@ -27,6 +27,48 @@
 #include <md5.h>
 #include <hmac.h>
 
+static int
+md5init (gnutls_mac_algorithm_t mac, void **ctx)
+{
+  *ctx = gnutls_malloc (sizeof (struct md5_ctx));
+  if (!*ctx)
+    return GNUTLS_E_MEMORY_ERROR;
+  md5_init_ctx (*ctx);
+  return 0;
+}
+
+static int
+md5hash (void *ctx, const void *text, size_t textsize)
+{
+  md5_process_bytes (text, textsize, ctx);
+  return 0;
+}
+
+static int
+md5copy (void **dst_ctx, void *src_ctx)
+{
+  *dst_ctx = gnutls_malloc (sizeof (struct md5_ctx));
+  if (!*dst_ctx)
+    return GNUTLS_E_MEMORY_ERROR;
+  memcpy (*dst_ctx, src_ctx, sizeof (struct md5_ctx));
+  return 0;
+}
+
+static int
+md5output (void *src_ctx, void *digest, size_t digestsize)
+{
+  char out[MD5_DIGEST_SIZE];
+  md5_finish_ctx (src_ctx, out);
+  memcpy (digest, out, digestsize);
+  return 0;
+}
+
+static void
+md5deinit (void *ctx)
+{
+  gnutls_free (ctx);
+}
+
 struct hmacctx
 {
   char *data;
@@ -36,7 +78,7 @@ struct hmacctx
 };
 
 static int
-hmacmd5init (gnutls_digest_algorithm_t ign, void **ctx)
+hmacmd5init (gnutls_mac_algorithm_t mac, void **ctx)
 {
   struct hmacctx *p;
 
@@ -96,7 +138,7 @@ hmacmd5copy (void **dst_ctx, void *src_ctx)
   struct hmacctx *p = src_ctx;
   struct hmacctx *q;
 
-  q = gnutls_calloc (1, sizeof (struct hmacctx));
+  q = gnutls_malloc (sizeof (struct hmacctx));
   if (!q)
     return -1;
 
@@ -109,18 +151,15 @@ hmacmd5copy (void **dst_ctx, void *src_ctx)
   memcpy (q->data, p->data, p->datasize);
   q->datasize = p->datasize;
 
-  if (p->key) 
+  q->key = gnutls_malloc (p->keysize);
+  if (!q->key)
     {
-      q->key = gnutls_malloc (p->keysize);
-      if (!q->key)
-        {
-          gnutls_free (q);
-          gnutls_free (q->data);
-          return -1;
-        }
-      memcpy (q->key, p->key, p->keysize);
-      q->keysize = p->keysize;
+      gnutls_free (q);
+      gnutls_free (q->data);
+      return -1;
     }
+  memcpy (q->key, p->key, p->keysize);
+  q->keysize = p->keysize;
 
   *dst_ctx = q;
 
@@ -156,13 +195,21 @@ hmacmd5deinit (void *ctx)
   gnutls_free (p);
 }
 
-static gnutls_crypto_digest_st mac = {
-  hmacmd5init,
-  hmacmd5setkey,
-  hmacmd5hash,
-  hmacmd5copy,
-  hmacmd5output,
-  hmacmd5deinit
+static gnutls_crypto_digest_st dig = {
+  .init = md5init,
+  .hash = md5hash,
+  .copy = md5copy,
+  .output = md5output,
+  .deinit = md5deinit
+};
+
+static gnutls_crypto_mac_st mac = {
+  .init = hmacmd5init,
+  .setkey = hmacmd5setkey,
+  .hash = hmacmd5hash,
+  .copy = hmacmd5copy,
+  .output = hmacmd5output,
+  .deinit = hmacmd5deinit
 };
 
 /**
@@ -182,7 +229,11 @@ gnutls_register_md5_handler (void)
 {
   int ret;
 
-  ret = gnutls_crypto_single_digest_register (GNUTLS_DIG_MD5, INT_MAX, &mac);
+  ret = gnutls_crypto_single_digest_register (GNUTLS_DIG_MD5, INT_MAX, &dig);
+  if (ret)
+    return ret;
+
+  ret = gnutls_crypto_single_mac_register (GNUTLS_MAC_MD5, INT_MAX, &mac);
   if (ret)
     return ret;
 
diff --git a/libextra/gnutls_openssl.c b/libextra/gnutls_openssl.c
index edec495..fee62f6 100644
--- a/libextra/gnutls_openssl.c
+++ b/libextra/gnutls_openssl.c
@@ -1009,10 +1009,10 @@ RAND_egd_bytes (const char *path, int bytes)
 void
 MD5_Init (MD5_CTX * ctx)
 {
-  ctx->handle = gnutls_malloc (sizeof (hash_hd_st));
+  ctx->handle = gnutls_malloc (sizeof (digest_hd_st));
   if (!ctx->handle)
     abort ();
-  _gnutls_hash_init (ctx->handle, GNUTLS_DIG_MD5, NULL, 0);
+  _gnutls_hash_init (ctx->handle, GNUTLS_DIG_MD5);
 }
 
 void
@@ -1034,7 +1034,7 @@ MD5 (const unsigned char *buf, unsigned long len, 
unsigned char *md)
   if (!md)
     return NULL;
 
-  _gnutls_hash_fast (GNUTLS_DIG_MD5, NULL, 0, buf, len, md);
+  _gnutls_hash_fast (GNUTLS_DIG_MD5, buf, len, md);
 
   return md;
 }
@@ -1042,10 +1042,10 @@ MD5 (const unsigned char *buf, unsigned long len, 
unsigned char *md)
 void
 RIPEMD160_Init (RIPEMD160_CTX * ctx)
 {
-  ctx->handle = gnutls_malloc (sizeof (hash_hd_st));
+  ctx->handle = gnutls_malloc (sizeof (digest_hd_st));
   if (!ctx->handle)
     abort ();
-  _gnutls_hash_init (ctx->handle, GNUTLS_DIG_RMD160, NULL, 0);
+  _gnutls_hash_init (ctx->handle, GNUTLS_DIG_RMD160);
 }
 
 void
@@ -1067,7 +1067,7 @@ RIPEMD160 (const unsigned char *buf, unsigned long len, 
unsigned char *md)
   if (!md)
     return NULL;
 
-  _gnutls_hash_fast (GNUTLS_DIG_RMD160, NULL, 0, buf, len, md);
+  _gnutls_hash_fast (GNUTLS_DIG_RMD160, buf, len, md);
 
   return md;
 }
diff --git a/src/benchmark.c b/src/benchmark.c
index 1ec5eab..7f5f51a 100644
--- a/src/benchmark.c
+++ b/src/benchmark.c
@@ -28,7 +28,9 @@
 
 static unsigned char data[64*1024];
 
-void cipher_bench(int algo, int size)
+#define TOTAL_ITER 8*1024
+
+static void cipher_bench(int algo, int size)
 {
 int ret, i;
 gnutls_cipher_hd_t ctx;
@@ -69,7 +71,7 @@ int keysize = gnutls_cipher_get_key_size(algo);
     goto leave;
   }
   
-  for (i=0;i<7*1024;i++) {
+  for (i=0;i<TOTAL_ITER;i++) {
     gnutls_cipher_encrypt(ctx, data, size*1024);
     data_size+= size*1024;
   }
@@ -81,7 +83,7 @@ int keysize = gnutls_cipher_get_key_size(algo);
   secs = 
(stop.tv_sec*1000+stop.tv_nsec/(1000*1000)-(start.tv_sec*1000+start.tv_nsec/(1000*1000)));
   secs /= 1000;
   dd = (((double)data_size/(double)secs))/1000;
-  printf("Transferred %ld kb in %.2f secs: ", data_size/1000, secs);
+  printf("Encrypted %ld kb in %.2f secs: ", data_size/1000, secs);
   printf("%.2f kbyte/sec\n", dd);
   
 leave:
@@ -90,9 +92,55 @@ leave:
 
 }
 
+static void mac_bench(int algo, int size)
+{
+int i;
+void* _key;
+struct timespec start, stop;
+double secs;
+long data_size = 0;
+double dd;
+int blocksize = gnutls_hmac_get_len(algo);
+
+  _key = malloc(blocksize);
+  if (_key == NULL)
+    return;
+  memset(_key, 0xf0, blocksize);
+
+  gnutls_global_init();
+  
+  printf("Checking %s (%dkb payload)... ", gnutls_mac_get_name(algo), size);
+  fflush(stdout);
+  clock_gettime(CLOCK_MONOTONIC, &start);
+
+  for (i=0;i<TOTAL_ITER;i++) {
+    gnutls_hmac_fast(algo, _key, blocksize, data, size*1024, _key);
+    data_size+= size*1024;
+  }
+  
+  clock_gettime(CLOCK_MONOTONIC, &stop);
+
+  secs = 
(stop.tv_sec*1000+stop.tv_nsec/(1000*1000)-(start.tv_sec*1000+start.tv_nsec/(1000*1000)));
+  secs /= 1000;
+  dd = (((double)data_size/(double)secs))/1000;
+  printf("Hashed %ld kb in %.2f secs: ", data_size/1000, secs);
+  printf("%.2f kbyte/sec\n", dd);
+  
+  free(_key);
+
+}
+
 
-int main()
+int main(void)
 {
+  mac_bench(GNUTLS_MAC_SHA1, 4);
+  mac_bench(GNUTLS_MAC_SHA1, 8);
+  mac_bench(GNUTLS_MAC_SHA1, 16);
+
+  mac_bench(GNUTLS_MAC_SHA256, 4);
+  mac_bench(GNUTLS_MAC_SHA256, 8);
+  mac_bench(GNUTLS_MAC_SHA256, 16);
+
   cipher_bench(GNUTLS_CIPHER_3DES_CBC, 4);
   cipher_bench(GNUTLS_CIPHER_3DES_CBC, 8);
   cipher_bench(GNUTLS_CIPHER_3DES_CBC, 16);
@@ -104,6 +152,7 @@ int main()
   cipher_bench(GNUTLS_CIPHER_ARCFOUR, 4);
   cipher_bench(GNUTLS_CIPHER_ARCFOUR, 8);
   cipher_bench(GNUTLS_CIPHER_ARCFOUR, 16);
+
  
   return 0; 
 }
diff --git a/tests/gc.c b/tests/gc.c
index 9330ac2..86614ac 100644
--- a/tests/gc.c
+++ b/tests/gc.c
@@ -42,22 +42,6 @@ doit (void)
   gnutls_global_init ();
 
   err =
-    _gnutls_hash_fast (GNUTLS_MAC_MD5, NULL, 0, "testtest", 8, digest);
-  if (err < 0)
-    fail ("_gnutls_hash_fast(MD5) failed: %d\n", err);
-  else
-    {
-      if (memcmp (digest, 
"\x05\xa6\x71\xc6\x6a\xef\xea\x12\x4c\xc0\x8b\x76\xea\x6d\x30\xbb", 16) == 0)
-       success ("HASH: _gnutls_hash_fast(MD5) OK\n");
-      else
-       {
-         hexprint (digest, 16);
-         fail ("HASH: _gnutls_hash_fast(MD5) failure\n");
-       }
-    }
-
-
-  err =
     _gnutls_hash_fast (GNUTLS_MAC_MD5, "keykeykey", 9, "abcdefgh", 8, digest);
   if (err < 0)
     fail ("_gnutls_hash_fast(MD5) failed: %d\n", err);


hooks/post-receive
-- 
GNU gnutls




reply via email to

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