From: Simon Josefsson Date: Mon, 16 Aug 2004 20:18:43 +0000 (+0000) Subject: Move hashing to generic crypto API. X-Git-Tag: gnutls_1_0_20~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8c54a466949d353539eb367243dc37a84f3ff4e6;p=thirdparty%2Fgnutls.git Move hashing to generic crypto API. Implement hashing for nettle/libgcrypt in generic crypto API. --- diff --git a/crypto/gc-libgcrypt.c b/crypto/gc-libgcrypt.c index 84c4ee7f5f..b90ea79fa8 100644 --- a/crypto/gc-libgcrypt.c +++ b/crypto/gc-libgcrypt.c @@ -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); +} diff --git a/crypto/gc-nettle.c b/crypto/gc-nettle.c index 68d05775fa..dc38c5f7ac 100644 --- a/crypto/gc-nettle.c +++ b/crypto/gc-nettle.c @@ -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); +} diff --git a/crypto/gc.h b/crypto/gc.h index ae3469c8f8..d79d3bea46 100644 --- a/crypto/gc.h +++ b/crypto/gc.h @@ -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 */ diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c index 81872edb2a..1b60da427c 100644 --- a/lib/gnutls_hash_int.c +++ b/lib/gnutls_hash_int.c @@ -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 @@ -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); } diff --git a/lib/gnutls_hash_int.h b/lib/gnutls_hash_int.h index caa989bf21..299b6bb798 100644 --- a/lib/gnutls_hash_int.h +++ b/lib/gnutls_hash_int.h @@ -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;