X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgc-libgcrypt.c;h=3be4272953b600c0f2dff86c1abd944ae3dcccd6;hb=5a448a463a290b59549f2ee1cf6c1b01a6043f45;hp=349d5619bb40e6e2e4cc22afb746851c7f951d75;hpb=ecbe47ca1c551b24c8a4d7309daba56006956849;p=gnulib.git diff --git a/lib/gc-libgcrypt.c b/lib/gc-libgcrypt.c index 349d5619b..3be427295 100644 --- a/lib/gc-libgcrypt.c +++ b/lib/gc-libgcrypt.c @@ -1,5 +1,5 @@ /* gc-libgcrypt.c --- Crypto wrappers around Libgcrypt for GC. - * Copyright (C) 2002, 2003, 2004, 2005 Simon Josefsson + * Copyright (C) 2002-2013 Free Software Foundation, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -12,26 +12,32 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. + * along with this file; if not, see . * */ /* Note: This file is only built if GC uses Libgcrypt. */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include /* Get prototype. */ #include "gc.h" +#include +#include + /* Get libgcrypt API. */ #include +#ifdef GNULIB_GC_MD2 +# include "md2.h" +#endif #include +#ifndef MIN_GCRYPT_VERSION +# define MIN_GCRYPT_VERSION "1.4.4" +#endif + /* Initialization. */ Gc_rc @@ -42,12 +48,15 @@ gc_init (void) err = gcry_control (GCRYCTL_ANY_INITIALIZATION_P); if (err == GPG_ERR_NO_ERROR) { - if (gcry_check_version (GCRYPT_VERSION) == NULL) - return GC_INIT_ERROR; + if (gcry_control (GCRYCTL_DISABLE_SECMEM, NULL, 0)) + return GC_INIT_ERROR; + + if (gcry_check_version (MIN_GCRYPT_VERSION) == NULL) + return GC_INIT_ERROR; err = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0); if (err != GPG_ERR_NO_ERROR) - return GC_INIT_ERROR; + return GC_INIT_ERROR; } return GC_OK; @@ -59,6 +68,8 @@ gc_done (void) return; } +#ifdef GNULIB_GC_RANDOM + /* Randomness. */ Gc_rc @@ -82,20 +93,381 @@ gc_random (char *data, size_t datalen) return GC_OK; } +#endif + /* Memory allocation. */ void gc_set_allocators (gc_malloc_t func_malloc, - gc_malloc_t secure_malloc, - gc_secure_check_t secure_check, - gc_realloc_t func_realloc, gc_free_t func_free) + gc_malloc_t secure_malloc, + gc_secure_check_t secure_check, + gc_realloc_t func_realloc, gc_free_t func_free) { gcry_set_allocation_handler (func_malloc, secure_malloc, secure_check, - func_realloc, func_free); + func_realloc, func_free); +} + +/* Ciphers. */ + +Gc_rc +gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode, + gc_cipher_handle * outhandle) +{ + int gcryalg, gcrymode; + gcry_error_t err; + + switch (alg) + { + case GC_AES128: + gcryalg = GCRY_CIPHER_RIJNDAEL; + break; + + case GC_AES192: + gcryalg = GCRY_CIPHER_RIJNDAEL; + break; + + case GC_AES256: + gcryalg = GCRY_CIPHER_RIJNDAEL256; + break; + + case GC_3DES: + gcryalg = GCRY_CIPHER_3DES; + break; + + case GC_DES: + gcryalg = GCRY_CIPHER_DES; + break; + + case GC_ARCFOUR128: + case GC_ARCFOUR40: + gcryalg = GCRY_CIPHER_ARCFOUR; + break; + + case GC_ARCTWO40: + gcryalg = GCRY_CIPHER_RFC2268_40; + break; + +#ifdef HAVE_CAMELLIA + case GC_CAMELLIA128: + gcryalg = GCRY_CIPHER_CAMELLIA128; + break; + + case GC_CAMELLIA256: + gcryalg = GCRY_CIPHER_CAMELLIA256; + break; +#endif + + default: + return GC_INVALID_CIPHER; + } + + switch (mode) + { + case GC_ECB: + gcrymode = GCRY_CIPHER_MODE_ECB; + break; + + case GC_CBC: + gcrymode = GCRY_CIPHER_MODE_CBC; + break; + + case GC_STREAM: + gcrymode = GCRY_CIPHER_MODE_STREAM; + break; + + default: + return GC_INVALID_CIPHER; + } + + err = gcry_cipher_open ((gcry_cipher_hd_t *) outhandle, + gcryalg, gcrymode, 0); + if (gcry_err_code (err)) + return GC_INVALID_CIPHER; + + return GC_OK; +} + +Gc_rc +gc_cipher_setkey (gc_cipher_handle handle, size_t keylen, const char *key) +{ + gcry_error_t err; + + err = gcry_cipher_setkey ((gcry_cipher_hd_t) handle, key, keylen); + if (gcry_err_code (err)) + return GC_INVALID_CIPHER; + + return GC_OK; +} + +Gc_rc +gc_cipher_setiv (gc_cipher_handle handle, size_t ivlen, const char *iv) +{ + gcry_error_t err; + + err = gcry_cipher_setiv ((gcry_cipher_hd_t) handle, iv, ivlen); + if (gcry_err_code (err)) + return GC_INVALID_CIPHER; + + return GC_OK; +} + +Gc_rc +gc_cipher_encrypt_inline (gc_cipher_handle handle, size_t len, char *data) +{ + if (gcry_cipher_encrypt ((gcry_cipher_hd_t) handle, + data, len, NULL, len) != 0) + return GC_INVALID_CIPHER; + + return GC_OK; +} + +Gc_rc +gc_cipher_decrypt_inline (gc_cipher_handle handle, size_t len, char *data) +{ + if (gcry_cipher_decrypt ((gcry_cipher_hd_t) handle, + data, len, NULL, len) != 0) + return GC_INVALID_CIPHER; + + return GC_OK; +} + +Gc_rc +gc_cipher_close (gc_cipher_handle handle) +{ + gcry_cipher_close (handle); + + return GC_OK; } /* Hashes. */ +typedef struct _gc_hash_ctx { + Gc_hash alg; + Gc_hash_mode mode; + gcry_md_hd_t gch; +#ifdef GNULIB_GC_MD2 + char hash[GC_MD2_DIGEST_SIZE]; + struct md2_ctx md2Context; +#endif +} _gc_hash_ctx; + +Gc_rc +gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle) +{ + _gc_hash_ctx *ctx; + int gcryalg = 0, gcrymode = 0; + gcry_error_t err; + Gc_rc rc = GC_OK; + + ctx = calloc (sizeof (*ctx), 1); + if (!ctx) + return GC_MALLOC_ERROR; + + ctx->alg = hash; + ctx->mode = mode; + + switch (hash) + { + case GC_MD2: + gcryalg = GCRY_MD_NONE; + break; + + case GC_MD4: + gcryalg = GCRY_MD_MD4; + break; + + case GC_MD5: + gcryalg = GCRY_MD_MD5; + break; + + case GC_SHA1: + gcryalg = GCRY_MD_SHA1; + break; + + case GC_SHA256: + gcryalg = GCRY_MD_SHA256; + break; + + case GC_SHA384: + gcryalg = GCRY_MD_SHA384; + break; + + case GC_SHA512: + gcryalg = GCRY_MD_SHA512; + break; + + case GC_SHA224: + gcryalg = GCRY_MD_SHA224; + break; + + case GC_RMD160: + gcryalg = GCRY_MD_RMD160; + break; + + default: + rc = GC_INVALID_HASH; + } + + switch (mode) + { + case 0: + gcrymode = 0; + break; + + case GC_HMAC: + gcrymode = GCRY_MD_FLAG_HMAC; + break; + + default: + rc = GC_INVALID_HASH; + } + + if (rc == GC_OK && gcryalg != GCRY_MD_NONE) + { + err = gcry_md_open (&ctx->gch, gcryalg, gcrymode); + if (gcry_err_code (err)) + rc = GC_INVALID_HASH; + } + + if (rc == GC_OK) + *outhandle = ctx; + else + free (ctx); + + return rc; +} + +Gc_rc +gc_hash_clone (gc_hash_handle handle, gc_hash_handle * outhandle) +{ + _gc_hash_ctx *in = handle; + _gc_hash_ctx *out; + int err; + + *outhandle = out = calloc (sizeof (*out), 1); + if (!out) + return GC_MALLOC_ERROR; + + memcpy (out, in, sizeof (*out)); + + err = gcry_md_copy (&out->gch, in->gch); + if (err) + { + free (out); + return GC_INVALID_HASH; + } + + return GC_OK; +} + +size_t +gc_hash_digest_length (Gc_hash hash) +{ + size_t len; + + switch (hash) + { + case GC_MD2: + len = GC_MD2_DIGEST_SIZE; + break; + + case GC_MD4: + len = GC_MD4_DIGEST_SIZE; + break; + + case GC_MD5: + len = GC_MD5_DIGEST_SIZE; + break; + + case GC_RMD160: + len = GC_RMD160_DIGEST_SIZE; + break; + + case GC_SHA1: + len = GC_SHA1_DIGEST_SIZE; + break; + + case GC_SHA256: + len = GC_SHA256_DIGEST_SIZE; + break; + + case GC_SHA384: + len = GC_SHA384_DIGEST_SIZE; + break; + + case GC_SHA512: + len = GC_SHA512_DIGEST_SIZE; + break; + + case GC_SHA224: + len = GC_SHA224_DIGEST_SIZE; + break; + + default: + return 0; + } + + return len; +} + +void +gc_hash_hmac_setkey (gc_hash_handle handle, size_t len, const char *key) +{ + _gc_hash_ctx *ctx = handle; +#ifdef GNULIB_GC_MD2 + if (ctx->alg != GC_MD2) +#endif + gcry_md_setkey (ctx->gch, key, len); +} + +void +gc_hash_write (gc_hash_handle handle, size_t len, const char *data) +{ + _gc_hash_ctx *ctx = handle; + +#ifdef GNULIB_GC_MD2 + if (ctx->alg == GC_MD2) + md2_process_bytes (data, len, &ctx->md2Context); + else +#endif + gcry_md_write (ctx->gch, data, len); +} + +const char * +gc_hash_read (gc_hash_handle handle) +{ + _gc_hash_ctx *ctx = handle; + const char *digest; + +#ifdef GNULIB_GC_MD2 + if (ctx->alg == GC_MD2) + { + md2_finish_ctx (&ctx->md2Context, ctx->hash); + digest = ctx->hash; + } + else +#endif + { + gcry_md_final (ctx->gch); + digest = gcry_md_read (ctx->gch, 0); + } + + return digest; +} + +void +gc_hash_close (gc_hash_handle handle) +{ + _gc_hash_ctx *ctx = handle; + +#ifdef GNULIB_GC_MD2 + if (ctx->alg != GC_MD2) +#endif + gcry_md_close (ctx->gch); + + free (ctx); +} + Gc_rc gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) { @@ -103,18 +475,61 @@ gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) switch (hash) { -#ifdef GC_USE_MD5 +#ifdef GNULIB_GC_MD2 + case GC_MD2: + md2_buffer (in, inlen, resbuf); + return GC_OK; + break; +#endif + +#ifdef GNULIB_GC_MD4 + case GC_MD4: + gcryalg = GCRY_MD_MD4; + break; +#endif + +#ifdef GNULIB_GC_MD5 case GC_MD5: gcryalg = GCRY_MD_MD5; break; #endif -#ifdef GC_USE_SHA1 +#ifdef GNULIB_GC_SHA1 case GC_SHA1: gcryalg = GCRY_MD_SHA1; break; #endif +#ifdef GNULIB_GC_SHA256 + case GC_SHA256: + gcryalg = GCRY_MD_SHA256; + break; +#endif + +#ifdef GNULIB_GC_SHA384 + case GC_SHA384: + gcryalg = GCRY_MD_SHA384; + break; +#endif + +#ifdef GNULIB_GC_SHA512 + case GC_SHA512: + gcryalg = GCRY_MD_SHA512; + break; +#endif + +#ifdef GNULIB_GC_SHA224 + case GC_SHA224: + gcryalg = GCRY_MD_SHA224; + break; +#endif + +#ifdef GNULIB_GC_RMD160 + case GC_RMD160: + gcryalg = GCRY_MD_RMD160; + break; +#endif + default: return GC_INVALID_HASH; } @@ -126,7 +541,48 @@ gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) /* One-call interface. */ -#ifdef GC_USE_MD5 +#ifdef GNULIB_GC_MD2 +Gc_rc +gc_md2 (const void *in, size_t inlen, void *resbuf) +{ + md2_buffer (in, inlen, resbuf); + return GC_OK; +} +#endif + +#ifdef GNULIB_GC_MD4 +Gc_rc +gc_md4 (const void *in, size_t inlen, void *resbuf) +{ + size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD4); + gcry_md_hd_t hd; + gpg_error_t err; + unsigned char *p; + + assert (outlen == GC_MD4_DIGEST_SIZE); + + err = gcry_md_open (&hd, GCRY_MD_MD4, 0); + if (err != GPG_ERR_NO_ERROR) + return GC_INVALID_HASH; + + gcry_md_write (hd, in, inlen); + + p = gcry_md_read (hd, GCRY_MD_MD4); + if (p == NULL) + { + gcry_md_close (hd); + return GC_INVALID_HASH; + } + + memcpy (resbuf, p, outlen); + + gcry_md_close (hd); + + return GC_OK; +} +#endif + +#ifdef GNULIB_GC_MD5 Gc_rc gc_md5 (const void *in, size_t inlen, void *resbuf) { @@ -158,7 +614,7 @@ gc_md5 (const void *in, size_t inlen, void *resbuf) } #endif -#ifdef GC_USE_SHA1 +#ifdef GNULIB_GC_SHA1 Gc_rc gc_sha1 (const void *in, size_t inlen, void *resbuf) { @@ -190,17 +646,17 @@ gc_sha1 (const void *in, size_t inlen, void *resbuf) } #endif -#ifdef GC_USE_HMAC_MD5 +#ifdef GNULIB_GC_HMAC_MD5 Gc_rc gc_hmac_md5 (const void *key, size_t keylen, - const void *in, size_t inlen, char *resbuf) + const void *in, size_t inlen, char *resbuf) { size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_MD5); gcry_md_hd_t mdh; unsigned char *hash; gpg_error_t err; - assert (hlen == 16); + assert (hlen == GC_MD5_DIGEST_SIZE); err = gcry_md_open (&mdh, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC); if (err != GPG_ERR_NO_ERROR) @@ -230,17 +686,17 @@ gc_hmac_md5 (const void *key, size_t keylen, } #endif -#ifdef GC_USE_HMAC_SHA1 +#ifdef GNULIB_GC_HMAC_SHA1 Gc_rc gc_hmac_sha1 (const void *key, size_t keylen, - const void *in, size_t inlen, char *resbuf) + const void *in, size_t inlen, char *resbuf) { size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); gcry_md_hd_t mdh; unsigned char *hash; gpg_error_t err; - assert (hlen == 16); + assert (hlen == GC_SHA1_DIGEST_SIZE); err = gcry_md_open (&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); if (err != GPG_ERR_NO_ERROR) @@ -269,3 +725,83 @@ gc_hmac_sha1 (const void *key, size_t keylen, return GC_OK; } #endif + +#ifdef GNULIB_GC_HMAC_SHA256 +Gc_rc +gc_hmac_sha256 (const void *key, size_t keylen, + const void *in, size_t inlen, char *resbuf) +{ + size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA256); + gcry_md_hd_t mdh; + unsigned char *hash; + gpg_error_t err; + + assert (hlen == GC_SHA256_DIGEST_SIZE); + + err = gcry_md_open (&mdh, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if (err != GPG_ERR_NO_ERROR) + return GC_INVALID_HASH; + + err = gcry_md_setkey (mdh, key, keylen); + if (err != GPG_ERR_NO_ERROR) + { + gcry_md_close (mdh); + return GC_INVALID_HASH; + } + + gcry_md_write (mdh, in, inlen); + + hash = gcry_md_read (mdh, GCRY_MD_SHA256); + if (hash == NULL) + { + gcry_md_close (mdh); + return GC_INVALID_HASH; + } + + memcpy (resbuf, hash, hlen); + + gcry_md_close (mdh); + + return GC_OK; +} +#endif + +#ifdef GNULIB_GC_HMAC_SHA512 +Gc_rc +gc_hmac_sha512 (const void *key, size_t keylen, + const void *in, size_t inlen, char *resbuf) +{ + size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA512); + gcry_md_hd_t mdh; + unsigned char *hash; + gpg_error_t err; + + assert (hlen == GC_SHA512_DIGEST_SIZE); + + err = gcry_md_open (&mdh, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC); + if (err != GPG_ERR_NO_ERROR) + return GC_INVALID_HASH; + + err = gcry_md_setkey (mdh, key, keylen); + if (err != GPG_ERR_NO_ERROR) + { + gcry_md_close (mdh); + return GC_INVALID_HASH; + } + + gcry_md_write (mdh, in, inlen); + + hash = gcry_md_read (mdh, GCRY_MD_SHA512); + if (hash == NULL) + { + gcry_md_close (mdh); + return GC_INVALID_HASH; + } + + memcpy (resbuf, hash, hlen); + + gcry_md_close (mdh); + + return GC_OK; +} +#endif