Implement hashing for nettle/libgcrypt in generic crypto API.
}
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;
}
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;
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);
+}
}
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;
}
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;
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);
+}
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,
};
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;
/* 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 */
/*
+ * Copyright (C) 2004 Simon Josefsson
* Copyright (C) 2000,2001 Nikos Mavroyanopoulos
* Copyright (C) 2004 Free Software Foundation
*
*/
/* 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>
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) {
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) {
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;
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));
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);
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);
}
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)
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;
}
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;
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);
}
/*
+ * Copyright (C) 2004 Simon Josefsson
* Copyright (C) 2000 Nikos Mavroyanopoulos
*
* This file is part of GNUTLS.
/* for message digests */
typedef struct {
- gcry_md_hd_t handle;
+ gc_hash handle;
gnutls_mac_algorithm_t algorithm;
const void *key;
int keysize;