blob: ed8fcf422e8098ebb272a76792d7019171534071 [file] [log] [blame]
// 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>
// |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.
namespace crypto {
class Cipher final {
public:
// Algorithm enumerates the supported secret key ciphers.
enum Algorithm {
kUninitialized = 0,
kAES256_XTS,
};
// Indicates whether the objects turns plaintext into ciphertext or vice versa.
enum Direction {
kUnset = 0,
kEncrypt,
kDecrypt,
};
Cipher();
~Cipher();
// 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 data using the given |key| and |iv|. The |tweakable| mask
// indicates which bits, if any, are used as an offset that can be set by |Tweak|. A value of
// zero means the IV cannot be adjusted.
zx_status_t InitEncrypt(Algorithm cipher, const Bytes& key, const Bytes& iv,
uint64_t tweakable = 0);
// Sets up the cipher to decrypt data using the given |key| and |iv|. The |tweakable| mask
// indicates which bits, if any, are used as an offset that can be set by |Tweak|. A value of
// zero means the IV cannot be adjusted.
zx_status_t InitDecrypt(Algorithm cipher, const Bytes& key, const Bytes& iv,
uint64_t tweakable = 0);
// Sets |out| to this object's direction. Returns |ZX_ERR_BAD_STATE| if it has not been
// configured.
zx_status_t GetDirection(Direction* out) const;
// Adjusts the "tweakable" bits of the IV to "seek" to a particular data |offset|. The |offset|
// must fall within the mask set in either |InitEncrypt| or |InitDecrypt|.
zx_status_t Tweak(uint64_t offset);
// Encrypts |len| bytes from |in| to |out|, based on the parameters set in
// |InitEncrypt|. Returns |ZX_ERR_BAD_STATE| if configured to decrypt and |ZX_ERR_INVALID_ARGS|
// if |len| is not a multiple of cipher blocks.
zx_status_t Encrypt(const uint8_t* in, size_t len, uint8_t* out);
// Decrypts |len| bytes from |in| to |out|, based on the parameters set in
// |InitDecrypt|. Returns |ZX_ERR_BAD_STATE| if configured to encrypt and |ZX_ERR_INVALID_ARGS|
// if |in_len| is not a multiple of cipher blocks.
zx_status_t Decrypt(const uint8_t* in, size_t len, uint8_t* out);
// Clears all state from this instance.
void Reset();
private:
DISALLOW_COPY_ASSIGN_AND_MOVE(Cipher);
// Sets up the cipher to encrypt or decrypt data using the given |key| and |iv| based on the
// given |direction|.
zx_status_t Init(Algorithm cipher, const Bytes& key, const Bytes& iv, uint64_t tweakable,
Direction Direction);
// Encrypts or decrypts |in_len| bytes from |in| to |out|, based on the parameters set in
// |Init|. Sets |actual| to number of bytes written to |out|.
zx_status_t Transform(const uint8_t* in, size_t in_len, uint8_t* out);
// 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_;
// Buffer used to hold the initial vector.
Bytes iv_;
// Cipher block size.
size_t block_size_;
// Bit mask of how much of the IV is reserved for an adjustable counter.
uint64_t tweakable_;
};
} // namespace crypto