]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Move hashing to generic crypto API.
authorSimon Josefsson <simon@josefsson.org>
Mon, 16 Aug 2004 20:18:43 +0000 (20:18 +0000)
committerSimon Josefsson <simon@josefsson.org>
Mon, 16 Aug 2004 20:18:43 +0000 (20:18 +0000)
Implement hashing for nettle/libgcrypt in generic crypto API.

crypto/gc-libgcrypt.c
crypto/gc-nettle.c
crypto/gc.h
lib/gnutls_hash_int.c
lib/gnutls_hash_int.h

index 84c4ee7f5f72ce49e65f87d19cc8a4530647f68d..b90ea79fa89195e8e2f99a9af9b6cf040f8e9a50 100644 (file)
@@ -155,7 +155,7 @@ gc_cipher_open (int alg, int mode, gc_cipher * outhandle)
 }
 
 int
-gc_cipher_setkey (gc_cipher handle, size_t keylen, char *key)
+gc_cipher_setkey (gc_cipher handle, size_t keylen, const char *key)
 {
   gcry_error_t err;
 
@@ -167,7 +167,7 @@ gc_cipher_setkey (gc_cipher handle, size_t keylen, char *key)
 }
 
 int
-gc_cipher_setiv (gc_cipher handle, size_t ivlen, char *iv)
+gc_cipher_setiv (gc_cipher handle, size_t ivlen, const char *iv)
 {
   gcry_error_t err;
 
@@ -203,3 +203,116 @@ gc_cipher_close (gc_cipher handle)
 
   return GC_OK;
 }
+
+/* Hashes. */
+
+int
+gc_hash_open (int hash, int mode, gc_hash * outhandle)
+{
+  int gcryalg, gcrymode;
+  gcry_error_t err;
+
+  switch (hash)
+    {
+    case GC_MD5:
+      gcryalg = GCRY_MD_MD5;
+      break;
+
+    case GC_SHA1:
+      gcryalg = GCRY_MD_SHA1;
+      break;
+
+    case GC_RMD160:
+      gcryalg = GCRY_MD_RMD160;
+      break;
+
+    default:
+      return GC_INVALID_HASH;
+    }
+
+  switch (mode)
+    {
+    case 0:
+      gcrymode = 0;
+      break;
+
+    case GC_HMAC:
+      gcrymode = GCRY_MD_FLAG_HMAC;
+      break;
+
+    default:
+      return GC_INVALID_HASH;
+    }
+
+  err = gcry_md_open ((gcry_md_hd_t*) outhandle, gcryalg, gcrymode);
+  if (gcry_err_code (err))
+    return GC_INVALID_HASH;
+
+  return GC_OK;
+}
+
+int
+gc_hash_clone (gc_hash handle, gc_hash * outhandle)
+{
+  int err;
+
+  err = gcry_md_copy((gcry_md_hd_t*)outhandle, (gcry_md_hd_t)handle);
+  if (err)
+    return GC_INVALID_HASH;
+
+  return GC_OK;
+}
+
+size_t
+gc_hash_digest_length (int hash)
+{
+  int gcryalg;
+
+  switch (hash)
+    {
+    case GC_MD5:
+      gcryalg = GCRY_MD_MD5;
+      break;
+
+    case GC_SHA1:
+      gcryalg = GCRY_MD_SHA1;
+      break;
+
+    case GC_RMD160:
+      gcryalg = GCRY_MD_RMD160;
+      break;
+
+    default:
+      return 0;
+    }
+
+  return gcry_md_get_algo_dlen (gcryalg);
+}
+void
+gc_hash_hmac_setkey (gc_hash handle, size_t len, const char *key)
+{
+  gcry_md_setkey((gcry_md_hd_t)handle, key, len);
+}
+
+void
+gc_hash_write (gc_hash handle, size_t len, const char *data)
+{
+  gcry_md_write ((gcry_md_hd_t)handle, data, len);
+}
+
+const char *
+gc_hash_read (gc_hash handle)
+{
+  const char *digest;
+
+  gcry_md_final ((gcry_md_hd_t)handle);
+  digest = gcry_md_read ((gcry_md_hd_t)handle, 0);
+
+  return digest;
+}
+
+void
+gc_hash_close (gc_hash handle)
+{
+  gcry_md_close ((gcry_md_hd_t)handle);
+}
index 68d05775fae5c689e5114ccf98c17d2bb59aa842..dc38c5f7acabcbfdeb3718c47d70bc992564abcc 100644 (file)
@@ -230,7 +230,7 @@ gc_cipher_open (int alg, int mode, gc_cipher * outhandle)
 }
 
 int
