X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgc-gnulib.c;h=a91a7c39a4aedcd89a4a2671d13e9cd57292757f;hb=3054e0c0b6c3f998ea52d8d25fc2bf1700a093ca;hp=6eff3e3fee4363f488d28b43f34d0e314a3227ba;hpb=6a58cb3f05f9a3d05ce2b0e0845b7514540d81b5;p=gnulib.git diff --git a/lib/gc-gnulib.c b/lib/gc-gnulib.c index 6eff3e3fe..a91a7c39a 100644 --- a/lib/gc-gnulib.c +++ b/lib/gc-gnulib.c @@ -1,5 +1,5 @@ -/* gc-gl-common.c --- Common gnulib internal crypto interface functions - * Copyright (C) 2002, 2003, 2004, 2005 Simon Josefsson +/* gc-gnulib.c --- Common gnulib internal crypto interface functions + * Copyright (C) 2002, 2003, 2004, 2005, 2006 Simon Josefsson * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -25,19 +25,24 @@ #endif /* Get prototype. */ -#include +#include "gc.h" #include #include /* For randomize. */ -#include -#include -#include -#include -#include +#ifdef GC_USE_RANDOM +# include +# include +# include +# include +# include +#endif /* Hashes. */ +#ifdef GC_USE_MD2 +# include "md2.h" +#endif #ifdef GC_USE_MD4 # include "md4.h" #endif @@ -77,6 +82,8 @@ gc_done (void) return; } +#ifdef GC_USE_RANDOM + /* Randomness. */ static Gc_rc @@ -102,6 +109,9 @@ randomize (int level, char *data, size_t datalen) break; } + if (strcmp (device, "no") == 0) + return GC_RANDOM_ERROR; + fd = open (device, O_RDONLY); if (fd < 0) return GC_RANDOM_ERROR; @@ -149,6 +159,8 @@ gc_random (char *data, size_t datalen) return randomize (2, data, datalen); } +#endif + /* Memory allocation. */ void @@ -166,6 +178,7 @@ typedef struct _gc_cipher_ctx { Gc_cipher_mode mode; #ifdef GC_USE_ARCTWO arctwo_context arctwoContext; + char arctwoIV[ARCTWO_BLOCK_SIZE]; #endif #ifdef GC_USE_ARCFOUR arcfour_context arcfourContext; @@ -188,6 +201,8 @@ gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode, Gc_rc rc = GC_OK; ctx = calloc (sizeof (*ctx), 1); + if (!ctx) + return GC_MALLOC_ERROR; ctx->alg = alg; ctx->mode = mode; @@ -199,6 +214,7 @@ gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode, switch (mode) { case GC_ECB: + case GC_CBC: break; default: @@ -333,6 +349,14 @@ gc_cipher_setiv (gc_cipher_handle handle, size_t ivlen, const char *iv) switch (ctx->alg) { +#ifdef GC_USE_ARCTWO + case GC_ARCTWO40: + if (ivlen != ARCTWO_BLOCK_SIZE) + return GC_INVALID_CIPHER; + memcpy (ctx->arctwoIV, iv, ivlen); + break; +#endif + #ifdef GC_USE_RIJNDAEL case GC_AES128: case GC_AES192: @@ -381,7 +405,28 @@ gc_cipher_encrypt_inline (gc_cipher_handle handle, size_t len, char *data) { #ifdef GC_USE_ARCTWO case GC_ARCTWO40: - arctwo_encrypt (&ctx->arctwoContext, data, data, len); + switch (ctx->mode) + { + case GC_ECB: + arctwo_encrypt (&ctx->arctwoContext, data, data, len); + break; + + case GC_CBC: + for (; len >= ARCTWO_BLOCK_SIZE; len -= ARCTWO_BLOCK_SIZE, + data += ARCTWO_BLOCK_SIZE) + { + size_t i; + for (i = 0; i < ARCTWO_BLOCK_SIZE; i++) + data[i] ^= ctx->arctwoIV[i]; + arctwo_encrypt (&ctx->arctwoContext, data, data, + ARCTWO_BLOCK_SIZE); + memcpy (ctx->arctwoIV, data, ARCTWO_BLOCK_SIZE); + } + break; + + default: + return GC_INVALID_CIPHER; + } break; #endif @@ -430,7 +475,30 @@ gc_cipher_decrypt_inline (gc_cipher_handle handle, size_t len, char *data) { #ifdef GC_USE_ARCTWO case GC_ARCTWO40: - arctwo_decrypt (&ctx->arctwoContext, data, data, len); + switch (ctx->mode) + { + case GC_ECB: + arctwo_decrypt (&ctx->arctwoContext, data, data, len); + break; + + case GC_CBC: + for (; len >= ARCTWO_BLOCK_SIZE; len -= ARCTWO_BLOCK_SIZE, + data += ARCTWO_BLOCK_SIZE) + { + char tmpIV[ARCTWO_BLOCK_SIZE]; + size_t i; + memcpy (tmpIV, data, ARCTWO_BLOCK_SIZE); + arctwo_decrypt (&ctx->arctwoContext, data, data, + ARCTWO_BLOCK_SIZE); + for (i = 0; i < ARCTWO_BLOCK_SIZE; i++) + data[i] ^= ctx->arctwoIV[i]; + memcpy (ctx->arctwoIV, tmpIV, ARCTWO_BLOCK_SIZE); + } + break; + + default: + return GC_INVALID_CIPHER; + } break; #endif @@ -483,11 +551,233 @@ gc_cipher_close (gc_cipher_handle handle) /* Hashes. */ +#define MAX_DIGEST_SIZE 20 + +typedef struct _gc_hash_ctx { + Gc_hash alg; + Gc_hash_mode mode; + char hash[MAX_DIGEST_SIZE]; +#ifdef GC_USE_MD2 + struct md2_ctx md2Context; +#endif +#ifdef GC_USE_MD4 + struct md4_ctx md4Context; +#endif +#ifdef GC_USE_MD5 + struct md5_ctx md5Context; +#endif +#ifdef GC_USE_SHA1 + struct sha1_ctx sha1Context; +#endif +} _gc_hash_ctx; + +Gc_rc +gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle) +{ + _gc_hash_ctx *ctx; + Gc_rc rc = GC_OK; + + ctx = calloc (sizeof (*ctx), 1); + + ctx->alg = hash; + ctx->mode = mode; + + switch (hash) + { +#ifdef GC_USE_MD2 + case GC_MD2: + md2_init_ctx (&ctx->md2Context); + break; +#endif + +#ifdef GC_USE_MD4 + case GC_MD4: + md4_init_ctx (&ctx->md4Context); + break; +#endif + +#ifdef GC_USE_MD5 + case GC_MD5: + md5_init_ctx (&ctx->md5Context); + break; +#endif + +#ifdef GC_USE_SHA1 + case GC_SHA1: + sha1_init_ctx (&ctx->sha1Context); + break; +#endif + + default: + rc = GC_INVALID_HASH; + break; + } + + switch (mode) + { + case 0: + break; + + default: + rc = GC_INVALID_HASH; + break; + } + + 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; + + *outhandle = out = calloc (sizeof (*out), 1); + if (!out) + return GC_MALLOC_ERROR; + + memcpy (out, in, sizeof (*out)); + + 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; + + default: + return 0; + } + + return len; +} + +void +gc_hash_write (gc_hash_handle handle, size_t len, const char *data) +{ + _gc_hash_ctx *ctx = handle; + + switch (ctx->alg) + { +#ifdef GC_USE_MD2 + case GC_MD2: + md2_process_bytes (data, len, &ctx->md2Context); + break; +#endif + +#ifdef GC_USE_MD4 + case GC_MD4: + md4_process_bytes (data, len, &ctx->md4Context); + break; +#endif + +#ifdef GC_USE_MD5 + case GC_MD5: + md5_process_bytes (data, len, &ctx->md5Context); + break; +#endif + +#ifdef GC_USE_SHA1 + case GC_SHA1: + sha1_process_bytes (data, len, &ctx->sha1Context); + break; +#endif + + default: + break; + } +} + +const char * +gc_hash_read (gc_hash_handle handle) +{ + _gc_hash_ctx *ctx = handle; + const char *ret = NULL; + + switch (ctx->alg) + { +#ifdef GC_USE_MD2 + case GC_MD2: + md2_finish_ctx (&ctx->md2Context, ctx->hash); + ret = ctx->hash; + break; +#endif + +#ifdef GC_USE_MD4 + case GC_MD4: + md4_finish_ctx (&ctx->md4Context, ctx->hash); + ret = ctx->hash; + break; +#endif + +#ifdef GC_USE_MD5 + case GC_MD5: + md5_finish_ctx (&ctx->md5Context, ctx->hash); + ret = ctx->hash; + break; +#endif + +#ifdef GC_USE_SHA1 + case GC_SHA1: + sha1_finish_ctx (&ctx->sha1Context, ctx->hash); + ret = ctx->hash; + break; +#endif + + default: + return NULL; + } + + return ret; +} + +void +gc_hash_close (gc_hash_handle handle) +{ + _gc_hash_ctx *ctx = handle; + + free (ctx); +} + Gc_rc gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) { switch (hash) { +#ifdef GC_USE_MD2 + case GC_MD2: + md2_buffer (in, inlen, resbuf); + break; +#endif + #ifdef GC_USE_MD4 case GC_MD4: md4_buffer (in, inlen, resbuf); @@ -513,6 +803,15 @@ gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf) return GC_OK; } +#ifdef GC_USE_MD2 +Gc_rc +gc_md2 (const void *in, size_t inlen, void *resbuf) +{ + md2_buffer (in, inlen, resbuf); + return GC_OK; +} +#endif + #ifdef GC_USE_MD4 Gc_rc gc_md4 (const void *in, size_t inlen, void *resbuf)