blob: 16de51bb9b3e9fc26aafc154e8a604ddac618aec [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_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_