-gc_cipher_setkey (gc_cipher handle, size_t keylen, char *key)
+gc_cipher_setkey (gc_cipher handle, size_t keylen, const char *key)
 {
   cinfo *cinf = (cinfo*) handle;
 
@@ -241,7 +241,7 @@ gc_cipher_setkey (gc_cipher handle, size_t keylen, char *key)
 }
 
 int
-gc_cipher_setiv (gc_cipher handle, size_t ivlen, char *iv)
+gc_cipher_setiv (gc_cipher handle, size_t ivlen, const char *iv)
 {
   cinfo *cinf = (cinfo*) handle;
 
@@ -295,3 +295,204 @@ gc_cipher_close (gc_cipher handle)
 
   return GC_OK;
 }
+
+/* Hashes. */
+
+#include "nettle-meta.h"
+#include "hmac.h"
+#include "md5.h"
+#include "sha.h"
+
+#define MAX_DIGEST_SIZE 20
+
+typedef struct hash_info {
+  int alg;
+  int mode;
+  const struct nettle_hash *info;
+  void *context;
+  void *outer;
+  void *inner;
+  char digest[MAX_DIGEST_SIZE];
+} hinfo;
+
+int
+gc_hash_open (int hash, int mode, gc_hash * outhandle)
+{
+  hinfo *hinf;
+
+  hinf = malloc (sizeof (*hinf));
+  if (!hinf)
+    return GC_MALLOC_ERROR;
+
+  hinf->alg = hash;
+  hinf->mode = mode;
+
+  switch (hash)
+    {
+    case GC_MD5:
+      hinf->info = &nettle_md5;
+      break;
+
+    case GC_SHA1:
+      hinf->info = &nettle_sha1;
+      break;
+
+      /* FIXME: RMD160. */
+
+    default:
+      free (hinf);
+      return GC_INVALID_HASH;
+    }
+
+  hinf->context = malloc (hinf->info->context_size);
+  if (!hinf->context)
+    {
+      free (hinf);
+      return GC_MALLOC_ERROR;
+    }
+
+  if (mode == GC_HMAC)
+    {
+      hinf->outer = malloc (hinf->info->context_size);
+      if (!hinf->outer)
+       {
+         free (hinf->context);
+         free (hinf);
+         return GC_MALLOC_ERROR;
+       }
+
+      hinf->inner = malloc (hinf->info->context_size);
+      if (!hinf->inner)
+       {
+         free (hinf->outer);
+         free (hinf->context);
+         free (hinf);
+         return GC_MALLOC_ERROR;
+       }
+    }
+  else
+    hinf->inner = hinf->outer = NULL;
+
+  hinf->info->init (hinf->context);
+
+  *outhandle = hinf;
+
+  return GC_OK;
+}
+
+int
+gc_hash_clone (gc_hash handle, gc_hash * outhandle)
+{
+  hinfo *oldhinf = (hinfo*) handle;
+  hinfo *newhinf;
+
+  newhinf = malloc (sizeof (*newhinf));
+  if (!newhinf)
+    return GC_MALLOC_ERROR;
+
+  newhinf->alg = oldhinf->alg;
+  newhinf->mode = oldhinf->mode;
+  newhinf->info = oldhinf->info;
+
+  newhinf->context = malloc (newhinf->info->context_size);
+  if (!newhinf->context)
+    {
+      free (newhinf);
+      return GC_MALLOC_ERROR;
+    }
+
+  if (oldhinf->mode == GC_HMAC)
+    {
+      newhinf->inner = malloc (newhinf->info->context_size);
+      if (!newhinf->inner)
+       {
+         free (newhinf->context);
+         free (newhinf);
+         return GC_MALLOC_ERROR;
+       }
+
+      newhinf->outer = malloc (newhinf->info->context_size);
+      if (!newhinf->outer)
+       {
+         free (newhinf->inner);
+         free (newhinf->context);
+         free (newhinf);
+         return GC_MALLOC_ERROR;
+       }
+
+      memcpy (newhinf->inner, oldhinf->inner, newhinf->info->context_size);
+      memcpy (newhinf->outer, oldhinf->outer, newhinf->info->context_size);
+    }
+
+  memcpy (newhinf->context, oldhinf->context, newhinf->info->context_size);
+
+  *outhandle = newhinf;
+
+  return GC_OK;
+}
+
+size_t
+gc_hash_digest_length (int hash)
+{
+  switch (hash)
+    {
+    case GC_MD5:
+      return MD5_DIGEST_SIZE;
+      break;
+
+    case GC_SHA1:
+      return SHA1_DIGEST_SIZE;
+      break;
+
+    case GC_RMD160:
+      return /* FIXME */20;
+      break;
+
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+void
+gc_hash_hmac_setkey (gc_hash handle, size_t len, const char *key)
+{
+  hinfo *hinf = (hinfo*) handle;
+
+  hmac_set_key(hinf->outer, hinf->inner, hinf->context,
+              hinf->info, (unsigned) len, key);
+}
+
+void
+gc_hash_write (gc_hash handle, size_t len, const char *data)
+{
+  hinfo *hinf = (hinfo*) handle;
+
+  hinf->info->update (hinf->context, (size_t) len, data);
+}
+
+const char *
+gc_hash_read (gc_hash handle)
+{
+  hinfo *hinf = (hinfo*) handle;
+
+  if (hinf->mode == GC_HMAC)
+    hmac_digest(hinf->outer, hinf->inner, hinf->context,
+               hinf->info, (unsigned) hinf->info->digest_size,
+               hinf->digest);
+  else
+    hinf->info->digest (hinf->context, (unsigned) hinf->info->digest_size,
+                       hinf->digest);
+
+  return hinf->digest;
+}
+
+void
+gc_hash_close (gc_hash handle)
+{
+  hinfo *hinf = (hinfo*) handle;
+
+  free (hinf->context);
+  free (hinf);
+}
index ae3469c8f8c4dfb42735d07a7fae66fa9fb3408b..d79d3bea46dd7836a208895828c188d26dfc6467 100644 (file)
@@ -32,10 +32,19 @@ enum Gc_rc
   GC_MALLOC_ERROR,
   GC_INIT_ERROR,
   GC_RANDOM_ERROR,
-  GC_INVALID_CIPHER
+  GC_INVALID_CIPHER,
+  GC_INVALID_HASH
 };
 typedef enum Gc_rc Gc_rc;
 
+enum Gc_hash
+  {
+    GC_MD5,
+    GC_SHA1,
+    GC_RMD160
+  };
+typedef enum Gc_hash Gc_hash;
+
 enum Gc_cipher
 {
   GC_AES128,
@@ -48,12 +57,18 @@ enum Gc_cipher
 };
 typedef enum Gc_cipher Gc_cipher;
 
-enum Gc_mode
+enum Gc_cipher_mode
 {
   GC_CBC,
   GC_STREAM
 };
-typedef enum Gc_mode Gc_mode;
+typedef enum Gc_cipher_mode Gc_cipher_mode;
+
+enum Gc_hash_mode
+  {
+    GC_HMAC = 1
+  };
+typedef enum Gc_hash_mode Gc_hash_mode;
 
 typedef void *gc_hash;
 typedef void *gc_cipher;
@@ -78,12 +93,19 @@ extern void gc_set_allocators (gc_malloc_t func_malloc,
 
 /* Ciphers. */
 extern int gc_cipher_open (int cipher, int mode, gc_cipher * outhandle);
-extern int gc_cipher_setkey (gc_cipher handle, size_t keylen, char *key);
-extern int gc_cipher_setiv (gc_cipher handle, size_t ivlen, char *iv);
-extern int gc_cipher_encrypt_inline (gc_cipher handle, size_t len,
-                                    char *data);
-extern int gc_cipher_decrypt_inline (gc_cipher handle, size_t len,
-                                    char *data);
+extern int gc_cipher_setkey (gc_cipher handle, size_t keylen, const char *key);
+extern int gc_cipher_setiv (gc_cipher handle, size_t ivlen, const char *iv);
+extern int gc_cipher_encrypt_inline (gc_cipher handle, size_t len, char *data);
+extern int gc_cipher_decrypt_inline (gc_cipher handle, size_t len, char *data);
 extern int gc_cipher_close (gc_cipher handle);
 
+/* Hashes. */
+extern int gc_hash_open (int hash, int mode, gc_hash * outhandle);
+extern int gc_hash_clone (gc_hash handle, gc_hash * outhandle);
+extern size_t gc_hash_digest_length (int hash);
+extern void gc_hash_hmac_setkey (gc_hash handle, size_t len, const char *key);
+extern void gc_hash_write (gc_hash handle, size_t len, const char *data);
+extern const char *gc_hash_read (gc_hash handle);
+extern void gc_hash_close (gc_hash handle);
+
 #endif /* GC_H */
index 81872edb2a48658ac8740a04f47fb4c4ac97ad31..1b60da427c655b4f2c7db527ebdf8a38f5db65dc 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2004 Simon Josefsson
  * Copyright (C) 2000,2001 Nikos Mavroyanopoulos
  * Copyright (C) 2004 Free Software Foundation
  *
@@ -21,8 +22,7 @@
  */
 
 /* This file handles all the internal functions that cope with hashes
- * and HMACs. Currently it uses the functions provided by
- * the gcrypt library that this can be easily changed.
+ * and HMACs.
  */
 
 #include <gnutls_int.h>
@@ -32,7 +32,7 @@
 GNUTLS_HASH_HANDLE _gnutls_hash_init(gnutls_mac_algorithm_t algorithm)
 {
     mac_hd_t ret;
-    gcry_error_t result;
+    int result;
 
     ret = gnutls_malloc(sizeof(mac_hd_st));
     if (ret == NULL) {
@@ -44,17 +44,17 @@ GNUTLS_HASH_HANDLE _gnutls_hash_init(gnutls_mac_algorithm_t algorithm)
 
     switch (algorithm) {
     case GNUTLS_MAC_SHA:
-       result = gcry_md_open(&ret->handle, GCRY_MD_SHA1, 0);
-       break;
+      result = gc_hash_open(GC_SHA1, 0, &ret->handle);
+      break;
     case GNUTLS_MAC_MD5:
-       result = gcry_md_open(&ret->handle, GCRY_MD_MD5, 0);
-       break;
+      result = gc_hash_open(GC_MD5, 0, &ret->handle);
+      break;
     case GNUTLS_MAC_RMD160:
-       result = gcry_md_open(&ret->handle, GCRY_MD_RMD160, 0);
-       break;
+      result = gc_hash_open(GC_RMD160, 0, &ret->handle);
+      break;
     default:
-       gnutls_assert();
-       result = -1;
+      gnutls_assert();
+      result = -1;
     }
 
     if (result) {
@@ -72,13 +72,13 @@ int _gnutls_hash_get_algo_len(gnutls_mac_algorithm_t algorithm)
 
     switch (algorithm) {
     case GNUTLS_MAC_SHA:
-       ret = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
+       ret = gc_hash_digest_length(GC_SHA1);
        break;
     case GNUTLS_MAC_MD5:
-       ret = gcry_md_get_algo_dlen(GCRY_MD_MD5);
+       ret = gc_hash_digest_length(GC_MD5);
        break;
     case GNUTLS_MAC_RMD160:
-       ret = gcry_md_get_algo_dlen(GCRY_MD_RMD160);
+       ret = gc_hash_digest_length(GC_RMD160);
        break;
     default:
        ret = 0;
@@ -92,15 +92,15 @@ int _gnutls_hash_get_algo_len(gnutls_mac_algorithm_t algorithm)
 int _gnutls_hash(GNUTLS_HASH_HANDLE handle, const void *text,
                 size_t textlen)
 {
-    if (textlen > 0)
-       gcry_md_write(handle->handle, text, textlen);
-    return 0;
+  if (textlen > 0)
+    gc_hash_write(handle->handle, textlen, text);
+  return 0;
 }
 
 GNUTLS_HASH_HANDLE _gnutls_hash_copy(GNUTLS_HASH_HANDLE handle)
 {
     GNUTLS_HASH_HANDLE ret;
-    gcry_error_t result;
+    int result;
 
     ret = gnutls_malloc(sizeof(mac_hd_st));
 
@@ -111,7 +111,7 @@ GNUTLS_HASH_HANDLE _gnutls_hash_copy(GNUTLS_HASH_HANDLE handle)
     ret->key = NULL;           /* it's a hash anyway */
     ret->keysize = 0;
 
-    result = gcry_md_copy(&ret->handle, handle->handle);
+    result = gc_hash_clone(handle->handle, &ret->handle);
 
     if (result) {
        gnutls_free(ret);
@@ -123,17 +123,16 @@ GNUTLS_HASH_HANDLE _gnutls_hash_copy(GNUTLS_HASH_HANDLE handle)
 
 void _gnutls_hash_deinit(GNUTLS_HASH_HANDLE handle, void *digest)
 {
-    opaque *mac;
+    const opaque *mac;
     int maclen;
 
     maclen = _gnutls_hash_get_algo_len(handle->algorithm);
 
-    gcry_md_final(handle->handle);
-    mac = gcry_md_read(handle->handle, 0);
+    mac = gc_hash_read(handle->handle);
     if (digest != NULL)
        memcpy(digest, mac, maclen);
 
-    gcry_md_close(handle->handle);
+    gc_hash_close(handle->handle);
 
     gnutls_free(handle);
 }
@@ -143,7 +142,7 @@ mac_hd_t _gnutls_hmac_init(gnutls_mac_algorithm_t algorithm,
                           const void *key, int keylen)
 {
     mac_hd_t ret;
-    gcry_error_t result;
+    int result;
 
     ret = gnutls_malloc(sizeof(mac_hd_st));
     if (ret == NULL)
@@ -152,15 +151,15 @@ mac_hd_t _gnutls_hmac_init(gnutls_mac_algorithm_t algorithm,
     switch (algorithm) {
     case GNUTLS_MAC_SHA:
        result =
-           gcry_md_open(&ret->handle, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+         gc_hash_open(GC_SHA1, GC_HMAC, &ret->handle);
        break;
     case GNUTLS_MAC_MD5:
        result =
-           gcry_md_open(&ret->handle, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
+         gc_hash_open(GC_MD5, GC_HMAC, &ret->handle);
        break;
     case GNUTLS_MAC_RMD160:
        result =
-           gcry_md_open(&ret->handle, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC);
+         gc_hash_open(GC_RMD160, GC_HMAC, &ret->handle);
        break;
     default:
        result = -1;
@@ -172,7 +171,7 @@ mac_hd_t _gnutls_hmac_init(gnutls_mac_algorithm_t algorithm,
     }
 
     if (ret != GNUTLS_MAC_FAILED) {
-       gcry_md_setkey(ret->handle, key, keylen);
+       gc_hash_hmac_setkey(ret->handle, keylen, key);
 
        ret->algorithm = algorithm;
        ret->key = key;
@@ -184,18 +183,17 @@ mac_hd_t _gnutls_hmac_init(gnutls_mac_algorithm_t algorithm,
 
 void _gnutls_hmac_deinit(mac_hd_t handle, void *digest)
 {
-    opaque *mac;
+    const opaque *mac;
     int maclen;
 
     maclen = _gnutls_hash_get_algo_len(handle->algorithm);
 
-    gcry_md_final(handle->handle);
-    mac = gcry_md_read(handle->handle, 0);
+    mac = gc_hash_read(handle->handle);
 
     if (digest != NULL)
        memcpy(digest, mac, maclen);
 
-    gcry_md_close(handle->handle);
+    gc_hash_close(handle->handle);
 
     gnutls_free(handle);
 }
index caa989bf21a388900df51bfae730f5d277e4e026..299b6bb798611bc31040430872cc9aa0009acff4 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ *      Copyright (C) 2004 Simon Josefsson
  *      Copyright (C) 2000 Nikos Mavroyanopoulos
  *
  * This file is part of GNUTLS.
@@ -26,7 +27,7 @@
 /* for message digests */
 
 typedef struct {
-    gcry_md_hd_t handle;
+    gc_hash handle;
     gnutls_mac_algorithm_t algorithm;
     const void *key;
     int keysize;