/* Copyright 2016 The Roughtime Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include <string>

#include <stdint.h>

#include <google/protobuf/stubs/logging.h>
#include <openssl/curve25519.h>

#include "client.h"

namespace roughtime {

std::string CreateRequest(const uint8_t nonce[kNonceLength]) {
  uint8_t query_bytes[kMinRequestSize];
  size_t query_len;

  Builder query(query_bytes, sizeof(query_bytes), 2);

  uint8_t* padding;

  static_assert(kTagNONC < kTagPAD, "Tags must be written in order");
  GOOGLE_CHECK(query.AddTagData(kTagNONC, nonce, kNonceLength) &&
               query.AddTag(&padding, kTagPAD, kPaddingLen) &&
               query.Finish(&query_len));
  GOOGLE_CHECK_EQ(query_len, sizeof(query_bytes));

  memset(padding, 0, kPaddingLen);

  return std::string(reinterpret_cast<char*>(query_bytes), query_len);
}

bool ParseResponse(uint64_t* out_time, uint32_t* out_radius,
                   std::string* out_error,
                   const uint8_t root_public_key[ED25519_PUBLIC_KEY_LEN],
                   const uint8_t* response_bytes, size_t response_len,
                   const uint8_t nonce[kNonceLength]) {
  *out_time = 0;
  *out_radius = 0;

  Parser response(response_bytes, response_len);
  if (!response.is_valid()) {
    *out_error = "structural error";
    return false;
  }

  const uint8_t* cert_bytes;
  size_t cert_len;
  if (!response.GetTag(&cert_bytes, &cert_len, kTagCERT)) {
    *out_error = "no certificate provided";
    return false;
  }

  Parser cert(cert_bytes, cert_len);
  if (!cert.is_valid()) {
    *out_error = "structural error in certificate";
    return false;
  }

  const uint8_t* signature;
  if (!cert.GetFixedLen(&signature, kTagSIG, ED25519_SIGNATURE_LEN)) {
    *out_error = "no signature in certificate";
    return false;
  }

  const uint8_t* delegation_bytes;
  size_t delegation_len;
  if (!cert.GetTag(&delegation_bytes, &delegation_len, kTagDELE)) {
    *out_error = "no delegation in certificate";
    return false;
  }

  std::string signed_message =
      std::string(kCertContextString, sizeof(kCertContextString)) +
      std::string(reinterpret_cast<const char*>(delegation_bytes),
                  delegation_len);

  if (!ED25519_verify(reinterpret_cast<const uint8_t*>(signed_message.data()),
                      signed_message.size(), signature, root_public_key)) {
    *out_error = "bad signature in certificate";
    return false;
  }

  const uint8_t* delegated_public_key;
  uint64_t min_time, max_time;
  Parser delegation(delegation_bytes, delegation_len);
  if (!delegation.is_valid() ||
      !delegation.Get(&min_time, kTagMINT) ||
      !delegation.Get(&max_time, kTagMAXT) ||
      !delegation.GetFixedLen(&delegated_public_key, kTagPUBK,
                              ED25519_PUBLIC_KEY_LEN)) {
    *out_error = "delegation missing required value";
    return false;
  }

  if (max_time < min_time) {
    *out_error = "invalid delegation validity period";
    return false;
  }

  const uint8_t* signed_response_bytes;
  size_t signed_response_len;
  if (!response.GetTag(&signed_response_bytes, &signed_response_len,
                       kTagSREP)) {
    *out_error = "no signed response";
    return false;
  }

  const uint8_t* response_signature;
  if (!response.GetFixedLen(&response_signature, kTagSIG,
                            ED25519_SIGNATURE_LEN)) {
    *out_error = "no signature in response";
    return false;
  }

  signed_message =
      std::string(kContextString, sizeof(kContextString)) +
      std::string(reinterpret_cast<const char*>(signed_response_bytes),
                  signed_response_len);

  if (!ED25519_verify(reinterpret_cast<const uint8_t*>(signed_message.data()),
                      signed_message.size(), response_signature,
                      delegated_public_key)) {
    *out_error = "bad signature in response";
    return false;
  }

  Parser signed_response(signed_response_bytes, signed_response_len);
  if (!signed_response.is_valid()) {
    *out_error = "invalid signed response in response";
    return false;
  }

  const uint8_t* root;
  uint64_t timestamp;
  uint32_t radius;
  if (!signed_response.GetFixedLen(&root, kTagROOT, kNonceLength) ||
      !signed_response.Get(&timestamp, kTagMIDP) ||
      !signed_response.Get(&radius, kTagRADI)) {
    *out_error = "signed response missing required values";
    return false;
  }

  if (timestamp < min_time || max_time < timestamp) {
    *out_error = "timestamp out of range for delegation";
    return false;
  }

  const uint8_t* path;
  size_t path_len;
  uint32_t tree_index;
  if (!response.Get(&tree_index, kTagINDX) ||
      !response.GetTag(&path, &path_len, kTagPATH)) {
    *out_error = "response missing required values";
    return false;
  }

  uint8_t hash[kNonceLength];
  HashLeaf(hash, nonce);

  if (path_len % kNonceLength != 0) {
    *out_error = "tree path is not a multiple of the hash size";
    return false;
  }

  for (size_t i = 0; i < path_len; i += kNonceLength) {
    const bool path_element_is_right = tree_index & 1;
    if (path_element_is_right) {
      HashNode(hash, hash, path + i);
    } else {
      HashNode(hash, path + i, hash);
    }
    tree_index /= 2;
  }

  if (memcmp(root, hash, kNonceLength) != 0) {
    *out_error = "calculated tree root doesn't match signed root";
    return false;
  }

  *out_time = timestamp;
  *out_radius = radius;

  return true;
}

}  // namespace roughtime
