Add, forgotten in last commit.
[gnulib.git] / lib / gc-gnulib.c
index 00bab97..6eff3e3 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 
+/* Hashes. */
+#ifdef GC_USE_MD4
+# include "md4.h"
+#endif
 #ifdef GC_USE_MD5
 # include "md5.h"
 #endif
+#ifdef GC_USE_SHA1
+# include "sha1.h"
+#endif
 #ifdef GC_USE_HMAC_MD5
 # include "hmac.h"
 #endif
 
-int
+/* Ciphers. */
+#ifdef GC_USE_ARCFOUR
+# include "arcfour.h"
+#endif
+#ifdef GC_USE_ARCTWO
+# include "arctwo.h"
+#endif
+#ifdef GC_USE_DES
+# include "des.h"
+#endif
+#ifdef GC_USE_RIJNDAEL
+# include "rijndael-api-fst.h"
+#endif
+
+Gc_rc
 gc_init (void)
 {
-  return 0;
+  return GC_OK;
 }
 
 void
@@ -58,7 +79,7 @@ gc_done (void)
 
 /* Randomness. */
 
-static int
+static Gc_rc
 randomize (int level, char *data, size_t datalen)
 {
   int fd;
@@ -110,19 +131,19 @@ randomize (int level, char *data, size_t datalen)
   return GC_OK;
 }
 
-int
+Gc_rc
 gc_nonce (char *data, size_t datalen)
 {
   return randomize (0, data, datalen);
 }
 
-int
+Gc_rc
 gc_pseudo_random (char *data, size_t datalen)
 {
   return randomize (1, data, datalen);
 }
 
