// Copyright 2017 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.

#pragma once

#include <stddef.h>
#include <stdint.h>

#include <crypto/bytes.h>
#include <fbl/macros.h>
#include <zircon/types.h>
#include <crypto/secret.h>

// |crypto::Cipher| is used to encrypt and decrypt data.  Ciphers differ from AEADs in that they
// require block-aligned lengths and do not check data integrity.  This implementation can be used
// as either a stream cipher, or as a random access cipher if the cipher has a "tweaked codebook
// mode".  See the variants of |Init| and |Transform| for details.  A 64 bit nonce is used to seal
// plain texts, meaning a given key and IV can be used for at most 2^64 - 1 operations.
namespace crypto {

class Cipher final {
 public:
  // Algorithm enumerates the supported secret key ciphers.
  enum Algorithm {
    kUninitialized = 0,
    kAES256_XTS,  // A "tweaked cipher
  };

  // Indicates whether the objects turns plaintext into ciphertext or vice versa.
  enum Direction {
    kUnset = 0,
    kEncrypt,
    kDecrypt,
  };

  Cipher();
  ~Cipher();

  Direction direction() const { return direction_; }
  uint64_t alignment() const { return alignment_; }

  // Gets the number of bytes needed for the symmetric key used by the given |cipher|.
  static zx_status_t GetKeyLen(Algorithm cipher, size_t* out);

  // Gets the number of bytes needed for the initialization vector (IV) used by the given
  // |cipher|.
  static zx_status_t GetIVLen(Algorithm cipher, size_t* out);

  // Gets the cipher block size in bytes for  the given |cipher|.  Data passed to |Encrypt| or
  // |Decrypt| must be a multiple of this size.
  static zx_status_t GetBlockSize(Algorithm cipher, size_t* out);

  // Sets up the cipher to encrypt or decrypt data using the given |key| and |iv|,  based on the
  // given |direction|, either as:
  //   - A stream ciphers, using the first variant that omits the |alignment|.
  //   - As a random access cipher, using the second variant.  All offsets must be
  //   |alignment|-aligned, and |alignment| must be a power of 2.
  zx_status_t Init(Algorithm algo, Direction direction, const Secret& key, const Bytes& iv,
                   uint64_t alignment);

  // Sets up the cipher to encrypt data using the given |key| and |iv|, either as a stream cipher
  // or a random access cipher, as described above in |Init|.
  zx_status_t InitEncrypt(Algorithm algo, const Secret& key, const Bytes& iv) {
    return Init(algo, kEncrypt, key, iv, 0);
  }
  zx_status_t InitEncrypt(Algorithm algo, const Secret& key, const Bytes& iv, uint64_t alignment) {
    return Init(algo, kEncrypt, key, iv, alignment);
  }

  // Sets up the cipher to decrypt data using the given |key| and |iv|, either as a stream cipher
  // or a random access cipher, as described above in |Init|.
  zx_status_t InitDecrypt(Algorithm algo, const Secret& key, const Bytes& iv) {
    return Init(algo, kDecrypt, key, iv, 0);
  }
  zx_status_t InitDecrypt(Algorithm algo, const Secret& key, const Bytes& iv, uint64_t alignment) {
    return Init(algo, kDecrypt, key, iv, alignment);
  }

  // Encrypts or decrypts |length| bytes from |in| to |out|, based on the given |direction| and
  // the parameters set in |Init|:
  //  - Must have been configured with the same |direction|.
  //  - If |alignment| was non-zero, |offset| must be a multiple of it.
  // Finally, |length| must be a multiple of cipher blocks, and |out| must have room for |length|
  // bytes.  This method will fail if called 2^64 or more times with the same key and IV.
  zx_status_t Transform(const uint8_t* in, zx_off_t offset, size_t length, uint8_t* out,
                        Direction Direction);

  // Encrypts |len| bytes from |in| to |out|, as described above in |Transform|.
  zx_status_t Encrypt(const uint8_t* in, size_t length, uint8_t* out) {
    return Transform(in, 0, length, out, kEncrypt);
  }
  zx_status_t Encrypt(const uint8_t* in, zx_off_t offset, size_t length, uint8_t* out) {
    return Transform(in, offset, length, out, kEncrypt);
  }

  // Decrypts |len| bytes from |in| to |out|, as described above in |Transform|.
  zx_status_t Decrypt(const uint8_t* in, size_t length, uint8_t* out) {
    return Transform(in, 0, length, out, kDecrypt);
  }
  zx_status_t Decrypt(const uint8_t* in, zx_off_t offset, size_t length, uint8_t* out) {
    return Transform(in, offset, length, out, kDecrypt);
  }

  // Clears all state from this instance.
  void Reset();

 private:
  DISALLOW_COPY_ASSIGN_AND_MOVE(Cipher);

  // Opaque crypto implementation context.
  struct Context;

  // Opaque pointer to the crypto implementation context.
  fbl::unique_ptr<Context> ctx_;
  // Indicates which algorithm to use to transform data.
  Algorithm cipher_;
  // Indicates whether configured to encrypt or decrypt.
  Direction direction_;
  // Cipher block size.
  size_t block_size_;
  // Buffer holding initial vector.  The IV is expanded to be |zx_off_t|-aligned.
  fbl::unique_ptr<zx_off_t[]> iv_;
  // Original value of |iv_[0]|.  |Transform| will fail if |iv_[0]| wraps around to this value.
  zx_off_t iv0_;
  // If non-zero, indicates how many bytes to use a nonce for before incrementing.
  uint64_t alignment_;
};
}  // namespace crypto
