| // 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_DIF_DIF_HMAC_H_ |
| #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_HMAC_H_ |
| |
| /** |
| * @file |
| * @brief <a href="/hw/ip/hmac/doc/">HMAC</a> Device Interface Functions |
| */ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "sw/device/lib/base/macros.h" |
| #include "sw/device/lib/base/mmio.h" |
| #include "sw/device/lib/dif/dif_base.h" |
| |
| #include "sw/device/lib/dif/autogen/dif_hmac_autogen.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif // __cplusplus |
| |
| /** |
| * Supported HMAC modes of operation. |
| */ |
| typedef enum dif_hmac_mode { |
| /** The HMAC mode. */ |
| kDifHmacModeHmac = 0, |
| /** The SHA256-only mode. */ |
| kDifHmacModeSha256, |
| } dif_hmac_mode_t; |
| |
| /** |
| * Supported byte endienness options. |
| */ |
| typedef enum dif_hmac_endianness { |
| /** Big endian byte ordering. */ |
| kDifHmacEndiannessBig = 0, |
| /** Little endian byte ordering. */ |
| kDifHmacEndiannessLittle, |
| } dif_hmac_endianness_t; |
| |
| /** |
| * Configuration for a single HMAC Transaction |
| */ |
| typedef struct dif_hmac_transaction { |
| /** Byte endianness for writes to the FIFO. */ |
| dif_hmac_endianness_t message_endianness; |
| /** Byte endianness for reads from the digest. */ |
| dif_hmac_endianness_t digest_endianness; |
| } dif_hmac_transaction_t; |
| |
| /** |
| * A typed representation of the HMAC digest. |
| */ |
| typedef struct dif_hmac_digest { |
| uint32_t digest[8]; |
| } dif_hmac_digest_t; |
| |
| /** |
| * Resets the HMAC engine and readies it to receive a new message to process an |
| * HMAC digest. |
| * |
| * This function causes the HMAC engine to start its operation. After a |
| * successful call to this function, |dif_hmac_fifo_push()| can be called to |
| * write the message for HMAC processing. |
| * |
| * This function must be called with a valid `key` that references a 32-byte, |
| * contiguous, readable region where the key may be copied from. |
| * |
| * @param hmac The HMAC device to start HMAC operation for. |
| * @param key The 256-bit HMAC key. |
| * @param config The per-transaction configuration. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_mode_hmac_start(const dif_hmac_t *hmac, |
| const uint8_t *key, |
| const dif_hmac_transaction_t config); |
| |
| /** |
| * Resets the HMAC engine and readies it to receive a new message to process a |
| * SHA256 digest. |
| * |
| * This function causes the HMAC engine to start its operation. After a |
| * successful call to this function, |dif_hmac_fifo_push()| can be called to |
| * write the message for SHA256 processing. |
| * |
| * @param hmac The HMAC device to start SHA256 operation for. |
| * @param config The per-transaction configuration. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_mode_sha256_start(const dif_hmac_t *hmac, |
| const dif_hmac_transaction_t config); |
| |
| /** |
| * Attempts to send `len` bytes from the buffer pointed to by `data` to the |
| * device described by `hmac`. This function will send to the message FIFO until |
| * the FIFO fills up or `len` bytes have been sent. |
| * |
| * In the event that the FIFO fills up before `len` bytes have been sent this |
| * function will return a `kDifHmacFifoFull` error. In this case it is valid |
| * to call this function again by advancing `data` by `len` - |*bytes_sent| |
| * bytes. It may be desirable to wait for space to free up on the FIFO before |
| * issuing subsequent calls to this function, but it is not strictly |
| * necessary. The number of entries in the FIFO can be queried with |
| * `dif_hmac_fifo_count_entries()`. |
| * |
| * `data` *must* point to an allocated buffer of at least length `len`. |
| * |
| * @param hmac The HMAC device to send to. |
| * @param data A contiguous buffer to copy from. |
| * @param len The length of the buffer to copy from. |
| * @param[out] bytes_sent The number of bytes sent to the FIFO (optional). |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_fifo_push(const dif_hmac_t *hmac, const void *data, |
| size_t len, size_t *bytes_sent); |
| |
| /** |
| * Retrieves the number of entries in the HMAC FIFO. These entries may be |
| * semi-arbitrary in length; this function should not be used to calculate |
| * message length. |
| * |
| * @param hmac The HMAC device to get the FIFO depth for. |
| * @param[out] num_entries The number of entries in the FIFO. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_fifo_count_entries(const dif_hmac_t *hmac, |
| uint32_t *num_entries); |
| |
| /** |
| * Retrieves the number of bits in the loaded HMAC device. |
| * `dif_hmac_fifo_count_entries()` should be called before this function to |
| * ensure the FIFO is empty, as any bits in the FIFO are not counted in |
| * `msg_len`. |
| * |
| * @param hmac The HMAC device to get the message length for. |
| * @param[out] msg_len The number of bits in the HMAC message. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_get_message_length(const dif_hmac_t *hmac, |
| uint64_t *msg_len); |
| |
| /** |
| * Attempts to run HMAC or SHA256 depending on the mode `hmac` was initialized |
| * in. Calls to this function always succeed and return without blocking. The |
| * caller can use `dif_hmac_check_state()` to check for errors and for the |
| * `DIF_HMAC_DONE` status before reading the digest with |
| * `dif_hmac_digest_read()`. |
| * |
| * @param hmac The HMAC device to initiate the run on. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_process(const dif_hmac_t *hmac); |
| |
| /** |
| * Attempts to finish a transaction started with `dif_hmac_mode_*_start`, and |
| * reads the final digest in the buffer referenced by `digest`. |
| * |
| * This queries the `INTR_STATE` register to check if the HMAC is finished, and |
| * will acknowledge a `hmac_done` interrupt. If that register is not pending, |
| * then this function assumes HMAC is still processing and will return |
| * `kDifHmacErrorDigestProcessing`. |
| * |
| * Once the digest has been read, the HMAC and SHA256 datapaths are disabled, |
| * clearing the digest registers. |
| * |
| * `digest` must reference an allocated, contiguous, 32-byte buffer. This buffer |
| * shall also be 4-byte aligned. This is all consistent with the platform |
| * requirements for size and alignment requirements of `dif_hmac_digest_t`. |
| * |
| * @param hmac The HMAC device to read the digest from. |
| * @param[out] digest A contiguous 32-byte, 4-byte aligned buffer for the |
| * digest. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_finish(const dif_hmac_t *hmac, dif_hmac_digest_t *digest); |
| |
| /** |
| * Randomizes internal secret registers on the HMAC device. This includes the |
| * key, hash value, and internal state machine. The value of `entropy` will be |
| * used to "randomize" the internal state of the HMAC device. See the HMAC IP |
| * documentation for more information: hw/ip/hmac/doc. |
| * |
| * @param hmac The HMAC device to clobber state on. |
| * @param entropy A source of randomness to write to the HMAC internal state. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_hmac_wipe_secret(const dif_hmac_t *hmac, uint32_t entropy); |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif // __cplusplus |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_HMAC_H_ |