From a86f5a1bea5ae057ec650e4b1af3985f53ccf350 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Thu, 31 May 2012 13:52:23 -0600 Subject: [PATCH] Bring arc4 back in --- packages/mcp/src/Makefile | 5 +- packages/mcp/src/arc4.c | 230 ++++++++++++++++++++++++++++++++++++++ packages/mcp/src/arc4.h | 40 +++++++ 3 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 packages/mcp/src/arc4.c create mode 100644 packages/mcp/src/arc4.h diff --git a/packages/mcp/src/Makefile b/packages/mcp/src/Makefile index 134ec7c..332dbe4 100644 --- a/packages/mcp/src/Makefile +++ b/packages/mcp/src/Makefile @@ -1,11 +1,14 @@ CFLAGS = -Wall -Werror TARGETS = claim.cgi puzzler.cgi puzzles.cgi -TARGETS += pointscli +TARGETS += pointscli arc4 all: build build: $(TARGETS) +arc4: CFLAGS += -DARC4_MAIN +arc4: arc4.o + pointscli: pointscli.o common.o puzzles.cgi: puzzles.cgi.o common.o diff --git a/packages/mcp/src/arc4.c b/packages/mcp/src/arc4.c new file mode 100644 index 0000000..01e3b27 --- /dev/null +++ b/packages/mcp/src/arc4.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include "arc4.h" + +#define swap(a, b) do {uint8_t _swap=a; a=b, b=_swap;} while (0) + +void +arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen) +{ + int i; + int j = 0; + + for (i = 0; i < 256; i += 1) { + ctx->S[i] = i; + } + + for (i = 0; i < 256; i += 1) { + j = (j + ctx->S[i] + key[i % keylen]) % 256; + swap(ctx->S[i], ctx->S[j]); + } + ctx->i = 0; + ctx->j = 0; +} + +uint8_t +arc4_out(struct arc4_ctx *ctx) +{ + ctx->i = (ctx->i + 1) % 256; + ctx->j = (ctx->j + ctx->S[ctx->i]) % 256; + swap(ctx->S[ctx->i], ctx->S[ctx->j]); + return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256]; +} + +void +arc4_crypt(struct arc4_ctx *ctx, + uint8_t *obuf, const uint8_t *ibuf, size_t buflen) +{ + size_t k; + + for (k = 0; k < buflen; k += 1) { + obuf[k] = ibuf[k] ^ arc4_out(ctx); + } +} + +/* Create a nonce as an arc4 stream with key=seed */ +void +arc4_nonce(uint8_t *nonce, size_t noncelen, + void *seed, size_t seedlen) +{ + struct arc4_ctx ctx; + int i; + + arc4_init(&ctx, seed, seedlen); + for (i = 0; i < noncelen; i += 1) { + nonce[i] = arc4_out(&ctx); + } +} + + +/*************************************************** + * + * Psuedo Random Number Generation + * + */ +static struct arc4_ctx prng_ctx; +static int prng_initialized = 0; + +void +arc4_rand_seed(const uint8_t *seed, size_t seedlen) +{ + arc4_init(&prng_ctx, seed, seedlen); + prng_initialized = 1; +} + +static void +arc4_rand_autoseed() +{ + if (! prng_initialized) { + uint8_t key[ARC4_KEYLEN]; + FILE *urandom; + + /* Open /dev/urandom or die trying */ + urandom = fopen("/dev/urandom", "r"); + if (! urandom) { + perror("Opening /dev/urandom"); + abort(); + } + setbuf(urandom, NULL); + fread(&key, sizeof(key), 1, urandom); + fclose(urandom); + + arc4_rand_seed(key, sizeof(key)); + } +} + +uint8_t +arc4_rand8() +{ + arc4_rand_autoseed(); + return arc4_out(&prng_ctx); +} + +uint32_t +arc4_rand32() +{ + arc4_rand_autoseed(); + return ((arc4_out(&prng_ctx) << 0) | + (arc4_out(&prng_ctx) << 8) | + (arc4_out(&prng_ctx) << 16) | + (arc4_out(&prng_ctx) << 24)); +} + +/***************************************** + * + * Stream operations + * + */ + +ssize_t +arc4_encrypt_stream(FILE *out, FILE *in, + const uint8_t *key, size_t keylen) +{ + struct arc4_ctx ctx; + uint32_t seed = arc4_rand32(); + uint8_t nonce[ARC4_KEYLEN]; + ssize_t written = 0; + int i; + + fwrite("arc4", 4, 1, out); + fwrite(&seed, sizeof(seed), 1, out); + + arc4_nonce(nonce, sizeof(nonce), &seed, sizeof(seed)); + for (i = 0; i < keylen; i += 1) { + nonce[i] ^= key[i]; + } + arc4_init(&ctx, nonce, sizeof(nonce)); + + while (1) { + int c = fgetc(in); + + if (EOF == c) break; + fputc((uint8_t)c ^ arc4_out(&ctx), out); + written += 1; + } + + return written; +} + +ssize_t +arc4_decrypt_stream(FILE *out, FILE *in, + const uint8_t *key, size_t keylen) +{ + struct arc4_ctx ctx; + uint32_t seed; + uint8_t nonce[ARC4_KEYLEN]; + ssize_t written = 0; + char sig[4]; + int i; + + fread(&sig, sizeof(sig), 1, in); + if (memcmp(sig, "arc4", 4)) { + return -1; + } + fread(&seed, sizeof(seed), 1, in); + + arc4_nonce(nonce, sizeof(nonce), &seed, sizeof(seed)); + for (i = 0; i < keylen; i += 1) { + nonce[i] ^= key[i]; + } + arc4_init(&ctx, nonce, sizeof(nonce)); + + while (1) { + int c = fgetc(in); + + if (EOF == c) break; + fputc((uint8_t)c ^ arc4_out(&ctx), out); + written += 1; + } + + return written; +} + + +#ifdef ARC4_MAIN + +#include +#include + +int +main(int argc, char *argv[]) +{ + uint8_t key[ARC4_KEYLEN] = {0}; + size_t keylen; + + /* Read key and initialize context */ + { + char *ekey = getenv("KEY"); + + if (ekey) { + keylen = strlen(ekey); + memcpy(key, ekey, keylen); + } else { + keylen = read(3, key, sizeof(key)); + if (-1 == keylen) { + fprintf(stderr, "error: must specify key.\n"); + return 1; + } + } + } + + if (! argv[1]) { + if (-1 == arc4_decrypt_stream(stdout, stdin, key, keylen)) { + fprintf(stderr, "error: not an arc4 stream.\n"); + return 1; + } + } else if (0 == strcmp(argv[1], "-e")) { + arc4_encrypt_stream(stdout, stdin, key, keylen); + } else { + fprintf(stderr, "Usage: %s [-e] +#include +#include + +#define ARC4_KEYLEN 256 + +struct arc4_ctx { + uint8_t S[256]; + uint8_t i; + uint8_t j; +}; + +/* Stream operations */ +ssize_t +arc4_encrypt_stream(FILE *out, FILE *in, + const uint8_t *key, size_t keylen); +ssize_t +arc4_decrypt_stream(FILE *out, FILE *in, + const uint8_t *key, size_t keylen); + + +/* Auto-seeding Psuedo Random Number Generator */ +void arc4_rand_seed(const uint8_t *seed, size_t seedlen); +uint8_t arc4_rand8(); +uint32_t arc4_rand32(); + +/* Low-level operations */ +void arc4_init(struct arc4_ctx *ctx, const uint8_t *key, size_t keylen); +uint8_t arc4_out(struct arc4_ctx *ctx); +void arc4_crypt(struct arc4_ctx *ctx, + uint8_t *obuf, const uint8_t *ibuf, size_t buflen); +void arc4_crypt_buffer(const uint8_t *key, size_t keylen, + uint8_t *buf, size_t buflen); +void arc4_nonce(uint8_t *nonce, size_t noncelen, void *seed, size_t seedlen); + + +#endif