/* Copyright (c) 2014, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/aead.h>

/* This program tests an AEAD against a series of test vectors from a file. The
 * test vector file consists of key-value lines where the key and value are
 * separated by a colon and optional whitespace. The keys are listed in
 * |NAMES|, below. The values are hex-encoded data.
 *
 * After a number of key-value lines, a blank line or EOF indicates the end of
 * the test case.
 *
 * For example, here's a valid test case:
 *
 *   KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
 *   NONCE: 978105dfce667bf4
 *   IN: 6a4583908d
 *   AD: b654574932
 *   CT: 5294265a60
 *   TAG: 1d45758621762e061368e68868e2f929
 */

#define BUF_MAX 512

/* These are the different types of line that are found in the input file. */
enum {
  KEY = 0, /* hex encoded key. */
  NONCE,   /* hex encoded nonce. */
  IN,      /* hex encoded plaintext. */
  AD,      /* hex encoded additional data. */
  CT,      /* hex encoded ciphertext (not including the authenticator,
              which is next). */
  TAG,     /* hex encoded authenticator. */
  NUM_TYPES,
};

static const char NAMES[6][NUM_TYPES] = {
    "KEY", "NONCE", "IN", "AD", "CT", "TAG",
};

static unsigned char hex_digit(char h) {
  if (h >= '0' && h <= '9') {
    return h - '0';
  } else if (h >= 'a' && h <= 'f') {
    return h - 'a' + 10;
  } else if (h >= 'A' && h <= 'F') {
    return h - 'A' + 10;
  } else {
    return 16;
  }
}

static int run_test_case(const EVP_AEAD *aead,
                         unsigned char bufs[NUM_TYPES][BUF_MAX],
                         const unsigned int lengths[NUM_TYPES],
                         unsigned int line_no) {
  EVP_AEAD_CTX ctx;
  size_t ciphertext_len, plaintext_len;
  unsigned char out[BUF_MAX + EVP_AEAD_MAX_OVERHEAD], out2[BUF_MAX];

  if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
                         NULL)) {
    fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
    return 0;
  }

  if (!EVP_AEAD_CTX_seal(&ctx, out, &ciphertext_len, sizeof(out), bufs[NONCE],
                         lengths[NONCE], bufs[IN], lengths[IN], bufs[AD],
                         lengths[AD])) {
    fprintf(stderr, "Failed to run AEAD on line %u\n", line_no);
    return 0;
  }

  if (ciphertext_len != lengths[CT] + lengths[TAG]) {
    fprintf(stderr, "Bad output length on line %u: %u vs %u\n", line_no,
            (unsigned)ciphertext_len, (unsigned)(lengths[CT] + lengths[TAG]));
    return 0;
  }

  if (memcmp(out, bufs[CT], lengths[CT]) != 0) {
    fprintf(stderr, "Bad output on line %u\n", line_no);
    return 0;
  }

  if (memcmp(out + lengths[CT], bufs[TAG], lengths[TAG]) != 0) {
    fprintf(stderr, "Bad tag on line %u\n", line_no);
    return 0;
  }

  if (!EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, lengths[IN], bufs[NONCE],
                         lengths[NONCE], out, ciphertext_len, bufs[AD],
                         lengths[AD])) {
    fprintf(stderr, "Failed to decrypt on line %u\n", line_no);
    return 0;
  }

  if (plaintext_len != lengths[IN]) {
    fprintf(stderr, "Bad decrypt on line %u: %u\n", line_no,
            (unsigned)ciphertext_len);
    return 0;
  }

  out[0] ^= 0x80;
  if (EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, lengths[IN], bufs[NONCE],
                        lengths[NONCE], out, ciphertext_len, bufs[AD],
                        lengths[AD])) {
    fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
    return 0;
  }

  EVP_AEAD_CTX_cleanup(&ctx);
  return 1;
}

