]> Pileus Git - ~andy/crypt/commitdiff
Add some initial code master
authorAndy Spencer <andy753421@gmail.com>
Sun, 5 Jan 2014 04:57:44 +0000 (04:57 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sun, 5 Jan 2014 04:57:44 +0000 (04:57 +0000)
13 files changed:
.gitignore [new file with mode: 0644]
hmac.c [new file with mode: 0644]
main.c [new file with mode: 0644]
main.h [new file with mode: 0644]
makefile [new file with mode: 0644]
none.c [new file with mode: 0644]
none.h [new file with mode: 0644]
scrypt.c [new file with mode: 0644]
scrypt.h [new file with mode: 0644]
sha2.c [new file with mode: 0644]
sha2.h [new file with mode: 0644]
util.c [new file with mode: 0644]
util.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..0441756
--- /dev/null
@@ -0,0 +1,6 @@
+*~
+*.o
+*.swp
+*.txt
+crypt
+tags
diff --git a/hmac.c b/hmac.c
new file mode 100644 (file)
index 0000000..20d097b
--- /dev/null
+++ b/hmac.c
@@ -0,0 +1,29 @@
+/* HMAC */
+static void hmac_gen(hash_t hash, int iter,
+               const char *out,  int nout,
+               const char *msg,  int nmsg,
+               const char *pass, int npass,
+               const char *salt, int nsalt);
+{
+       // iter - ??
+
+       uint8_t *opad = alloc0(nout);
+       uint8_t *ipad = alloc0(nout);
+       uint8_t *buf  = alloc0(nout);
+       uint8_t *tmp1 = alloc0(nout+nmsg);
+       uint8_t *tmp2 = alloc0(nout+2);
+
+       if (npass > nout)
+               hash(buf, key);
+       else if (npass < nout)
+               memcpy(buf, key, npass);
+
+       for (int i = 0; i < nout; i++) {
+               opad[i] = 0x5c ^ key[i];
+               ipad[i] = 0x36 ^ key[i];
+       }
+
+       memcpy(tmp1, ipad, message);
+       hash(tmp, ipad + message);
+       hash(out, opad + tmp)
+}
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..5545cff
--- /dev/null
+++ b/main.c
@@ -0,0 +1,210 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "util.h"
+
+#include "none.h"
+#include "sha2.h"
+#include "scrypt.h"
+
+/* Options */
+#define OPT(flag, opt, name, desc) \
+       { name "\0" desc, flag, NULL, opt }
+
+#define OPT_OPT(opt)  ((opt).val)
+#define OPT_LEN(opt)  ((int)strlen((opt).name))
+#define OPT_NAME(opt) ((opt).name)
+#define OPT_DESC(opt) (&(opt).name[OPT_LEN(opt)])
+
+/* Crypto functions */
+typedef enum {
+       NONE,
+       SHA256,
+       SCRYPT,
+} crypt_t;
+
+/* Options */
+static struct option long_options[] = {
+       OPT( 0, 'e', "encrypt",  "Encrypt data"            ),
+       OPT( 0, 'd', "decrypt",  "Decrypt data"            ),
+       OPT( 0, 't', "test",     "Run self tests"          ),
+       OPT( 1, 'f', "function", "Specify crypto function" ),
+       OPT( 1, 'i', "input",    "Input file"              ),
+       OPT( 1, 'o', "output",   "Output file"             ),
+       OPT( 0, 'q', "quiet",    "Decrease verbosity"      ),
+       OPT( 0, 'v', "verbose",  "Increase verbosity"      ),
+       OPT( 0, 'h', "help",     "Print usage information" ),
+       { },
+};
+
+static struct {
+       const char *name;
+       const char *desc;
+} crypt_info[] = {
+       [NONE  ] { "none",   "No-op encryption/decryption" },
+       [SHA256] { "sha256", "SHA-256 hash function" },
+       [SCRYPT] { "scrypt", "Memory intensive hash function" },
+};
+
+/* Settings */
+static int      opt_decrypt;
+static int      opt_encrypt;
+static crypt_t  opt_crypt;
+static char    *opt_instr;
+static char    *opt_outstr;
+static FILE    *opt_input;
+static FILE    *opt_output;
+static int      opt_level;
+static int      opt_test;
+
+/* Helpers */
+static const char *crypt_name(crypt_t id)
+{
+       if (id < 0 || id >= N_ELEM(crypt_info))
+               error("invalid crypt id %d", id);
+       return crypt_info[id].name;
+}
+
+static crypt_t crypt_id(const char *name)
+{
+       for (int i = 0; i < N_ELEM(crypt_info); i++)
+               if (!strcmp(name, crypt_info[i].name))
+                       return (crypt_t)i;
+       error("invalid crypt function %s", name);
+       return NONE;
+}
+
+static void usage(const char *name)
+{
+       printf("Usage:\n");
+       printf("  %s [OPTION...]\n", name);
+       printf("\n");
+       printf("Options:\n");
+       for (int i = 0; long_options[i].name; i++)
+               printf("  -%c, --%-10s  %s\n",
+                       long_options[i].val,
+                       long_options[i].name,
+                       long_options[i].name + 1 +
+                               strlen(long_options[i].name));
+       printf("\n");
+       printf("Crypto functions:\n");
+       for (int i = 0; i < N_ELEM(crypt_info); i++)
+               printf("  %-16s  %s\n",
+                       crypt_info[i].name,
+                       crypt_info[i].desc);
+}
+
+static void parse(int argc, char **argv)
+{
+       while (1) {
+               int c = getopt_long(argc, argv, "edf:i:o:qvth", long_options, NULL);
+               if (c == -1)
+                       break;
+               switch (c) {
+                       case 'e':
+                               opt_encrypt = 1;
+                               break;
+                       case 'd':
+                               opt_decrypt = 1;
+                               break;
+                       case 't':
+                               opt_test = 1;
+                               break;
+                       case 'f':
+                               opt_crypt = crypt_id(optarg);
+                               break;
+                       case 'i':
+                               opt_input  = fopen(optarg, "rb");
+                               opt_instr  = optarg;
+                               break;
+                       case 'o':
+                               opt_output = fopen(optarg, "wb+");
+                               opt_outstr = optarg;
+                               break;
+                       case 'q':
+                               opt_level--;
+                               break;
+                       case 'v':
+                               opt_level++;
+                               break;
+                       case 'h':
+                               usage(argv[0]);
+                               exit(0);
+                       case '?':
+                               exit(1);
+                       default:
+                               exit(2);
+               }
+       }
+}
+
+void run(crypt_t id, FILE *in, FILE *out)
+{
+       uint8_t dec[512], enc[512];
+       uint8_t sum[512];
+       int len;
+
+       switch (id) {
+               case NONE:
+                       while ((len = fread(&dec, 1, 512, in)) > 0) {
+                               //debug("<< [%s]:%d", dec, len);
+                               none_enc(dec, enc, len);
+                               //debug(">> [%s]:%d", enc, len);
+                               fwrite(enc, 1, len, out);
+                       }
+                       break;
+               case SHA256:
+                       break;
+               case SCRYPT:
+                       while ((len = fread(&dec, 1, 512, in)) > 0) {
+                               scrypt_hash(dec, sum);
+                       }
+                       break;
+       }
+}
+
+/* Test */
+static void test(crypt_t id)
+{
+       if (!opt_test)
+               return;
+
+       switch (id) {
+               case NONE:   none_test();   break;
+               case SHA256: sha256_test(); break;
+               case SCRYPT: scrypt_test(); break;
+       }
+}
+
+/* Main */
+int main(int argc, char **argv)
+{
+       /* Parse arguments */
+       opt_instr  = "stdin";
+       opt_outstr = "stdout";
+       opt_input  = stdin;
+       opt_output = stdout;
+       parse(argc, argv);
+       loglevel = opt_level;
+
+       /* Debug output */
+       debug("encrypt:  %s", opt_encrypt ? "true" : "false");
+       debug("decrypt:  %s", opt_decrypt ? "true" : "false");
+       debug("crypto:   %s", crypt_name(opt_crypt));
+       debug("loglevel: %d", opt_level);
+       debug("input:    %s", opt_instr);
+       debug("output:   %s", opt_outstr);
+
+       /* Run tests */
+       test(opt_crypt);
+
+       /* Main loop */
+       run(opt_crypt, opt_input, opt_output);
+
+       return 0;
+};
+
diff --git a/main.h b/main.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/makefile b/makefile
new file mode 100644 (file)
index 0000000..4a3ba25
--- /dev/null
+++ b/makefile
@@ -0,0 +1,21 @@
+PROG     ?= crypt
+GCC      ?= gcc
+CFLAGS   ?= -Wall -Werror --std=c99
+CPPFLAGS ?=
+LDFLAGS  ?= -lfitz
+
+# Targets
+test: $(PROG)
+       echo test | ./$(PROG) -v -t -f scrypt
+
+all: $(PROG)
+
+clean:
+       rm -f *.o $(PROG)
+
+# Rules
+$(PROG): main.o util.o none.o sha2.o scrypt.o
+       $(GCC) $(CFLAGS) -o $@ $+ $(LDFLAGS)
+
+%.o: %.c makefile $(wildcard *.h)
+       $(GCC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
diff --git a/none.c b/none.c
new file mode 100644 (file)
index 0000000..48df738
--- /dev/null
+++ b/none.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+#include "none.h"
+
+void none_test(void)
+{
+}
+
+void none_enc(void *in, void *out, int len)
+{
+       memcpy(out, in, len);
+}
+
+void none_dec(void *in, void *out, int len)
+{
+       memcpy(out, in, len);
+}
diff --git a/none.h b/none.h
new file mode 100644 (file)
index 0000000..210f111
--- /dev/null
+++ b/none.h
@@ -0,0 +1,4 @@
+/* none functions */
+void none_test(void);
+void none_enc(void *in, void *out, int len);
+void none_dec(void *in, void *out, int len);
diff --git a/scrypt.c b/scrypt.c
new file mode 100644 (file)
index 0000000..a85eccd
--- /dev/null
+++ b/scrypt.c
@@ -0,0 +1,245 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+#include "sha2.h"
+#include "scrypt.h"
+
+/**
+ * Name  RFC    Description
+ * pass  P      Passphrase, an octet string.
+ * salt  S      Salt, an octet string.
+ * cost  N      CPU/Memory cost parameter
+ * bs    r      Block size parameter.
+ * par   p      Parallelization parameter
+ * len?  dkLen  Intended output length
+ * in    B      Input data
+ * out   B'     Output data
+ */
+
+/* Types */
+typedef void hash_t(uint8_t *out, const uint8_t *in, int len);
+
+/* Helpers */
+#if 0
+static int mod(uint8_t out[64], uint8_t in[64])
+{
+}
+
+static void copy(uint8_t out[64], uint8_t in[64])
+{
+}
+
+static void xor(uint8_t out[64], uint8_t a[64], uint8_t b[64])
+{
+}
+#endif
+
+/* HMAC */
+static void hmac_gen(hash_t hash,
+               uint8_t *out, int nout,
+               const uint8_t *key, int nkey,
+               const uint8_t *msg, int nmsg)
+{
+       uint8_t *fix  = alloc0(nout);
+       uint8_t *ipad = alloc0(nout+nmsg);
+       uint8_t *opad = alloc0(nout+nout);
+
+       /* Fixup key */
+       if (nkey > nout)
+               hash(fix, key, nkey);
+       else
+               memcpy(fix, key, nkey);
+
+       /* Create pad strings */
+       for (int i = 0; i < nout; i++) {
+               opad[i] = 0x5c ^ fix[i];
+               ipad[i] = 0x36 ^ fix[i];
+       }
+
+       /* Run hashes - hash(o+hash(i+msg)) */
+       memcpy(ipad+nout, msg, nmsg);
+       hash(opad+nout, ipad, nout+nmsg);
+       hash(out, opad, nout+nout);
+
+       /* Cleanup */
+       free(fix);
+       free(opad);
+       free(ipad);
+}
+
+/* PBKDF2 */
+static void pbkdf2_gen(uint8_t *out, int nout,
+               const uint8_t *pass, int npass,
+               const uint8_t *salt, int nsalt,
+               int iter)
+{
+       int      nbuf = nsalt + 4;
+       uint8_t *buf  = alloc0(nbuf);
+       memcpy(buf, salt, nsalt);
+
+       const int nptr = 256/8;
+
+       for (int i = 0; i < nout/nptr; i++) {
+               uint8_t *ptr = &out[i*nptr];
+
+               buf[nsalt+0] = ((i+1) & 0xFF000000) >> 030;
+               buf[nsalt+1] = ((i+1) & 0x00FF0000) >> 020;
+               buf[nsalt+2] = ((i+1) & 0x0000FF00) >> 010;
+               buf[nsalt+3] = ((i+1) & 0x000000FF) >> 000;
+
+               hmac_gen(sha256_hash, ptr, nptr, pass, npass, buf, nbuf);
+               for (int j = 1; j < iter; j++)
+                       hmac_gen(sha256_hash, ptr, nptr, pass, npass, ptr, nptr);
+       }
+
+       free(buf);
+}
+
+static void pbkdf2_gen_str(uint8_t *out, int nout,
+               const char *pass, const char *salt, int iter)
+{
+       pbkdf2_gen(out, nout,
+               (const uint8_t *)pass, strlen(pass),
+               (const uint8_t *)salt, strlen(salt), iter);
+}
+
+/* Salsa20/8 */
+static void salsa(uint8_t out[64], uint8_t in[64])
+{
+}
+
+/* scrypt */
+#if 0
+static void block_mix(uint8_t *out[64], uint8_t *in[64], int bs)
+{
+       // xor each block with the last block
+       // alternat first/second half for result
+
+       uint8_t tmp[64]
+       for (int i = 0; i < 2*r; i++) {
+               int o = bs*(i%2) + (i/2);
+               xor(tmp, in[2*r - 1], in[i]);
+               salsa(out[o], tmp);
+       }
+}
+
+static void ro_mix(uint8_t *out[128], uint8_t *in[128], int cost, int bs)
+{
+       // generate vector of size cost
+       // randomly collapse vector as output
+
+       uint8_t *state[64];
+       uint8_t *mixed[64];
+       uint8_t *tmp[64];
+
+       copy(state, in);
+
+       for (i = 0; i < cost; i++) {
+               copy(mixed[i], state);
+               block_mix(state, state);
+       }
+
+       for (i = 0; i < cost; i++) {
+               int j = mod(state, cost);
+               xor(tmp, state, mixed[j]);
+               block_mix(state, tmp);
+       }
+
+       copy(out, state);
+}
+
+static void scrypt_run(uint8_t out[64],
+               char *pass, char *salt,
+               int cost, int bs, int par, int len)
+{
+       // hash pass/salt into large buffer
+       // mix each buffer (in parallel)
+       // combine bubers into output
+
+       sha256_hmac(buf, pass, salt, 1, par * 128 * bs);
+
+       for (i = 0; i < par; i++)
+               buf[i] = ro_mix(buf[i], cost, bs);
+
+       sha256_hmac(out, pass, buf, 1, len);
+}
+#endif
+
+/* Entry point */
+void scrypt_hash(uint8_t *in, uint8_t *sum)
+{
+       *sum = 0;
+}
+
+/* Tests */
+#if 0
+static void test_script(void)
+{
+       /* Parameters */
+       const int   cost = 1024;
+       const int   bs   = 1;
+       const int   par  = 1;
+       const int   len  = 32;
+
+       /* Input data */
+       const char *pass = "hello";
+       const char *salt = "world";
+
+       /* Output data */
+       static uint8_t out[32];
+
+       /* Run the hash */
+       scrypt_hash(out, pass, salt, par, bs, len);
+
+       /* Print output */
+}
+#endif
+
+static void test_keygen(void)
+{
+       const uint8_t truth0[] = {
+               0x55, 0xac, 0x04, 0x6e, 0x56, 0xe3, 0x08, 0x9f,
+               0xec, 0x16, 0x91, 0xc2, 0x25, 0x44, 0xb6, 0x05,
+               0xf9, 0x41, 0x85, 0x21, 0x6d, 0xde, 0x04, 0x65,
+               0xe6, 0x8b, 0x9d, 0x57, 0xc2, 0x0d, 0xac, 0xbc,
+               0x49, 0xca, 0x9c, 0xcc, 0xf1, 0x79, 0xb6, 0x45,
+               0x99, 0x16, 0x64, 0xb3, 0x9d, 0x77, 0xef, 0x31,
+               0x7c, 0x71, 0xb8, 0x45, 0xb1, 0xe3, 0x0b, 0xd5,
+               0x09, 0x11, 0x20, 0x41, 0xd3, 0xa1, 0x97, 0x83,
+       };
+
+       const uint8_t truth1[] = {
+               0x4d, 0xdc, 0xd8, 0xf6, 0x0b, 0x98, 0xbe, 0x21,
+               0x83, 0x0c, 0xee, 0x5e, 0xf2, 0x27, 0x01, 0xf9,
+               0x64, 0x1a, 0x44, 0x18, 0xd0, 0x4c, 0x04, 0x14,
+               0xae, 0xff, 0x08, 0x87, 0x6b, 0x34, 0xab, 0x56,
+               0xa1, 0xd4, 0x25, 0xa1, 0x22, 0x58, 0x33, 0x54,
+               0x9a, 0xdb, 0x84, 0x1b, 0x51, 0xc9, 0xb3, 0x17,
+               0x6a, 0x27, 0x2b, 0xde, 0xbb, 0xa1, 0xd0, 0x78,
+               0x47, 0x8f, 0x62, 0xb3, 0x97, 0xf3, 0x3c, 0x8d,
+       };
+
+       uint8_t out0[64] = {};
+       uint8_t out1[64] = {};
+
+       //             output     password    salt    iters
+       pbkdf2_gen_str(out0, 64,  "passwd",   "salt", 1);
+       //pbkdf2_gen_str(out1, 64,  "Password", "NaCl", 80000);
+
+       hexdump("\nTest #1", NULL, truth0, 64);
+       hexdump("",          NULL, out0,   64);
+
+       hexdump("\nTest #2", NULL, truth1, 64);
+       hexdump("",          NULL, out1,   64);
+
+       (void)salsa;
+       (void)pbkdf2_gen;
+       (void)hmac_gen;
+}
+
+void scrypt_test(void)
+{
+       test_keygen();
+}
diff --git a/scrypt.h b/scrypt.h
new file mode 100644 (file)
index 0000000..1ee717b
--- /dev/null
+++ b/scrypt.h
@@ -0,0 +1,3 @@
+/* scrypt functions */
+void scrypt_test();
+void scrypt_hash(uint8_t *in, uint8_t *sum);
diff --git a/sha2.c b/sha2.c
new file mode 100644 (file)
index 0000000..b686d3e
--- /dev/null
+++ b/sha2.c
@@ -0,0 +1,49 @@
+#include <stdint.h>
+
+#include "util.h"
+#include "sha2.h"
+
+/* Hashes:
+ *   SHA-224
+ *   SHA-256
+ *   SHA-384
+ *   SHA-512
+ *   SHA-512/224
+ *   SHA-512/256
+ */
+
+/* From Fitz */
+typedef struct {
+       unsigned int state[8];
+       unsigned int count[2];
+       union {
+               unsigned char u8[64];
+               unsigned int u32[16];
+       } buffer;
+} fz_sha256;
+
+void fz_sha256_init(fz_sha256 *state);
+void fz_sha256_update(fz_sha256 *state, const unsigned char *input, unsigned int inlen);
+void fz_sha256_final(fz_sha256 *state, unsigned char digest[32]);
+
+/* SHA-256 */
+void sha256_hash(uint8_t out[32], const uint8_t *data, int len)
+{
+       fz_sha256 state = {};
+
+       fz_sha256_init(&state);
+       fz_sha256_update(&state, data, len);
+       fz_sha256_final(&state, out);
+}
+
+/* Test */
+void sha256_test(void)
+{
+       uint8_t in[]    = "hello";
+       uint8_t out[32] = {};
+
+       sha256_hash(out, in, sizeof(in)-1);
+
+       hexdump("Input:",  "\t%04x: ", in,  sizeof(in)-1);
+       hexdump("Output:", "\t%04x: ", out, sizeof(out));
+}
diff --git a/sha2.h b/sha2.h
new file mode 100644 (file)
index 0000000..476c6a0
--- /dev/null
+++ b/sha2.h
@@ -0,0 +1,3 @@
+/* SHA-2 functions */
+void sha256_test(void);
+void sha256_hash(uint8_t out[32], const uint8_t *data, int len);
diff --git a/util.c b/util.c
new file mode 100644 (file)
index 0000000..dd047b8
--- /dev/null
+++ b/util.c
@@ -0,0 +1,98 @@
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Log levels */
+#define LOG_DEFAULT LOG_INFO
+
+typedef enum {
+       LOG_DEBUG,
+       LOG_INFO,
+       LOG_WARN,
+       LOG_ERROR,
+} log_t;
+
+/* Globals */
+int loglevel;
+
+/* Helper functions */
+static void message(int level, const char *prefix, const char *fmt, va_list ap)
+{
+       if (level >= LOG_DEFAULT-loglevel) {
+               fprintf(stderr, "%s: ", prefix);
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+       }
+}
+
+/* Mesage functions */
+void debug(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       message(LOG_DEBUG, "debug", fmt, ap);
+       va_end(ap);
+}
+
+void info(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       message(LOG_INFO, "info", fmt, ap);
+       va_end(ap);
+}
+
+void warn(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       message(LOG_WARN, "warning", fmt, ap);
+       va_end(ap);
+}
+
+void error(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       message(LOG_ERROR, "error", fmt, ap);
+       va_end(ap);
+       exit(1);
+}
+
+/* Hex dump */
+void hexdump(const char *label, const char *prefix,
+               const uint8_t *data, int len, ...)
+{
+       va_list ap;
+       va_start(ap, len);
+
+       if (!label)   label  = "";
+       if (!prefix)  prefix = "%04x: ";
+
+       vprintf(label, ap);
+       for (int i = 0; i < len; i++) {
+               if ((i % 16) == 0) {
+                       printf("\n");
+                       printf(prefix, i);
+               } else if ((i % 8) == 0) {
+                       printf("  ");
+               } else if ((i % 2) == 0) {
+                       printf(" ");
+               }
+               printf("%02hhx", data[i]);
+       }
+       printf("\n");
+
+       va_end(ap);
+}
+
+
+/* Misc */
+void *alloc0(int size)
+{
+       void *out = calloc(1, size);
+       if (!out)
+               error("Alloc failed");
+       return out;
+}
diff --git a/util.h b/util.h
new file mode 100644 (file)
index 0000000..4ab68e3
--- /dev/null
+++ b/util.h
@@ -0,0 +1,17 @@
+/* Macros */
+#define N_ELEM(x) (sizeof(x)/sizeof(*(x)))
+
+/* Globals */
+extern int loglevel;
+
+/* Debug functions */
+void info(const char *fmt, ...);
+void debug(const char *fmt, ...);
+void warn(const char *fmt, ...);
+void error(const char *fmt, ...);
+
+/* Output functions */
+void hexdump(const char *fmt, const char *prefix, const uint8_t *data, ...);
+
+/* Misc */
+void *alloc0(int size);