HMAC-SHA2
The HMAC component is based on the OpenTitan HMAC design.
OpenTitan HMAC core reference architecture shows the upstream core. The OCAH bus, key-delivery, and entropy connections are described in the integration details below.
1. OCAH Modifications
-
AXI4-lite key bus slave interface replaces side loading interface
-
AXI4-lite control/status bus slave interface
The crypto interconnect narrows HMAC’s host path from 64-bit AXI to 32-bit AXI,
converts and isolates it as AXI-Lite, then hmac_wrapper bridges it to TL-UL
for the tt_hmac core. The address path subtracts the HMAC base address and
masks to a 13-bit window (8 KB), accommodating both the register space and the
message FIFO window at offset 0x1000. HMAC exposes a single fatal
alert channel (index [0] in OpenTitan Alert Termination), three interrupts
(done, fifo_empty, err), and an idle_o status output. Unlike the other
crypto wrappers, HMAC has no EDN connection.
The Key Manager delivers a 256-bit HMAC key as eight words per share, in the
format given in Key Manager Key Delivery. HMAC has no select bit: the delivered key
is used in preference to the engine’s software key registers whenever
KEY_CTRL.KEY_VALID is set.
The delivered key is most-significant-bit justified in the engine’s 1024-bit
key field, and the engine takes its key length from CFG.key_length, which the
delivery path does not write; only the 256-bit encoding matches the delivered
key. An unset or unsupported length
raises a configuration error when hashing starts. A supported length that
disagrees with the delivered key does not raise an error: the engine takes key
material from the top of the 1024-bit field, so the padding below the delivered
key is mixed into the key and the resulting digest is wrong but repeatable.
Consult the OpenTitan HMAC documentation for the authoritative core functionality of the IP. The Programmer’s Guide gives the programming guidance for this block. The register map follows below.
2. Memory Map and Register Reference
2.1. Memory Map
Register offsets are relative to the block base in the subsystem memory map. The detailed map below defines each register and its fields.
2.2. Detailed Register Map
HMAC Accelerator
Accelerator for SHA-2 256/384/512-based keyed HMAC and the hash function
Register Arrays:
- KEY[32]: 32 registers, base 0x24, stride 0x4
- DIGEST[16]: 16 registers, base 0xA4, stride 0x4
Register List:
| Address | Name | Access | Description |
|---|---|---|---|
| 0x0 | INTR_STATE | RW | - |
| 0x4 | INTR_ENABLE | RW | - |
| 0x8 | INTR_TEST | W | - |
| 0xC | ALERT_TEST | W | - |
| 0x10 | CFG | RW | - |
| 0x14 | CMD | W | - |
| 0x18 | STATUS | R | - |
| 0x1C | ERR_CODE | R | - |
| 0x20 | WIPE_SECRET | W | - |
| 0x24 - 0xA0 | KEY[32] | W | - |
| 0xA4 - 0xE0 | DIGEST[16] | RW | - |
| 0xE4 | MSG_LENGTH_LOWER | RW | - |
| 0xE8 | MSG_LENGTH_UPPER | RW | - |
Register Details:
INTR_STATE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:3 | Reserved | - | - | Reserved |
| 2 | hmac_err | RW1C | 0x0 | HMAC error has occurred. ERR_CODE register shows which error occurred. |
| 1 | fifo_empty | R | 0x0 | The message FIFO is empty. This interrupt is raised only if the message FIFO is actually writable by software, i.e., if all of the following conditions are met: i) The HMAC block is not running in HMAC mode and performing the second round of computing the final hash of the outer key as well as the result of the first round using the inner key. ii) Software has not yet written the Process or Stop command to finish the hashing operation. For the interrupt to be raised, the message FIFO must also have been full previously. Otherwise, the hardware empties the FIFO faster than software can fill it and there is no point in interrupting the software to inform it about the message FIFO being empty. |
| 0 | hmac_done | RW1C | 0x0 | HMAC/SHA-2 has completed. |
INTR_ENABLE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:3 | Reserved | - | - | Reserved |
| 2 | hmac_err | RW | 0x0 | Enable interrupt when !!INTR_STATE.hmac_err is set. |
| 1 | fifo_empty | RW | 0x0 | Enable interrupt when !!INTR_STATE.fifo_empty is set. |
| 0 | hmac_done | RW | 0x0 | Enable interrupt when !!INTR_STATE.hmac_done is set. |
INTR_TEST
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:3 | Reserved | - | - | Reserved |
| 2 | hmac_err | W | 0x0 | Write 1 to force !!INTR_STATE.hmac_err to 1. |
| 1 | fifo_empty | W | 0x0 | Write 1 to force !!INTR_STATE.fifo_empty to 1. |
| 0 | hmac_done | W | 0x0 | Write 1 to force !!INTR_STATE.hmac_done to 1. |
ALERT_TEST
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:1 | Reserved | - | - | Reserved |
| 0 | fatal_fault | W | 0x0 | Write 1 to trigger one alert event of this kind. |
CFG
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:15 | Reserved | - | - | Reserved |
| 14:9 | key_length | RW | 0x20 | Key length configuration. This is a 6-bit one-hot encoded field to configure the key length for HMAC. The HMAC can be programmed with the following key lengths: 128-bit, 256-bit, 384-bit, 512-bit and 1024-bit. But the HMAC supports any arbitrary key length: the software should configure the HMAC with the next largest supported key length and concatenate zeros to reach the programmed key length. The position of these zeros depends on the endianness, thus on the programmed [`CFG.key_swap`](registers.md#cfg--key_swap). For example, for an 80-bit key, HMAC should be configured with an 128-bit key length, fed with the 80-bit key and with 48 zero-bits. Note that the key length cannot be greater than the block size: up to 1024-bit for SHA-2 384/512 and up to 512-bit for SHA-2 256. The value of this register is irrelevant when only SHA-2 (not keyed HMAC) is configured. However, for HMAC mode (`hmac_en == 1`), when HMAC is triggered to start while !!KEY_LENGTH holds `Key_None` or !!KEY_LENGTH holds `Key_1024` for !!DIGEST_SIZE = `SHA2_256`, starting is blocked and an error is signalled to SW. |
| 8:5 | digest_size | RW | 0x8 | Digest size configuration. This is a 4-bit one-hot encoded field to select digest size for either HMAC or SHA-2. Invalid/unsupported values, i.e., values that don't correspond to SHA2_256, SHA2_384, or SHA2_512, are mapped to SHA2_None. |
| 4 | key_swap | RW | 0x0 | Key register byte swap (deprecated: KEY path is for DV only; production uses key manager sideload). If 1 the endianness of each KEY_* register is swapped. Default value (value 0) is big endian representation of the KEY_* CSRs. |
| 3 | digest_swap | RW | 0x0 | Digest register byte swap. If 1 the value in each digest output register is converted to big-endian byte order. This setting does not affect the order of the digest output registers, !!DIGEST_0 still contains the first 4 bytes of the digest. |
| 2 | endian_swap | RW | 0x0 | Endian swap. If 0, each value will be added to the message in little-endian byte order. The value is written to MSG_FIFO same to the SW writes. If 1, then each individual multi-byte value, regardless of its alignment, written to !!MSG_FIFO will be added to the message in big-endian byte order. A message written to !!MSG_FIFO one byte at a time will not be affected by this setting. From a hardware perspective byte swaps are performed on a TL-UL word granularity. |
| 1 | sha_en | RW | - | SHA-2 enable. If 0, the SHA engine will not initiate compression, this is used to stop operation of the SHA-2 engine until configuration has been done. When the SHA-2 engine is disabled the digest is cleared. |
| 0 | hmac_en | RW | - | HMAC datapath enable. If this bit is 1, HMAC operates when `hash_start` toggles. |
CMD
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:4 | Reserved | - | - | Reserved |
| 3 | hash_continue | W1C | - | When 1 is written to this field, SHA-2 or HMAC will continue hashing based on the current hash in the digest registers and the message length, which both have to be restored to switch context. |
| 2 | hash_stop | W1C | - | When 1 is written to this field, SHA-2 or HMAC will afterwards set the `hmac_done` interrupt as soon as the current block has been hashed. The hash can then be read from the registers !!DIGEST_0 to !!DIGEST_15. Together with the message length in !!MSG_LENGTH_LOWER and !!MSG_LENGTH_UPPER, this forms the information that has to be saved before switching context. |
| 1 | hash_process | W1C | - | If 1 is written to this field, SHA-2 or HMAC calculates the digest or signing based on currently received message. |
| 0 | hash_start | W1C | - | If 1 is written into this field, SHA-2 or HMAC begins its operation. CPU must configure relative information first, such as the digest size, secret key and the key length. |
STATUS
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:10 | Reserved | - | - | Reserved |
| 9:4 | fifo_depth | R | - | FIFO entry count. |
| 3 | Reserved | - | - | Reserved |
| 2 | fifo_full | R | - | FIFO full. Data written to the FIFO whilst it is full will cause back-pressure on the interconnect |
| 1 | fifo_empty | R | 0x1 | FIFO empty |
| 0 | hmac_idle | R | 0x1 | HMAC idle status. When IDLE, the `DIGEST` and the `MSG_LENGTH_LOWER`/`MSG_LENGTH_UPPER` can be written to from SW which enables restoring context (to support context switching). |
ERR_CODE
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | err_code | R | 0x0 | If an error interrupt occurs, this register has information of error cause. Please take a look at `hw/ip/prim/rtl/prim_sha2_pkg.sv:err_code_e enum type. |
WIPE_SECRET
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | secret | W | - | Secret value |
KEY[32]
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | key_0 | W | - | 32-bit chunk of 1024-bit secret key |
DIGEST[16]
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | digest_0 | RW | - | 32-bit chunk of 512-bit digest |
MSG_LENGTH_LOWER
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | v | RW | - | Message Length [31:0] |
MSG_LENGTH_UPPER
| Bits | Field | Access | Reset | Description |
|---|---|---|---|---|
| 31:0 | v | RW | - | Message Length [63:32] |