/* -*-c-*-
*
- * $Id: rc4.c,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ * $Id: rc4.c,v 1.3 1999/12/13 15:34:01 mdw Exp $
*
* The alleged RC4 stream cipher
*
/*----- Revision history --------------------------------------------------*
*
* $Log: rc4.c,v $
+ * Revision 1.3 1999/12/13 15:34:01 mdw
+ * Add support for seeding from a generic pseudorandom source.
+ *
+ * Revision 1.2 1999/12/10 23:27:35 mdw
+ * Generic cipher and RNG interfaces.
+ *
* Revision 1.1 1999/09/03 08:41:12 mdw
* Initial import.
*
/*----- Header files ------------------------------------------------------*/
#include <assert.h>
+#include <stdarg.h>
#include <stdio.h>
#include <mLib/bits.h>
+#include <mLib/sub.h>
+#include "gcipher.h"
+#include "grand.h"
#include "rc4.h"
/*----- Main code ---------------------------------------------------------*/
if (p == q)
p = k;
}
-
-#ifdef notdef
- for (i = 0; i < 256; i += 16) {
- printf("%3d :", i);
- for (j = i; j < i + 16; j++)
- printf(" %02x", ctx->s[j]);
- putchar('\n');
- }
-#endif
}
/* --- @rc4_encrypt@ --- *
while (sz) { unsigned x; RC4_BYTE(x); *d++ = *s++ ^ x; sz--; });
}
+/*----- Generic cipher interface ------------------------------------------*/
+
+typedef struct gctx {
+ gcipher c;
+ rc4_ctx rc4;
+} gctx;
+
+static const gcipher_ops gops;
+
+static gcipher *ginit(const void *k, size_t sz)
+{
+ gctx *g = CREATE(gctx);
+ g->c.ops = &gops;
+ rc4_init(&g->rc4, k, sz);
+ return (&g->c);
+}
+
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
+{
+ gctx *g = (gctx *)c;
+ rc4_encrypt(&g->rc4, s, t, sz);
+}
+
+static void gdestroy(gcipher *c)
+{
+ gctx *g = (gctx *)c;
+ DESTROY(g);
+}
+
+static const gcipher_ops gops = {
+ &rc4.b,
+ gencrypt, gencrypt, gdestroy, 0, 0
+};
+
+const gccipher rc4 = {
+ { "rc4", 0, 0 },
+ ginit
+};
+
+/*----- Generic random number generator interface -------------------------*/
+
+typedef struct grctx {
+ grand r;
+ rc4_ctx rc4;
+} grctx;
+
+static void grdestroy(grand *r)
+{
+ grctx *g = (grctx *)r;
+ DESTROY(g);
+}
+
+static int grmisc(grand *r, unsigned op, ...)
+{
+ grctx *g = (grctx *)r;
+ va_list ap;
+ int rc = 0;
+ octet buf[4];
+ va_start(ap, op);
+
+ switch (op) {
+ case GRAND_CHECK:
+ switch (va_arg(ap, unsigned)) {
+ case GRAND_CHECK:
+ case GRAND_SEEDINT:
+ case GRAND_SEEDUINT32:
+ case GRAND_SEEDBLOCK:
+ case GRAND_SEEDRAND:
+ rc = 1;
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ break;
+ case GRAND_SEEDINT:
+ STORE32(buf, va_arg(ap, unsigned));
+ rc4_init(&g->rc4, buf, sizeof(buf));
+ break;
+ case GRAND_SEEDUINT32:
+ STORE32(buf, va_arg(ap, uint32));
+ rc4_init(&g->rc4, buf, sizeof(buf));
+ break;
+ case GRAND_SEEDBLOCK: {
+ const void *p = va_arg(ap, const void *);
+ size_t sz = va_arg(ap, size_t);
+ rc4_init(&g->rc4, p, sz);
+ } break;
+ case GRAND_SEEDRAND: {
+ grand *rr = va_arg(ap, grand *);
+ octet buf[16];
+ rr->ops->fill(rr, buf, sizeof(buf));
+ rc4_init(&g->rc4, buf, sizeof(buf));
+ } break;
+ default:
+ GRAND_BADOP;
+ break;
+ }
+
+ va_end(ap);
+ return (rc);
+}
+
+static octet grbyte(grand *r)
+{
+ grctx *g = (grctx *)r;
+ octet o;
+ RC4_OPEN(&g->rc4, RC4_BYTE(o););
+ return (o);
+}
+
+static uint32 grword(grand *r)
+{
+ grctx *g = (grctx *)r;
+ octet b[4];
+ int i;
+ RC4_OPEN(&g->rc4,
+ for (i = 0; i < sizeof(b); i++)
+ RC4_BYTE(b[i]););
+ return (LOAD32(b));
+}
+
+static void grfill(grand *r, void *p, size_t sz)
+{
+ grctx *g = (grctx *)r;
+ rc4_encrypt(&g->rc4, 0, p, sz);
+}
+
+static const grand_ops grops = {
+ "rc4",
+ 0,
+ grmisc, grdestroy,
+ grword, grbyte, grword, grand_range, grfill
+};
+
+/* --- @rc4_rand@ --- *
+ *
+ * Arguments: @const void *k@ = pointer to key material
+ * @size_t sz@ = size of key material
+ *
+ * Returns: Pointer to generic random number generator interface.
+ *
+ * Use: Creates a random number interface wrapper around an
+ * OFB-mode block cipher.
+ */
+
+grand *rc4_rand(const void *k, size_t sz)
+{
+ grctx *g = CREATE(grctx);
+ g->r.ops = &grops;
+ rc4_init(&g->rc4, k, sz);
+ return (&g->r);
+}
+
/*----- Test rig ----------------------------------------------------------*/
#ifdef TEST_RIG