/* Copyright (c) 2016, 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 <string>

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

#include <openssl/curve25519.h>


namespace bssl {

struct SPAKE2Run {
  bool Run() {
    ScopedSPAKE2_CTX alice(SPAKE2_CTX_new(
        spake2_role_alice,
        reinterpret_cast<const uint8_t *>(alice_names.first.data()),
        alice_names.first.size(),
        reinterpret_cast<const uint8_t *>(alice_names.second.data()),
        alice_names.second.size()));
    ScopedSPAKE2_CTX bob(SPAKE2_CTX_new(
        spake2_role_bob,
        reinterpret_cast<const uint8_t *>(bob_names.first.data()),
        bob_names.first.size(),
        reinterpret_cast<const uint8_t *>(bob_names.second.data()),
        bob_names.second.size()));

    if (!alice || !bob) {
      return false;
    }

    uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
    uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE];
    size_t alice_msg_len, bob_msg_len;

    if (!SPAKE2_generate_msg(
            alice.get(), alice_msg, &alice_msg_len, sizeof(alice_msg),
            reinterpret_cast<const uint8_t *>(alice_password.data()),
            alice_password.size()) ||
        !SPAKE2_generate_msg(
            bob.get(), bob_msg, &bob_msg_len, sizeof(bob_msg),
            reinterpret_cast<const uint8_t *>(bob_password.data()),
            bob_password.size())) {
      return false;
    }

    if (alice_corrupt_msg_bit >= 0 &&
        static_cast<size_t>(alice_corrupt_msg_bit) < 8 * alice_msg_len) {
      alice_msg[alice_corrupt_msg_bit/8] ^= 1 << (alice_corrupt_msg_bit & 7);
    }

    uint8_t alice_key[64], bob_key[64];
    size_t alice_key_len, bob_key_len;

    if (!SPAKE2_process_msg(alice.get(), alice_key, &alice_key_len,
                            sizeof(alice_key), bob_msg, bob_msg_len) ||
        !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, sizeof(bob_key),
                            alice_msg, alice_msg_len)) {
      return false;
    }

    key_matches_ = (alice_key_len == bob_key_len &&
                    memcmp(alice_key, bob_key, alice_key_len) == 0);

    return true;
  }

  bool key_matches() const {
    return key_matches_;
  }

  std::string alice_password = "password";
  std::string bob_password = "password";
  std::pair<std::string, std::string> alice_names = {"alice", "bob"};
  std::pair<std::string, std::string> bob_names = {"bob", "alice"};
  int alice_corrupt_msg_bit = -1;

 private:
  bool key_matches_ = false;
};

static bool TestSPAKE2() {
  for (unsigned i = 0; i < 20; i++) {
    SPAKE2Run spake2;
    if (!spake2.Run()) {
      fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
      return false;
    }

    if (!spake2.key_matches()) {
      fprintf(stderr, "Key didn't match for equal passwords.\n");
      return false;
    }
  }

  return true;
}

static bool TestWrongPassword() {
  SPAKE2Run spake2;
  spake2.bob_password = "wrong password";
  if (!spake2.Run()) {
    fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
    return false;
  }

  if (spake2.key_matches()) {
    fprintf(stderr, "Key matched for unequal passwords.\n");
    return false;
  }

  return true;
}

static bool TestWrongNames() {
  SPAKE2Run spake2;
  spake2.alice_names.second = "charlie";
  spake2.bob_names.second = "charlie";
  if (!spake2.Run()) {
    fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
    return false;
  }

  if (spake2.key_matches()) {
    fprintf(stderr, "Key matched for unequal names.\n");
    return false;
  }

  return true;
}

static bool TestCorruptMessages() {
  for (int i = 0; i < 8 * SPAKE2_MAX_MSG_SIZE; i++) {
    SPAKE2Run spake2;
    spake2.alice_corrupt_msg_bit = i;
    if (spake2.Run() && spake2.key_matches()) {
      fprintf(stderr, "Passed after corrupting Alice's message, bit %d\n", i);
      return false;
    }
  }

  return true;
}

}  // namespace bssl

/* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */

int main(int argc, char **argv) {
  if (!bssl::TestSPAKE2() ||
      !bssl::TestWrongPassword() ||
      !bssl::TestWrongNames() ||
      !bssl::TestCorruptMessages()) {
    return 1;
  }

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