return buffer;
}
+static FILE*
+file_open(char *filename)
+{
+ FILE *file = fopen(filename, "r");
+ if (file == NULL) {
+ fprintf(stderr, "Could not open file %s", filename);
+ exit(1);
+ }
+ return file;
+}
+
static unsigned
uint_of_char(unsigned char c)
{
if (c >= '0' && c <= '9') { return c - '0'; }
if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
- fprintf(stderr, "Not a hexadecimal char\n");
+ fprintf(stderr, "'%c' (%d): Not a hexadecimal char\n", c, c);
exit(1);
}
-static uint8_t*
-ascii_to_raw(const char *ascii)
+typedef struct {
+ uint8_t *buffer;
+ size_t buf_size;
+ size_t size;
+} vector;
+
+static vector
+vec_new(size_t buf_size)
{
- const size_t len = strlen(ascii);
- if (len % 2 != 0) {
- fprintf(stderr, "Hexa string has an odd length\n");
- exit(1);
- }
- const size_t size = len / 2;
- uint8_t *raw = alloc(size);
- for (unsigned i = 0; i < size; i++) {
- unsigned msb = uint_of_char(ascii[2*i + 0]);
- unsigned lsb = uint_of_char(ascii[2*i + 1]);
- raw[i] = lsb | (msb << 4);
- }
- return raw;
+ vector v;
+ v.buffer = alloc(buf_size);
+ v.buf_size = buf_size;
+ v.size = 0;
+ return v;
}
-static const char*
-test_chacha20(const char *key, const char *nonce, const char *stream)
+static vector
+vec_zero(size_t size)
{
- uint8_t *k = ascii_to_raw(key);
- uint8_t *n = ascii_to_raw(nonce);
- uint8_t *s = ascii_to_raw(stream);
- size_t size = strlen(stream) / 2;
- uint8_t *out = alloc(size);
- memset(out, 0, size);
- crypto_chacha_ctx ctx;
-
- crypto_init_chacha20(&ctx, k, n);
- crypto_encrypt_chacha20(&ctx, out, out, size);
- int match = memcmp(out, s, size) == 0;
+ vector v = vec_new(size);
+ memset(v.buffer, 0, size);
+ v.size = size;
+ return v;
+}
- free(out);
- free(s);
- free(n);
- free(k);
- return match ? "OK" : "FAIL! ABORT! REVIEW!";
+static void
+vec_del(vector *v)
+{
+ free(v->buffer);
}
static void
-chacha20(void)
+vec_push_back(vector *v, uint8_t e)
{
- static const char *k0 =
- "0000000000000000000000000000000000000000000000000000000000000000";
- static const char *k1 =
- "0000000000000000000000000000000000000000000000000000000000000001";
- static const char *kr =
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
+ if (v->buf_size == v->size) {
+ // double initial buffer size (and then some)
+ size_t new_buf_size = v->buf_size * 2 + 1;
+ uint8_t *new_buffer = alloc(new_buf_size);
+ memcpy(new_buffer, v->buffer, v->buf_size);
+ free(v->buffer);
+ v->buffer = new_buffer;
+ v->buf_size = new_buf_size;
+ }
+ v->buffer[v->size] = e;
+ v->size++;
+}
- static const char *n0 = "0000000000000000";
- static const char *n1 = "0000000000000001";
- static const char *n2 = "0100000000000000";
- static const char *nr = "0001020304050607";
+static vector
+read_hex_line(FILE *input_file)
+{
+ char c = getc(input_file);
+ while (c != '\t') {
+ c = getc(input_file);
+ }
+ vector v = vec_new(64);
+ c = getc(input_file);
+ while (c != '\n') {
+ uint8_t msb = uint_of_char(c); c = getc(input_file);
+ uint8_t lsb = uint_of_char(c); c = getc(input_file);
+ vec_push_back(&v, lsb | (msb << 4));
+ }
+ return v;
+}
- static const char *s00 =
- "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc"
- "8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11c"
- "c387b669b2ee6586";
- static const char *s10 =
- "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952"
- "ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea81"
- "7e9ad275ae546963";
- static const char *s01 =
- "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df1"
- "37821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e"
- "445f41e3";
- static const char *s02 =
- "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd1"
- "38e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d"
- "6bbdb0041b2f586b";
- static const char *srr =
- "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56"
- "f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1"
- "5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de9526"
- "4986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e"
- "09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750"
- "32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5"
- "07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f7"
- "6dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2"
- "ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab7"
- "8fab78c9";
+static int
+test_chacha20(char* filename)
+{
+ int status = 0;
+ FILE *file = file_open(filename);
+ while (getc(file) != EOF) {
+ vector key = read_hex_line(file);
+ vector nonce = read_hex_line(file);
+ vector stream = read_hex_line(file);
+ vector out = vec_zero(stream.size);
- printf("Chacha20, stream 0 0: %s\n", test_chacha20(k0, n0, s00));
- printf("Chacha20, stream 1 0: %s\n", test_chacha20(k1, n0, s10));
- printf("Chacha20, stream 0 1: %s\n", test_chacha20(k0, n1, s01));
- printf("Chacha20, stream 0 2: %s\n", test_chacha20(k0, n2, s02));
- printf("Chacha20, stream r r: %s\n", test_chacha20(kr, nr, srr));
+ crypto_chacha_ctx ctx;
+ crypto_init_chacha20(&ctx, key.buffer, nonce.buffer);
+ crypto_encrypt_chacha20(&ctx, out.buffer, out.buffer, out.size);
+ status |= memcmp(out.buffer, stream.buffer, out.size);
+
+ vec_del(&out);
+ vec_del(&stream);
+ vec_del(&nonce);
+ vec_del(&key);
+ }
+ printf("%s: chacha20\n", status != 0 ? "FAILED" : "OK");
+ fclose(file);
+ return status;
}
int main(void)
{
- chacha20();
- return 0;
+ int status = 0;
+ status |= test_chacha20("vectors_chacha20.txt");
+ return status;
}