/* 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 <stdio.h>
#include <string.h>

#include <string>
#include <vector>

#include <openssl/base64.h>
#include <openssl/crypto.h>
#include <openssl/err.h>

#include "../internal.h"


enum encoding_relation {
  // canonical indicates that the encoding is the expected encoding of the
  // input.
  canonical,
  // valid indicates that the encoding is /a/ valid encoding of the input, but
  // need not be the canonical one.
  valid,
  // invalid indicates that the encoded data is valid.
  invalid,
};

struct TestVector {
  enum encoding_relation relation;
  const char *decoded;
  const char *encoded;
};

// Test vectors from RFC 4648.
static const TestVector kTestVectors[] = {
    {canonical, "", ""},
    {canonical, "f", "Zg==\n"},
    {canonical, "fo", "Zm8=\n"},
    {canonical, "foo", "Zm9v\n"},
    {canonical, "foob", "Zm9vYg==\n"},
    {canonical, "fooba", "Zm9vYmE=\n"},
    {canonical, "foobar", "Zm9vYmFy\n"},
    {valid, "foobar", "Zm9vYmFy\n\n"},
    {valid, "foobar", " Zm9vYmFy\n\n"},
    {valid, "foobar", " Z m 9 v Y m F y\n\n"},
    {invalid, "", "Zm9vYmFy=\n"},
    {invalid, "", "Zm9vYmFy==\n"},
    {invalid, "", "Zm9vYmFy===\n"},
    {invalid, "", "Z"},
    {invalid, "", "Z\n"},
    {invalid, "", "ab!c"},
    {invalid, "", "ab=c"},
    {invalid, "", "abc"},

    {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n"},
    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n"},
    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n"},
    {invalid, "",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n==\n"},
    {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
     "4eHh4eHh4\n"},
    {canonical,
     "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
     "4eHh4eHh4eHh4eA==\n"},
    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh"
     "4eHh4eHh4eHh4eA==\n"},
    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e"
     "Hh4eHh4eHh4eA==\n"},
    {invalid, "",
     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=="
     "\neHh4eHh4eHh4eHh4eHh4eHh4\n"},

    // A '-' has traditionally been treated as the end of the data by OpenSSL
    // and anything following would be ignored. BoringSSL does not accept this
    // non-standard extension.
    {invalid, "", "Zm9vYmFy-anythinggoes"},
    {invalid, "", "Zm9vYmFy\n-anythinggoes"},

    // CVE-2015-0292
    {invalid, "",
     "ZW5jb2RlIG1lCg==========================================================="
     "=======\n"},
};

static const size_t kNumTests = OPENSSL_ARRAY_SIZE(kTestVectors);

// RemoveNewlines returns a copy of |in| with all '\n' characters removed.
static std::string RemoveNewlines(const char *in) {
  std::string ret;
  const size_t in_len = strlen(in);

  for (size_t i = 0; i < in_len; i++) {
    if (in[i] != '\n') {
      ret.push_back(in[i]);
    }
  }

  return ret;
}

static bool TestEncodeBlock() {
  for (unsigned i = 0; i < kNumTests; i++) {
    const TestVector *t = &kTestVectors[i];
    if (t->relation != canonical) {
      continue;
    }

    const size_t decoded_len = strlen(t->decoded);
    size_t max_encoded_len;
    if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
      fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i);
      return false;
    }

    std::vector<uint8_t> out_vec(max_encoded_len);
    uint8_t *out = out_vec.data();
    size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len);

    std::string encoded(RemoveNewlines(t->encoded));
    if (len != encoded.size() ||
        OPENSSL_memcmp(out, encoded.data(), len) != 0) {
      fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
              t->decoded, (int)len, (const char*)out, encoded.c_str());
      return false;
    }
  }

  return true;
}

static bool TestDecodeBase64() {
  size_t len;

  for (unsigned i = 0; i < kNumTests; i++) {
    const TestVector *t = &kTestVectors[i];

    if (t->relation == valid) {
      // The non-canonical encodings will generally have odd whitespace etc
      // that |EVP_DecodeBase64| will reject.
      continue;
    }

    const std::string encoded(RemoveNewlines(t->encoded));
    std::vector<uint8_t> out_vec(encoded.size());
    uint8_t *out = out_vec.data();

    int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
                              (const uint8_t *)encoded.data(), encoded.size());

    if (t->relation == invalid) {
      if (ok) {
        fprintf(stderr, "decode(\"%s\") didn't fail but should have\n",
                encoded.c_str());
        return false;
      }
    } else if (t->relation == canonical) {
      if (!ok) {
        fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str());
        return false;
      }

      if (len != strlen(t->decoded) ||
          OPENSSL_memcmp(out, t->decoded, len) != 0) {
        fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
                encoded.c_str(), (int)len, (const char*)out, t->decoded);
        return false;
      }
    }
  }

  return true;
}

static bool TestDecodeBlock() {
  for (unsigned i = 0; i < kNumTests; i++) {
    const TestVector *t = &kTestVectors[i];
    if (t->relation != canonical) {
      continue;
    }

    std::string encoded(RemoveNewlines(t->encoded));

    std::vector<uint8_t> out_vec(encoded.size());
    uint8_t *out = out_vec.data();

    // Test that the padding behavior of the deprecated API is preserved.
    int ret =
        EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
    if (ret < 0) {
      fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded);
      return false;
    }
    if (ret % 3 != 0) {
      fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
      return false;
    }
    size_t expected_len = strlen(t->decoded);
    if (expected_len % 3 != 0) {
      ret -= 3 - (expected_len % 3);
    }
    if (static_cast<size_t>(ret) != strlen(t->decoded) ||
        OPENSSL_memcmp(out, t->decoded, ret) != 0) {
      fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
              t->encoded, ret, (const char*)out, t->decoded);
      return false;
    }
  }

  return true;
}

static bool TestEncodeDecode() {
  for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
    const TestVector *t = &kTestVectors[test_num];

    EVP_ENCODE_CTX ctx;
    const size_t decoded_len = strlen(t->decoded);

    if (t->relation == canonical) {
      size_t max_encoded_len;
      if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
        fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num);
        return false;
      }

      // EVP_EncodeUpdate will output new lines every 64 bytes of output so we
      // need slightly more than |EVP_EncodedLength| returns. */
      max_encoded_len += (max_encoded_len + 63) >> 6;
      std::vector<uint8_t> out_vec(max_encoded_len);
      uint8_t *out = out_vec.data();

      EVP_EncodeInit(&ctx);

      int out_len;
      EVP_EncodeUpdate(&ctx, out, &out_len,
                       reinterpret_cast<const uint8_t *>(t->decoded),
                       decoded_len);
      size_t total = out_len;

      EVP_EncodeFinal(&ctx, out + total, &out_len);
      total += out_len;

      if (total != strlen(t->encoded) ||
          OPENSSL_memcmp(out, t->encoded, total) != 0) {
        fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
                test_num, out, static_cast<unsigned>(total));
        return false;
      }
    }

    std::vector<uint8_t> out_vec(strlen(t->encoded));
    uint8_t *out = out_vec.data();

    EVP_DecodeInit(&ctx);
    int out_len;
    size_t total = 0;
    int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
                               reinterpret_cast<const uint8_t *>(t->encoded),
                               strlen(t->encoded));
    if (ret != -1) {
      total = out_len;
      ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
      total += out_len;
    }

    switch (t->relation) {
      case canonical:
      case valid:
        if (ret == -1) {
          fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
          return false;
        }
        if (total != decoded_len ||
            OPENSSL_memcmp(out, t->decoded, decoded_len)) {
          fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
                  test_num);
          return false;
        }
        break;

      case invalid:
        if (ret != -1) {
          fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num);
          return false;
        }
        break;
    }
  }

  return true;
}

