/* 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. */

#ifndef SECURITY_ROUGHTIME_SERVER_H_
#define SECURITY_ROUGHTIME_SERVER_H_

#include <memory>
#include <utility>

#include <google/protobuf/stubs/macros.h>

#include "protocol.h"
#include "time_source.h"

namespace roughtime {

// kToBeSignedCertSize is the size of the signed portion (DELE) of a
// certificate.  Its tags are (PUBK, MINT, MAXT).
constexpr size_t kToBeSignedCertSize = MessageHeaderLen(3) +
                                       ED25519_PUBLIC_KEY_LEN + kTimestampSize +
                                       kTimestampSize;

// kCertSize is the size of the entire certificate.  Its tags are (DELE, SIG).
constexpr size_t kCertSize =
    MessageHeaderLen(2) + ED25519_SIGNATURE_LEN + kToBeSignedCertSize;

// CreateCertificate signs the supplied |public_key| using |root_private_key|,
// and sets |out_cert| to a certificate containing the public key, the
// signature, and the supplied validity interval.  Returns true if successful,
// otherwise false.
// TODO(mab): Find better home for this, likely in an offline tool.
bool CreateCertificate(uint8_t out_cert[kCertSize],
                       const uint8_t root_private_key[ED25519_PRIVATE_KEY_LEN],
                       rough_time_t start_time, rough_time_t end_time,
                       const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]);

// Identity is a server's private key and certificate.  (The certificate is the
// server's public key signed by an offline private master key.)
struct Identity {
  uint8_t private_key[ED25519_PRIVATE_KEY_LEN];
  uint8_t certificate[kCertSize];
};

// kBatchSizeLog2 is one less than the number of levels in the Merkle tree of
// client nonces.  The response packet must have room for this many hashes.
// This value was taken because it's too easy to saturate batches of size 32 in
// load testing so 64 seems like a reasonable number for now. We may revisit
// this if the non-crypto parts of processing become less expensive.
constexpr size_t kBatchSizeLog2 = 6;

// kBatchSize is the most requests we'll process at a time, a.k.a. the number of
// leaves in the Merkle tree.
constexpr size_t kBatchSize = 1 << kBatchSizeLog2;

// Tree encapsulates the Merkle tree of client nonces.  The tree is too large
// (2**13 bytes) to be sent to each client, so each client is sent the part of
// the tree necessary to verify the inclusion of its nonce.
class Tree {
 public:
  Tree() {}
  Tree(const Tree&) = delete;
  Tree& operator=(const Tree&) = delete;

  // AddLeaf adds a new client nonce at the specified index.
  void AddLeaf(size_t index, const uint8_t nonce[kNonceLength]) {
    HashLeaf(tree_[0][index], nonce);
  }

  // Build constructs the Merkle tree.  The existing |num_leaves| leaf hashes in
  // levels_[0] are left alone, and the tree is built by (possibly adding a
  // dummy leaf node and) creating levels 1 and higher.
  //
  // If |num_leaves| is 1, this is a no-op.  In that case, the root is the same
  // node as the one leaf.
  void Build(size_t num_leaves);

  // GetPathLength returns the number of nodes necessary to represent a path to
  // the root.  This may be zero.
  size_t GetPathLength() { return levels_ - 1; }

  // GetPath sets |*out_path| to the data needed to verify inclusion in the root
  // hash of the leaf at |index|.  The path consists of one node for each
  // sub-root level.  So, for example, the first element is the leaf that is the
  // sibling of the leaf at |index|.
  //
  // The data are intended for consumption by a client that knows the leaf at
  // |index|, because it is that client's nonce.
  void GetPath(uint8_t* out_path, size_t index);

  // GetRoot returns a pointer to the root hash, which is |kNonceLength| bytes
  // long.
  const uint8_t* GetRoot() { return tree_[levels_ - 1][0]; }

 private:
  // tree_ is a Merkle tree.  The first index is the level of the tree, with
  // leaves at level 0.
  uint8_t tree_[kBatchSizeLog2 + 1][kBatchSize][kNonceLength];

  // Level is the number of levels in the tree, including the root.  Hence,
  // after calling |Build|, the root lives at |tree_[levels_-1][0]|.
  size_t levels_;
};

constexpr size_t kMaxRecvPacketSize = kMinRequestSize;

constexpr size_t kToBeSignedSize =
    MessageHeaderLen(3) + kTimestampSize + kRadiusSize + kNonceLength;

// kMaxResponseSize is the size of the largest possible server response.
constexpr size_t kMaxResponseSize =
    MessageHeaderLen(5) + kCertSize + kToBeSignedSize + ED25519_SIGNATURE_LEN +
    (kBatchSizeLog2 * kNonceLength) + sizeof(uint32_t) /* index */;

class Server {
 public:
  Server() = delete;
  Server(const Server&) = delete;
  Server& operator=(const Server&) = delete;

  Server(std::unique_ptr<Identity> identity,
         std::unique_ptr<TimeSource> time_source);

  // AddRequest decodes |packet|.  If the packet is valid, it is added to
  // |tree_| and true is returned.  Otherwise, false is returned.
  bool AddRequest(const uint8_t* packet, size_t len);

  // Sign creates a signed response (Merkle tree root and timestamp) and a
  // signature.
  bool Sign();

  // MakeResponse creates a response for the |index|'th leaf node of the Merkle
  // tree, where the indices correspond to successful calls to |AddRequest|.
  bool MakeResponse(uint8_t* out_response, size_t* out_len, uint32_t index);

  void Reset() { num_leaves_ = 0; }

 private:
  std::unique_ptr<TimeSource> time_source_;

  std::unique_ptr<Identity> identity_;

  Tree tree_;
  // num_leaves is the number of leaf nodes inserted
  size_t num_leaves_;

  // to_be_signed_with_context_ is the signed portion of the server's response,
  // prefixed by |kContextString|.
  uint8_t to_be_signed_with_context_[kToBeSignedSize + sizeof(kContextString)];

  // to_be_signed_ points |sizeof(kContextStringBytes)| into
  // |to_be_signed_with_context_|, for convenience.  It contains tags (ROOT,
  // TIME).
  uint8_t* const to_be_signed_;

  // Signature is the ED25519 signature over |to_be_signed_with_context_|.
  uint8_t signature_[ED25519_SIGNATURE_LEN];
};

// BrokenReplyGenerator is an interface for generating replies that are broken
// in a variety of ways. This is used to ensure that clients correctly handle
// various corner cases.
class BrokenReplyGenerator {
 public:
  virtual ~BrokenReplyGenerator();

  // probability_1024 returns the probability, in parts-per-1024, that this
  // generator should be used for a given request.
  uint16_t probability_1024() const;
  void set_probability_1024(uint16_t probabilty);

  // Process takes a valid request in |request| and the standard response in
  // |normal_response|. If it wishes to substitute an alternative reply then it
  // may write up to |max_out_len| bytes to |out|, set |*out_len| to the number
  // of bytes written and return true. Otherwise it must return false.
  virtual bool Process(uint8_t* out, size_t* out_len, size_t max_out_len,
                       const uint8_t* normal_response,
                       size_t normal_response_len, const uint8_t* request,
                       size_t request_len) = 0;

 protected:
  uint16_t probability_1024_ = 0;
};

}  // namespace roughtime

#endif  // SECURITY_ROUGHTIME_SERVER_H_
