blob: 5a7432b541d3844c73e16a2b89f04f124ee84950 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_AES_H_
#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_AES_H_
/**
* @file
* @brief AES operations for the OpenTitan cryptography library.
*/
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* Enum to denote the AES-GCM tag length.
*
* Values are hardened.
*/
typedef enum aead_gcm_tag_len {
// Tag length 128 bits.
kAeadGcmTagLen128 = 0xb9ab,
// Tag length 120 bits.
kAeadGcmTagLen120 = 0xae53,
// Tag length 112 bits.
kAeadGcmTagLen112 = 0x175d,
// Tag length 104 bits.
kAeadGcmTagLen104 = 0x68fc,
// Tag length 96 bits.
kAeadGcmTagLen96 = 0x7686,
// Tag length 64 bits.
kAeadGcmTagLen64 = 0xc6a9,
// Tag length 32 bits.
kAeadGcmTagLen32 = 0x4b37,
} aead_gcm_tag_len_t;
/**
* Enum to define AES mode of operation.
*
* Values are hardened.
*/
typedef enum block_cipher_mode {
// AES ECB mode (electronic codebook mode).
kBlockCipherModeEcb = 0x7cae,
// AES CBC mode (cipher block chaining mode).
kBlockCipherModeCbc = 0x9736,
// AES CFB mode (cipher feedback mode).
kBlockCipherModeCfb = 0xe378,
// AES OFB mode (output feedback mode).
kBlockCipherModeOfb = 0x9cdd,
// AES CTR mode (counter mode).
kBlockCipherModeCtr = 0x4a1f,
} block_cipher_mode_t;
/**
* Enum to define AES operation to be performed.
*
* Values are hardened.
*/
typedef enum aes_operation {
// AES operation mode encrypt.
kAesOperationEncrypt = 0xdea9,
// AES operation mode decrypt.
kAesOperationDecrypt = 0x5d5a,
} aes_operation_t;
/**
* Enum to define padding scheme for AES data.
*
* Values are hardened.
*/
typedef enum aes_padding {
// Pads with value same as the number of padding bytes.
kAesPaddingPkcs7 = 0xce99,
// Pads with 0x80 (10000000), followed by zero bytes.
kAesPaddingIso9797M2 = 0xb377,
// Pads with 0x00 bytes.
kAesPaddingIso9797M1 = 0x49eb,
// Pads with random bytes, last byte is no. of padded bytes.
kAesPaddingRandom = 0x746c,
// Pads with 0x00 bytes, last byte is no. of padded bytes.
kAesPaddingX923 = 0xed32,
// Add no padding.
kAesPaddingNull = 0x259f,
} aes_padding_t;
/**
 * Context for GCM GHASH operation.
 *
 * Representation is internal to the hmac implementation; initialize
 * with #otcrypto_gcm_ghash_init.
 */
