// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#ifndef SRC_LIB_DIGEST_HASH_LIST_H_
#define SRC_LIB_DIGEST_HASH_LIST_H_

#include <stddef.h>
#include <stdint.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include "src/lib/digest/digest.h"
#include "src/lib/digest/node-digest.h"

namespace digest {
namespace internal {

// |digest::internal::HashListBase| contains common hash list code. Callers MUST NOT use this class
// directly. See |digest::HashListCreator| and |digest::HashListVerifier| below.
class HashListBase {
 public:
  HashListBase() = default;
  virtual ~HashListBase() = default;
  DISALLOW_COPY_ASSIGN_AND_MOVE(HashListBase);

  size_t data_off() const { return data_off_; }
  size_t data_len() const { return data_len_; }
  size_t list_off() const { return list_off_; }
  size_t list_len() const { return list_len_; }

  // Gets or sets relevant NodeDigest fields.
  uint64_t GetNodeId() const { return node_digest_.id(); }
  size_t GetNodeSize() const { return node_digest_.node_size(); }
  size_t GetDigestSize() const { return node_digest_.len(); }
  void SetNodeId(uint64_t id) { node_digest_.set_id(id); }
  zx_status_t SetNodeSize(size_t node_size) { return node_digest_.SetNodeSize(node_size); }

  // Returns true if |data_off| is aligned to a node boundary.
  bool IsAligned(size_t data_off) const { return node_digest_.IsAligned(data_off); }

  // Modifies |data_off| and |buf_len| to be aligned to the minimum number of nodes that covered
  // their original range.
  zx_status_t Align(size_t *data_off, size_t *buf_len) const;

  // Sets the length of data this hash list will represent. The maxium possible size is
  // |SIZE_MAX - NodeSize + 1|, i.e. the maximum node-aligned value of type |size_t|.
  zx_status_t SetDataLength(size_t data_len);

  // Sets whether the hash list should pad the length of the data it's given up to the next multiple
  // of the node size.
  void SetPadDataToNodeSize(bool pad_data_to_node_size) {
    pad_data_to_node_size_ = pad_data_to_node_size;
  }

  // Returns the corresponding offset in the hash list for an offset in the data. This method
  // does not check if |data_off| is within bounds.
  size_t GetListOffset(size_t data_off) const;

  // Returns the minimum size needed to hold a hash list for the given |data_len|. Note that this
  // differs from |list_len()| in that it returns what's needed, whereas the latter returns what
  // the list length currently is.
  size_t GetListLength() const;

 protected:
  void set_list_len(size_t list_len) { list_len_ = list_len; }

  // Checks range given by |data_off| and |buf_len| is valid.
  virtual bool IsValidRange(size_t data_off, size_t buf_len);

  // Handle the |buf_len| bytes from |buf|, corresponding to the data sequence starting at
  // |data_off|.
  zx_status_t ProcessData(const uint8_t *buf, size_t buf_len, size_t data_off);

  // Process the next digest in the hash list, e.g. write a digest when creating, or compare when
  // verifying. The no-argument version simply invokes the second version with the current digest.
  // The second version is implemented in derived classes.
  void HandleOne();
  virtual void HandleOne(const Digest &digest) {}

 private:
  zx_status_t Check(size_t off, size_t len, size_t max, size_t *out = nullptr) const;

  // Digest object used to create hashes to store or check.
  NodeDigest node_digest_;

  // Offset and length of data represented by the hash list.
  size_t data_off_ = 0;
  size_t data_len_ = 0;

  // Contents, offset, and length of the hash list.
  size_t list_off_ = 0;
  size_t list_len_ = 0;

  // Whether the hash list should pad the length of the data it's given up to the next multiple of
  // the node size.
  bool pad_data_to_node_size_ = false;
};

// |digest::internal::HashList| contains code templated on the list type. Callers MUST NOT use this
// class directly. See |digest::HashListCreator| and |digest::HashListVerifier| below.
template <typename T>
class HashList : public HashListBase {
 public:
  static_assert(sizeof(T) == sizeof(uint8_t), "Do not invoke HashList directly.");

  T *list() const { return list_; }

  // Registers |list| as a hash list for |data_len_| bytes of data.
  zx_status_t SetList(T *list, size_t list_len);

 private:
  T *list_ = nullptr;
};

}  // namespace internal

// |digest::HashListCreator| creates hash lists for data.
// Example (without error checking):
//   HashListCreator creator;
//   creator.SetDataLength(data_len);
//   size_t list_len = creator.GetListLength();
//   uint8_t *list = malloc(list_len); // or other allocation routine
//   creator.SetList(list, list_len);
//   creator.Append(&data[0], partial_len1);
//   creator.Append(&data[partial_len1], partial_len2);
class HashListCreator : public internal::HashList<uint8_t> {
 public:
  // Reads |buf_len| bytes of data from |buf| and appends digests to the hash |list|.
  zx_status_t Append(const void *buf, size_t buf_len);

 protected:
  // Writes a single calculated digest to the appropriate position in the list.
  void HandleOne(const Digest &digest) override;
};

// |digest::HashListVerifier| verifies data against a hash list.
// Example (without error checking):
//   HashListVerifier verifier;
//   verifier.SetDataLength(data_len);
//   verifier.SetList(list, list_len);
//   verifier.Align(&data_off, &partial_len);
//   return verifier.Verify(&data[data_off], partial_len) == ZX_OK;
class HashListVerifier : public internal::HashList<const uint8_t> {
 public:
  // Reads |buf_len| bytes of data from |buf|, calculates digests for each node of data, and
  // compares them to the digests stored in the hash list. |data_off| must be node-aligned.
  // |buf_len| must be node-aligned, or reach the end of the data. See also |Align|.
  zx_status_t Verify(const void *buf, size_t buf_len, size_t data_off);

 protected:
  // Verification ranges must start on a node boundary, and end on a node boundary or the end of the
  // data.
  bool IsValidRange(size_t data_off, size_t buf_len) override;

  // Compares a single calculated digest to the corresponding one in the list.
  void HandleOne(const Digest &digest) override;

 private:
  // Used to store the verification result. The verification logic intentionally does NOT short
  // circuit; we want the hash checks to be as close to constant time as possible.
  bool verified_ = false;
};

// Convenience method for calculating the minimum size needed to hold a hash list for the given
// |data_size|.
//
// Panics if |node_size| does not satisfy |NodeDigest::IsValidNodeSize|.
size_t CalculateHashListSize(size_t data_size, size_t node_size);

}  // namespace digest

#endif  // SRC_LIB_DIGEST_HASH_LIST_H_