static bool TestDecodeUpdateStreaming() {
  for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
    const TestVector *t = &kTestVectors[test_num];
    if (t->relation == invalid) {
      continue;
    }

    const size_t encoded_len = strlen(t->encoded);

    std::vector<uint8_t> out(encoded_len);

    for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
      size_t out_len = 0;
      EVP_ENCODE_CTX ctx;
      EVP_DecodeInit(&ctx);

      for (size_t i = 0; i < encoded_len;) {
        size_t todo = encoded_len - i;
        if (todo > chunk_size) {
          todo = chunk_size;
        }

        int bytes_written;
        int ret = EVP_DecodeUpdate(
            &ctx, out.data() + out_len, &bytes_written,
            reinterpret_cast<const uint8_t *>(t->encoded + i), todo);
        i += todo;

        switch (ret) {
          case -1:
            fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num);
            return 0;
          case 0:
            out_len += bytes_written;
            if (i == encoded_len ||
                (i + 1 == encoded_len && t->encoded[i] == '\n') ||
                /* If there was an '-' in the input (which means “EOF”) then
                 * this loop will continue to test that |EVP_DecodeUpdate| will
                 * ignore the remainder of the input. */
                strchr(t->encoded, '-') != nullptr) {
              break;
            }

            fprintf(stderr,
                    "#%u: EVP_DecodeUpdate returned zero before end of "
                    "encoded data\n",
                    test_num);
            return 0;
          default:
            out_len += bytes_written;
        }
      }

      int bytes_written;
      int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
      if (ret == -1) {
        fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num);
        return 0;
      }
      out_len += bytes_written;

      if (out_len != strlen(t->decoded) ||
          OPENSSL_memcmp(out.data(), t->decoded, out_len) != 0) {
        fprintf(stderr, "#%u: incorrect output\n", test_num);
        return 0;
      }
    }
  }

  return true;
}

int main(void) {
  CRYPTO_library_init();

  if (!TestEncodeBlock() ||
      !TestDecodeBase64() ||
      !TestDecodeBlock() ||
      !TestDecodeUpdateStreaming() ||
      !TestEncodeDecode()) {
    return 1;
  }

  printf("PASS\n");
  return 0;
}
