diff rc4.c @ 143:5d99163f7e32 libtomcrypt-orig

import of libtomcrypt 0.99
author Matt Johnston <matt@ucc.asn.au>
date Sun, 19 Dec 2004 11:34:45 +0000
parents 7faae8f46238
children
line wrap: on
line diff
--- a/rc4.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rc4.c	Sun Dec 19 11:34:45 2004 +0000
@@ -14,11 +14,15 @@
 
 const struct _prng_descriptor rc4_desc = 
 {
-   "rc4",
+   "rc4", 32,
     &rc4_start,
     &rc4_add_entropy,
     &rc4_ready,
-    &rc4_read
+    &rc4_read,
+    &rc4_done,
+    &rc4_export,
+    &rc4_import,
+    &rc4_test
 };
 
 int rc4_start(prng_state *prng)
@@ -33,11 +37,18 @@
 
 int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
 {
-    _ARGCHK(buf != NULL);
+    _ARGCHK(buf  != NULL);
     _ARGCHK(prng != NULL);
-
+ 
+    /* trim as required */
     if (prng->rc4.x + len > 256) {
-       return CRYPT_INVALID_KEYSIZE;
+       if (prng->rc4.x == 256) {
+          /* I can't possibly accept another byte, ok maybe a mint wafer... */
+          return CRYPT_OK;
+       } else {
+          /* only accept part of it */
+          len = 256 - prng->rc4.x;
+       }       
     }
 
     while (len--) {
@@ -50,26 +61,30 @@
 
 int rc4_ready(prng_state *prng)
 {
-    unsigned char key[256], tmp;
-    int keylen, x, y;
+    unsigned char key[256], tmp, *s;
+    int keylen, x, y, j;
 
     _ARGCHK(prng != NULL);
 
     /* extract the key */
-    memcpy(key, prng->rc4.buf, 256);
+    s = prng->rc4.buf;
+    XMEMCPY(key, s, 256);
     keylen = prng->rc4.x;
 
     /* make RC4 perm and shuffle */
     for (x = 0; x < 256; x++) {
-        prng->rc4.buf[x] = x;
+        s[x] = x;
     }
 
-    for (x = y = 0; x < 256; x++) {
-        y = (y + prng->rc4.buf[x] + key[x % keylen]) & 255;
-        tmp = prng->rc4.buf[x]; prng->rc4.buf[x] = prng->rc4.buf[y]; prng->rc4.buf[y] = tmp;
+    for (j = x = y = 0; x < 256; x++) {
+        y = (y + prng->rc4.buf[x] + key[j++]) & 255;
+        if (j == keylen) {
+           j = 0; 
+        }
+        tmp = s[x]; s[x] = s[y]; s[y] = tmp;
     }
-    prng->rc4.x = x;
-    prng->rc4.y = y;
+    prng->rc4.x = 0;
+    prng->rc4.y = 0;
 
 #ifdef CLEAN_STACK
     zeromem(key, sizeof(key));
@@ -80,8 +95,7 @@
 
 unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng)
 {
-   int x, y; 
-   unsigned char *s, tmp;
+   unsigned char x, y, *s, tmp;
    unsigned long n;
 
    _ARGCHK(buf != NULL);
@@ -103,5 +117,92 @@
    return n;
 }
 
+int rc4_done(prng_state *prng)
+{
+   _ARGCHK(prng != NULL);
+   return CRYPT_OK;
+}
+
+int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(prng   != NULL);
+
+   if (*outlen < 32) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   if (rc4_read(out, 32, prng) != 32) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   *outlen = 32;
+
+   return CRYPT_OK;
+}
+ 
+int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   int err;
+   _ARGCHK(in   != NULL);
+   _ARGCHK(prng != NULL);
+
+   if (inlen != 32) {
+      return CRYPT_INVALID_ARG;
+   }
+   
+   if ((err = rc4_start(prng)) != CRYPT_OK) {
+      return err;
+   }
+   return rc4_add_entropy(in, 32, prng);
+}
+
+int rc4_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct {
+      unsigned char key[8], pt[8], ct[8];
+   } tests[] = {
+{
+   { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+   { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+   { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }
+}
+};
+   prng_state prng;
+   unsigned char dst[8];
+   int err, x;
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       if ((err = rc4_start(&prng)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = rc4_ready(&prng)) != CRYPT_OK) {
+          return err;
+       }
+       XMEMCPY(dst, tests[x].pt, 8);
+       if (rc4_read(dst, 8, &prng) != 8) {
+          return CRYPT_ERROR_READPRNG;
+       }
+       rc4_done(&prng);
+       if (memcmp(dst, tests[x].ct, 8)) {
+#if 0
+          int y;
+          printf("\n\nRC4 failed, I got:\n"); 
+          for (y = 0; y < 8; y++) printf("%02x ", dst[y]);
+          printf("\n");
+#endif
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   return CRYPT_OK;
+#endif
+}
+
 #endif