int main(int argc, char **argv) {
  FILE *f;
  const EVP_AEAD *aead = NULL;
  unsigned int line_no = 0, num_tests = 0, j;

  unsigned char bufs[NUM_TYPES][BUF_MAX];
  unsigned int lengths[NUM_TYPES];

  if (argc != 3) {
    fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
    return 1;
  }

  if (strcmp(argv[1], "aes-128-gcm") == 0) {
    aead = EVP_aead_aes_128_gcm();
  } else if (strcmp(argv[1], "aes-256-gcm") == 0) {
    aead = EVP_aead_aes_256_gcm();
  } else if (strcmp(argv[1], "chacha20-poly1305") == 0) {
    aead = EVP_aead_chacha20_poly1305();
  } else {
    fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
    return 2;
  }

  f = fopen(argv[2], "r");
  if (f == NULL) {
    perror("failed to open input");
    return 1;
  }

  for (j = 0; j < NUM_TYPES; j++) {
    lengths[j] = 0;
  }

  for (;;) {
    char line[4096];
    unsigned int i, type_len = 0;

    unsigned char *buf = NULL;
    unsigned int *buf_len = NULL;

    if (!fgets(line, sizeof(line), f)) {
      break;
    }

    line_no++;
    if (line[0] == '#') {
      continue;
    }

    if (line[0] == '\n' || line[0] == 0) {
      /* Run a test, if possible. */
      char any_values_set = 0;
      for (j = 0; j < NUM_TYPES; j++) {
        if (lengths[j] != 0) {
          any_values_set = 1;
          break;
        }
      }

      if (!any_values_set) {
        continue;
      }

      if (!run_test_case(aead, bufs, lengths, line_no)) {
        return 4;
      }

      for (j = 0; j < NUM_TYPES; j++) {
        lengths[j] = 0;
      }

      num_tests++;
      continue;
    }

    /* Each line looks like:
     *   TYPE: 0123abc
     * Where "TYPE" is the type of the data on the line,
     * e.g. "KEY". */
    for (i = 0; line[i] != 0 && line[i] != '\n'; i++) {
      if (line[i] == ':') {
        type_len = i;
        break;
      }
    }
    i++;

    if (type_len == 0) {
      fprintf(stderr, "Parse error on line %u\n", line_no);
      return 3;
    }

    /* After the colon, there's optional whitespace. */
    for (; line[i] != 0 && line[i] != '\n'; i++) {
      if (line[i] != ' ' && line[i] != '\t') {
        break;
      }
    }

    line[type_len] = 0;
    for (j = 0; j < NUM_TYPES; j++) {
      if (strcmp(line, NAMES[j]) != 0) {
        continue;
      }
      if (lengths[j] != 0) {
        fprintf(stderr, "Duplicate value on line %u\n", line_no);
        return 3;
      }
      buf = bufs[j];
      buf_len = &lengths[j];
    }

    if (buf == NULL) {
      fprintf(stderr, "Unknown line type on line %u\n", line_no);
      return 3;
    }

    j = 0;
    for (; line[i] != 0 && line[i] != '\n'; i++) {
      unsigned char v, v2;
      v = hex_digit(line[i++]);
      if (line[i] == 0 || line[i] == '\n') {
        fprintf(stderr, "Odd-length hex data on line %u\n", line_no);
        return 3;
      }
      v2 = hex_digit(line[i]);
      if (v > 15 || v2 > 15) {
        fprintf(stderr, "Invalid hex char on line %u\n", line_no);
        return 3;
      }
      v <<= 4;
      v |= v2;

      if (j == BUF_MAX) {
        fprintf(stderr, "Too much hex data on line %u (max is %u bytes)\n",
                line_no, (unsigned)BUF_MAX);
        return 3;
      }
      buf[j++] = v;
      *buf_len = *buf_len + 1;
    }
  }

  printf("Completed %u test cases\n", num_tests);
  printf("PASS\n");
  fclose(f);

  return 0;
}
