| // 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_DRIVERS_AES_H_ |
| #define OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_AES_H_ |
| |
| #include "sw/device/lib/base/hardened.h" |
| #include "sw/device/lib/base/hardened_status.h" |
| #include "sw/device/lib/base/macros.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| enum { |
| /** Number of bits in an AES cipher block. */ |
| kAesBlockNumBits = 128, |
| /** Number of bytes in an AES cipher block. */ |
| kAesBlockNumBytes = kAesBlockNumBits / 8, |
| /** Number of words in an AES cipher block. */ |
| kAesBlockNumWords = kAesBlockNumBytes / sizeof(uint32_t), |
| }; |
| |
| /** |
| * An AES block, which may represent plaintext or ciphertext. |
| */ |
| typedef struct aes_block { |
| uint32_t data[kAesBlockNumWords]; |
| } aes_block_t; |
| |
| /** |
| * A cipher mode supported natively by the AES hardware. |
| */ |
| typedef enum aes_cipher_mode { |
| kAesCipherModeEcb = 1, |
| kAesCipherModeCbc = 2, |
| kAesCipherModeCfb = 4, |
| kAesCipherModeOfb = 8, |
| kAesCipherModeCtr = 16, |
| } aes_cipher_mode_t; |
| |
| /** |
| * A key length supported by the AES hardware. |
| * |
| * The encoded values are used as identifiers to configure the hardware and |
| * don't represent the key length in any specific format. |
| */ |
| typedef enum aes_key_len { |
| kAesKeyLen128 = 1, |
| kAesKeyLen192 = 2, |
| kAesKeyLen256 = 4, |
| } aes_key_len_t; |
| |
| /** |
| * Represents an AES key. |
| * |
| * The key may be provided by software as two shares, or it may be a sideloaded |
| * key that is produced by the keymgr and not visible to software. |
| */ |
| typedef struct aes_key { |
| /** |
| * Block cipher mode for which the key is intended. |
| */ |
| aes_cipher_mode_t mode; |
| |
| /** |
| * Whether the key is sideloaded. |
| */ |
| hardened_bool_t sideload; |
| |
| /** |
| * The length of the key. |
| */ |
| aes_key_len_t key_len; |
| |
| /** |
| * The key, split into two shares. The actual key will be formed by |
| * XORing both keys together. |
| * |
| * Neither entry may be null. If a non-shared key is desired, one of |
| * the two pointers should be pointed to an array of zero-valued words |
| * of sufficient length. |
| */ |
| const uint32_t *key_shares[2]; |
| } aes_key_t; |
| |
| /** |
| * Prepares the AES hardware to perform an encryption operation. |
| * |
| * If `key.sideload` is true, then this routine does not load the key; the |
| * caller must separately call keymgr to write the key into the AES block before |
| * calling `aes_update`. |
| * |
| * If the selected mode requires an IV, then `iv` must not be null. Otherwise |
| * (e.g. for ECB mode), `iv` is ignored and may be null. |
| * |
| * @param key Encryption key. |
| * @param iv IV to use for non-ECB modes, 128 bits. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| status_t aes_encrypt_begin(const aes_key_t key, const aes_block_t *iv); |
| |
| /** |
| * Prepares the AES hardware to perform a decryption operation. |
| * |
| * If `key.sideload` is true, then this routine does not load the key; the |
| * caller must separately call keymgr to write the key into the AES block before |
| * calling `aes_update`. |
| * |
| * If the selected mode requires an IV, then `iv` must not be null. Otherwise |
| * (e.g. for ECB mode), `iv` is ignored and may be null. |
| * |
| * @param key Encryption key. |
| * @param iv IV to use for non-ECB modes, 128 bits. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| status_t aes_decrypt_begin(const aes_key_t key, const aes_block_t *iv); |
| |
| /** |
| * Advances the AES state by a single block. |
| * |
| * The AES hardware does not simply perform a single synchronous block |
| * operation; there is a delay as a block makes it way through the hardware; |
| * outputs are delayed one input from when it is fed into the hardware. |
| * |
| * Therefore, this function works as follows: |
| * 1. The contents of `src` are fed into the hardware (unless it is null, in |
| * which case this step is skipped). |
| * 2. The contents of `dest` are filled with the hardware's output (again, |
| * unless it is null). `dest` may overlap with `src`. |
| * |
| * Operation of the driver will look something like this: |
| * ``` |
| * aes_encrypt_begin(...); |
| * aes_update(NULL, input0); |
| * aes_update(output0, input1); |
| * // ... |
| * aes_update(output(N-1), inputN); |
| * aes_update(outputN, NULL); |
| * aes_end(); |
| * ``` |
| * |
| * @param dest The output block. |
| * @param src The input block. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| status_t aes_update(aes_block_t *dest, const aes_block_t *src); |
| |
| /** |
| * Completes an AES session by clearing control settings and key material. |
| * |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| status_t aes_end(void); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_AES_H_ |