-/* 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
#endif
/* Get prototype. */
-#include <gc.h>
+#include "gc.h"
#include <stdlib.h>
#include <string.h>
/* For randomize. */
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
+#ifdef GC_USE_RANDOM
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <errno.h>
+#endif
/* Hashes. */
+#ifdef GC_USE_MD2
+# include "md2.h"
+#endif
#ifdef GC_USE_MD4
# include "md4.h"
#endif
return;
}
+#ifdef GC_USE_RANDOM
+
/* Randomness. */
static Gc_rc
break;
}
+ if (strcmp (device, "no") == 0)
+ return GC_RANDOM_ERROR;
+
fd = open (device, O_RDONLY);
if (fd < 0)
return GC_RANDOM_ERROR;
return randomize (2, data, datalen);
}
+#endif
+
/* Memory allocation. */
void
Gc_cipher_mode mode;
#ifdef GC_USE_ARCTWO
arctwo_context arctwoContext;
+ char arctwoIV[ARCTWO_BLOCK_SIZE];
#endif
#ifdef GC_USE_ARCFOUR
arcfour_context arcfourContext;
Gc_rc rc = GC_OK;
ctx = calloc (sizeof (*ctx), 1);
+ if (!ctx)
+ return GC_MALLOC_ERROR;
ctx->alg = alg;
ctx->mode = mode;
switch (mode)
{
case GC_ECB:
+ case GC_CBC:
break;
default:
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:
{
#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
{
#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
/* 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);
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)