-int
+Gc_rc
 gc_random (char *data, size_t datalen)
 {
   return randomize (2, data, datalen);
@@ -138,20 +159,353 @@ gc_set_allocators (gc_malloc_t func_malloc,
 {
   return;
 }
+/* Ciphers. */
+
+typedef struct _gc_cipher_ctx {
+  Gc_cipher alg;
+  Gc_cipher_mode mode;
+#ifdef GC_USE_ARCTWO
+  arctwo_context arctwoContext;
+#endif
+#ifdef GC_USE_ARCFOUR
+  arcfour_context arcfourContext;
+#endif
+#ifdef GC_USE_DES
+  des_ctx desContext;
+#endif
+#ifdef GC_USE_RIJNDAEL
+  rijndaelKeyInstance aesEncKey;
+  rijndaelKeyInstance aesDecKey;
+  rijndaelCipherInstance aesContext;
+#endif
+} _gc_cipher_ctx;
+
+Gc_rc
+gc_cipher_open (Gc_cipher alg, Gc_cipher_mode mode,
+               gc_cipher_handle * outhandle)
+{
+  _gc_cipher_ctx *ctx;
+  Gc_rc rc = GC_OK;
+
+  ctx = calloc (sizeof (*ctx), 1);
+
+  ctx->alg = alg;
+  ctx->mode = mode;
+
+  switch (alg)
+    {
+#ifdef GC_USE_ARCTWO
+    case GC_ARCTWO40:
+      switch (mode)
+       {
+       case GC_ECB:
+         break;
+
+       default:
+         rc = GC_INVALID_CIPHER;
+       }
+      break;
+#endif
+
+#ifdef GC_USE_ARCFOUR
+    case GC_ARCFOUR128:
+    case GC_ARCFOUR40:
+      switch (mode)
+       {
+       case GC_STREAM:
+         break;
+
+       default:
+         rc = GC_INVALID_CIPHER;
+       }
+      break;
+#endif
+
+#ifdef GC_USE_DES
+    case GC_DES:
+      switch (mode)
+       {
+       case GC_ECB:
+         break;
+
+       default:
+         rc = GC_INVALID_CIPHER;
+       }
+      break;
+#endif
+
+#ifdef GC_USE_RIJNDAEL
+    case GC_AES128:
+    case GC_AES192:
+    case GC_AES256:
+      switch (mode)
+       {
+       case GC_ECB:
+       case GC_CBC:
+         break;
+
+       default:
+         rc = GC_INVALID_CIPHER;
+       }
+      break;
+#endif
+
+    default:
+      rc = GC_INVALID_CIPHER;
+    }
+
+  if (rc == GC_OK)
+    *outhandle = ctx;
+  else
+    free (ctx);
+
+  return rc;
+}
+
+Gc_rc
+gc_cipher_setkey (gc_cipher_handle handle, size_t keylen, const char *key)
+{
+  _gc_cipher_ctx *ctx = handle;
+
+  switch (ctx->alg)
+    {
+#ifdef GC_USE_ARCTWO
+    case GC_ARCTWO40:
+      arctwo_setkey (&ctx->arctwoContext, keylen, key);
+      break;
+#endif
+
+#ifdef GC_USE_ARCFOUR
+    case GC_ARCFOUR128:
+    case GC_ARCFOUR40:
+      arcfour_setkey (&ctx->arcfourContext, key, keylen);
+      break;
+#endif
+
+#ifdef GC_USE_DES
+    case GC_DES:
+      if (keylen != 8)
+       return GC_INVALID_CIPHER;
+      des_setkey (&ctx->desContext, key);
+      break;
+#endif
+
+#ifdef GC_USE_RIJNDAEL
+    case GC_AES128:
+    case GC_AES192:
+    case GC_AES256:
+      {
+       rijndael_rc rc;
+       size_t i;
+       char keyMaterial[RIJNDAEL_MAX_KEY_SIZE + 1];
+
+       for (i = 0; i < keylen; i++)
+         sprintf (&keyMaterial[2*i], "%02x", key[i] & 0xFF);
+
+       rc = rijndaelMakeKey (&ctx->aesEncKey, RIJNDAEL_DIR_ENCRYPT,
+                             keylen * 8, keyMaterial);
+       if (rc < 0)
+         return GC_INVALID_CIPHER;
+
+       rc = rijndaelMakeKey (&ctx->aesDecKey, RIJNDAEL_DIR_DECRYPT,
+                             keylen * 8, keyMaterial);
+       if (rc < 0)
+         return GC_INVALID_CIPHER;
+
+       rc = rijndaelCipherInit (&ctx->aesContext, RIJNDAEL_MODE_ECB, NULL);
+       if (rc < 0)
+         return GC_INVALID_CIPHER;
+      }
+      break;
+#endif
+
+    default:
+      return GC_INVALID_CIPHER;
+    }
+
+  return GC_OK;
+}
+
+Gc_rc
+gc_cipher_setiv (gc_cipher_handle handle, size_t ivlen, const char *iv)
+{
+  _gc_cipher_ctx *ctx = handle;
+
+  switch (ctx->alg)
+    {
+#ifdef GC_USE_RIJNDAEL
+    case GC_AES128:
+    case GC_AES192:
+    case GC_AES256:
+      switch (ctx->mode)
+       {
+       case GC_ECB:
+         /* Doesn't use IV. */
+         break;
+
+       case GC_CBC:
+         {
+           rijndael_rc rc;
+           size_t i;
+           char ivMaterial[2 * RIJNDAEL_MAX_IV_SIZE + 1];
+
+           for (i = 0; i < ivlen; i++)
+             sprintf (&ivMaterial[2*i], "%02x", iv[i] & 0xFF);
+
+           rc = rijndaelCipherInit (&ctx->aesContext, RIJNDAEL_MODE_CBC,
+                                    ivMaterial);
+           if (rc < 0)
+             return GC_INVALID_CIPHER;
+         }
+         break;
+
+       default:
+         return GC_INVALID_CIPHER;
+       }
+      break;
+#endif
+
+    default:
+      return GC_INVALID_CIPHER;
+    }
+
+  return GC_OK;
+}
+
+Gc_rc
+gc_cipher_encrypt_inline (gc_cipher_handle handle, size_t len, char *data)
+{
+  _gc_cipher_ctx *ctx = handle;
+
+  switch (ctx->alg)
+    {
+#ifdef GC_USE_ARCTWO
+    case GC_ARCTWO40:
+      arctwo_encrypt (&ctx->arctwoContext, data, data, len);
+      break;
+#endif
+
+#ifdef GC_USE_ARCFOUR
+    case GC_ARCFOUR128:
+    case GC_ARCFOUR40:
+      arcfour_stream (&ctx->arcfourContext, data, data, len);
+      break;
+#endif
+
+#ifdef GC_USE_DES
+    case GC_DES:
+      for (; len >= 8; len -= 8, data += 8)
+       des_ecb_encrypt (&ctx->desContext, data, data);
+      break;
+#endif
+
+#ifdef GC_USE_RIJNDAEL
+    case GC_AES128:
+    case GC_AES192:
+    case GC_AES256:
+      {
+       int nblocks;
+
+       nblocks = rijndaelBlockEncrypt (&ctx->aesContext, &ctx->aesEncKey,
+                                       data, 8 * len, data);
+       if (nblocks < 0)
+         return GC_INVALID_CIPHER;
+      }
+      break;
+#endif
+
+    default:
+      return GC_INVALID_CIPHER;
+    }
+
+  return GC_OK;
+}
+
+Gc_rc
+gc_cipher_decrypt_inline (gc_cipher_handle handle, size_t len, char *data)
+{
+  _gc_cipher_ctx *ctx = handle;
+
+  switch (ctx->alg)
+    {
+#ifdef GC_USE_ARCTWO
+    case GC_ARCTWO40:
+      arctwo_decrypt (&ctx->arctwoContext, data, data, len);
+      break;
+#endif
+
+#ifdef GC_USE_ARCFOUR
+    case GC_ARCFOUR128:
+    case GC_ARCFOUR40:
+      arcfour_stream (&ctx->arcfourContext, data, data, len);
+      break;
+#endif
+
+#ifdef GC_USE_DES
+    case GC_DES:
+      for (; len >= 8; len -= 8, data += 8)
+       des_ecb_decrypt (&ctx->desContext, data, data);
+      break;
+#endif
+
+#ifdef GC_USE_RIJNDAEL
+    case GC_AES128:
+    case GC_AES192:
+    case GC_AES256:
+      {
+       int nblocks;
+
+       nblocks = rijndaelBlockDecrypt (&ctx->aesContext, &ctx->aesDecKey,
+                                       data, 8 * len, data);
+       if (nblocks < 0)
+         return GC_INVALID_CIPHER;
+      }
+      break;
+#endif
+
+    default:
+      return GC_INVALID_CIPHER;
+    }
+
+  return GC_OK;
+}
+
+Gc_rc
+gc_cipher_close (gc_cipher_handle handle)
+{
+  _gc_cipher_ctx *ctx = handle;
+
+  if (ctx)
+    free (ctx);
+
+  return GC_OK;
+}
 
 /* Hashes. */
 
-int
+Gc_rc
 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
 {
   switch (hash)
     {
+#ifdef GC_USE_MD4
+    case GC_MD4:
+      md4_buffer (in, inlen, resbuf);
+      break;
+#endif
+
 #ifdef GC_USE_MD5
     case GC_MD5:
       md5_buffer (in, inlen, resbuf);
       break;
 #endif
 
+#ifdef GC_USE_SHA1
+    case GC_SHA1:
+      sha1_buffer (in, inlen, resbuf);
+      break;
+#endif
+
     default:
       return GC_INVALID_HASH;
     }
@@ -159,21 +513,49 @@ gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
   return GC_OK;
 }
 
+#ifdef GC_USE_MD4
+Gc_rc
+gc_md4 (const void *in, size_t inlen, void *resbuf)
+{
+  md4_buffer (in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
+
 #ifdef GC_USE_MD5
-int
+Gc_rc
 gc_md5 (const void *in, size_t inlen, void *resbuf)
 {
   md5_buffer (in, inlen, resbuf);
-  return 0;
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_SHA1
+Gc_rc
+gc_sha1 (const void *in, size_t inlen, void *resbuf)
+{
+  sha1_buffer (in, inlen, resbuf);
+  return GC_OK;
 }
 #endif
 
 #ifdef GC_USE_HMAC_MD5
-int
+Gc_rc
 gc_hmac_md5 (const void *key, size_t keylen,
             const void *in, size_t inlen, char *resbuf)
 {
   hmac_md5 (key, keylen, in, inlen, resbuf);
-  return 0;
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_HMAC_SHA1
+Gc_rc
+gc_hmac_sha1 (const void *key, size_t keylen,
+             const void *in, size_t inlen, char *resbuf)
+{
+  hmac_sha1 (key, keylen, in, inlen, resbuf);
+  return GC_OK;
 }
 #endif