typedef struct gcm_ghash_context gcm_ghash_context_t;
/**
* Generates a new AES key.
*
* The caller should allocate and partially populate the blinded
* key struct, including populating the key configuration and
* allocating space for the keyblob. The caller should indicate
* the length of the allocated keyblob; this function will
* return an error if the keyblob length does not match
* expectations. For hardware-backed keys, the keyblob length is 0
* and the keyblob pointer may be `NULL`. For non-hardware-backed keys,
* the keyblob should be twice the length of the key. The value in
* the `checksum` field of the blinded key struct will be populated
* by the key generation function.
*
* @param[out] key Destination blinded key struct.
* @return The result of the cipher operation.
*/
crypto_status_t otcrypto_aes_keygen(crypto_blinded_key_t *key);
/**
* Performs the AES operation.
*
* The input data in the `cipher_input` is first padded using the
* `aes_padding` scheme and the output is copied to `cipher_output`.
*
* The caller should allocate space for the `cipher_output` buffer,
* (same length as input, rounded up to the next full block), and
* set the length of expected output in the `len` field of the
* output. If the user-set length and the output length do not
* match, an error message will be returned.
*
* @param key Pointer to the blinded key struct with key shares.
* @param iv Initialization vector, used for CBC, CFB, OFB, CTR modes.
* @param aes_mode Required AES mode of operation.
* @param aes_operation Required AES operation (encrypt or decrypt).
* @param cipher_input Input data to be ciphered.
* @param aes_padding Padding scheme to be used for the data.
* @param[out] cipher_output Output data after cipher operation.
* @return The result of the cipher operation.
*/
crypto_status_t otcrypto_aes(const crypto_blinded_key_t *key,
crypto_uint8_buf_t iv,
block_cipher_mode_t aes_mode,
aes_operation_t aes_operation,
crypto_const_uint8_buf_t cipher_input,
aes_padding_t aes_padding,
crypto_uint8_buf_t *cipher_output);
/**
* Performs the AES-GCM authenticated encryption operation.
*
* This function encrypts the input `plaintext` to produce an
* output `ciphertext`. Together it generates an authentication
* tag `auth_tag` on the ciphered data and any non-confidential
* additional authenticated data `aad`.
*
* The caller should allocate space for the `ciphertext` buffer,
* (same length as input), `auth_tag` buffer (same as tag_len), and
* set the length of expected outputs in the `len` field of
* `ciphertext` and `auth_tag`. If the user-set length and the output
* length does not match, an error message will be returned.
*
* @param key Pointer to the blinded gcm-key struct.
* @param plaintext Input data to be encrypted and authenticated.
* @param iv Initialization vector for the encryption function.
* @param aad Additional authenticated data.
* @param tag_len Length of authentication tag to be generated.
* @param[out] ciphertext Encrypted output data, same length as input data.
* @param[out] auth_tag Generated authentication tag.
* @return Result of the authenticated encryption.
* operation
*/
crypto_status_t otcrypto_aes_encrypt_gcm(
const crypto_blinded_key_t *key, crypto_const_uint8_buf_t plaintext,
crypto_uint8_buf_t iv, crypto_uint8_buf_t aad, aead_gcm_tag_len_t tag_len,
crypto_uint8_buf_t *ciphertext, crypto_uint8_buf_t *auth_tag);
/**
* Performs the AES-GCM authenticated decryption operation.
*
* This function first verifies if the authentication tag `auth_tag`
* matches the internally generated tag. Upon verification, the
* function decrypts the input `ciphertext` to get a `plaintext data.
*
* The caller should allocate space for the `plaintext` buffer,
* (same length as ciphertext), and set the length of expected output
* in the `len` field of `plaintext`. If the user-set length and the
* output length does not match, an error message will be returned.
*
* @param key Pointer to the blinded gcm-key struct.
* @param ciphertext Input data to be decrypted.
* @param iv Initialization vector for the decryption function.
* @param aad Additional authenticated data.
* @param auth_tag Authentication tag to be verified.
* @param[out] plaintext Decrypted plaintext data, same len as input data.
* @return Result of the authenticated decryption.
* operation
*/
crypto_status_t otcrypto_aes_decrypt_gcm(const crypto_blinded_key_t *key,
crypto_const_uint8_buf_t ciphertext,
crypto_uint8_buf_t iv,
crypto_uint8_buf_t aad,
crypto_uint8_buf_t auth_tag,
crypto_uint8_buf_t *plaintext);
/**
* Internal GHASH operation of Galois Counter Mode (GCM).
*
* GHASH is an operation internal to GCM. It can be used to create
* custom implementations that do not adhere to the AES-GCM encryption
* and decryption API provided here. However, custom GCM constructs
* can be dangerous; for most use cases, prefer the provided
* encryption and decryption operations.
*
* This function initializes the GHASH context and must be called
* to create a context object.
*
* @param hash_subkey Hash subkey (H), 16 bytes.
* @param[out] ctx Output GHASH context object, caller-allocated.
* @return Result of the operation.
*/
crypto_status_t otcrypto_gcm_ghash_init(const crypto_blinded_key_t *hash_subkey,
gcm_ghash_context_t *ctx);
/**
* Internal GHASH operation of Galois Counter Mode (GCM).
*
* GHASH is an operation internal to GCM. It can be used to create
* custom implementations that do not adhere to the AES-GCM encryption
* and decryption API provided here. However, custom GCM constructs
* can be dangerous; for most use cases, prefer the provided
* encryption and decryption operations.
*
* This operation adds the input buffer to the message that will
* be hashed and updates the GHASH context. If the input length is
* not a multiple of 128 bits, it will be right-padded with zeros.
* The input length must not be zero.
*
* @param ctx GHASH context object.
* @param input Input buffer.
* @return Result of the operation.
*/
crypto_status_t otcrypto_gcm_ghash_update(gcm_ghash_context_t *ctx,
crypto_const_uint8_buf_t input);
/**
* Internal GHASH operation of Galois Counter Mode (GCM).
*
* GHASH is an operation internal to GCM. It can be used to create
* custom implementations that do not adhere to the AES-GCM encryption
* and decryption API provided here. However, custom GCM constructs
* can be dangerous; for most use cases, prefer the provided
* encryption and decryption operations.
*
* This operation signals that all input has been provided and
* extracts the digest from the GHASH context. The digest buffer must
* be 16 bytes.
*
* @param ctx GHASH context object.
* @param[out] digest Output buffer for digest, 16 bytes.
* @return Result of the operation.
*/
crypto_status_t otcrypto_gcm_ghash_final(gcm_ghash_context_t *ctx,
crypto_uint8_buf_t digest);
/**
* Internal AES-GCTR operation of AES Galois Counter Mode (AES-GCM).
*
* GCTR is an operation internal to AES-GCM and is based on AES-CTR.
* It can be used to create custom implementations that do not adhere
* to the AES-GCM encryption and decryption API provided here.
* However, custom GCM constructs can be dangerous; for most use
* cases, prefer the provided encryption and decryption operations.
*
* The caller-allocated output buffer must be the same length as the
* input.
*
* @param key AES key for the GCTR operation.
* @param input Input buffer.
* @param[out] output Output buffer (same length as input).
* @return Result of the operation.
*/
crypto_status_t otcrypto_aes_gcm_gctr(const crypto_blinded_key_t *key,
crypto_const_uint8_buf_t input,
crypto_uint8_buf_t output);
/**
* Performs the AES-KWP authenticated encryption operation.
*
* This encrypt function takes an input key `key_to_wrap` and using
* the encryption key `key_kek` outputs a wrapped key `wrapped_key`.
*
* The caller should allocate space for the `wrapped_key` buffer,
* (same len as `key_to_wrap`), and set the length of expected output
* in the `len` field of `wrapped_key`. If the user-set length and the
* output length does not match, an error message will be returned.
*
* @param key_to_wrap Pointer to the blinded key to be wrapped.
* @param key_kek Input Pointer to the blinded encryption key.
* @param[out] wrapped_key Pointer to the output wrapped key.
* @return Result of the aes-kwp encrypt operation.
*/
crypto_status_t otcrypto_aes_kwp_encrypt(
const crypto_blinded_key_t *key_to_wrap,
const crypto_blinded_key_t *key_kek, crypto_uint8_buf_t *wrapped_key);
/**
* Performs the AES-KWP authenticated decryption operation.
*
* This decrypt function takes a wrapped key `wrapped_key` and using
* encryption key `key_kek` outputs an unwrapped key `unwrapped_key`.
*
* @param wrapped_key Pointer to the input wrapped key.
* @param key_kek Input Pointer to the blinded encryption key.
* @param[out] unwrapped_key Pointer to the output unwrapped key struct.
* @return Result of the aes-kwp decrypt operation.
*/
crypto_status_t otcrypto_aes_kwp_decrypt(crypto_const_uint8_buf_t wrapped_key,
const crypto_blinded_key_t *key_kek,
crypto_blinded_key_t *unwrapped_key);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_AES_H_