HMAC-SHA2

The HMAC component is based on the OpenTitan HMAC design.

OpenTitan HMAC core reference architecture
Figure 1. OpenTitan HMAC core reference architecture

Figure 1 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:

Table 1. HMAC Accelerator register list
AddressNameAccessDescription
0x0INTR_STATERW-
0x4INTR_ENABLERW-
0x8INTR_TESTW-
0xCALERT_TESTW-
0x10CFGRW-
0x14CMDW-
0x18STATUSR-
0x1CERR_CODER-
0x20WIPE_SECRETW-
0x24 - 0xA0KEY[32]W-
0xA4 - 0xE0DIGEST[16]RW-
0xE4MSG_LENGTH_LOWERRW-
0xE8MSG_LENGTH_UPPERRW-

Register Details:

INTR_STATE

Table 2. hmac.INTR_STATE fields
BitsFieldAccessResetDescription
31:3Reserved--Reserved
2hmac_errRW1C0x0HMAC error has occurred. ERR_CODE register shows which error occurred.
1fifo_emptyR0x0The 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.
0hmac_doneRW1C0x0HMAC/SHA-2 has completed.

INTR_ENABLE

Table 3. hmac.INTR_ENABLE fields
BitsFieldAccessResetDescription
31:3Reserved--Reserved
2hmac_errRW0x0Enable interrupt when !!INTR_STATE.hmac_err is set.
1fifo_emptyRW0x0Enable interrupt when !!INTR_STATE.fifo_empty is set.
0hmac_doneRW0x0Enable interrupt when !!INTR_STATE.hmac_done is set.

INTR_TEST

Table 4. hmac.INTR_TEST fields
BitsFieldAccessResetDescription
31:3Reserved--Reserved
2hmac_errW0x0Write 1 to force !!INTR_STATE.hmac_err to 1.
1fifo_emptyW0x0Write 1 to force !!INTR_STATE.fifo_empty to 1.
0hmac_doneW0x0Write 1 to force !!INTR_STATE.hmac_done to 1.

ALERT_TEST

Table 5. hmac.ALERT_TEST fields
BitsFieldAccessResetDescription
31:1Reserved--Reserved
0fatal_faultW0x0Write 1 to trigger one alert event of this kind.

CFG

Table 6. hmac.CFG fields
BitsFieldAccessResetDescription
31:15Reserved--Reserved
14:9key_lengthRW0x20Key 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:5digest_sizeRW0x8Digest 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.
4key_swapRW0x0Key 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.
3digest_swapRW0x0Digest 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.
2endian_swapRW0x0Endian 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.
1sha_enRW-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.
0hmac_enRW-HMAC datapath enable.

If this bit is 1, HMAC operates when `hash_start` toggles.

CMD

Table 7. hmac.CMD fields
BitsFieldAccessResetDescription
31:4Reserved--Reserved
3hash_continueW1C-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.
2hash_stopW1C-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.
1hash_processW1C-If 1 is written to this field, SHA-2 or HMAC calculates the digest or signing based on currently received message.
0hash_startW1C-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

Table 8. hmac.STATUS fields
BitsFieldAccessResetDescription
31:10Reserved--Reserved
9:4fifo_depthR-FIFO entry count.
3Reserved--Reserved
2fifo_fullR-FIFO full. Data written to the FIFO whilst it is full will cause back-pressure on the interconnect
1fifo_emptyR0x1FIFO empty
0hmac_idleR0x1HMAC 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

Table 9. hmac.ERR_CODE fields
BitsFieldAccessResetDescription
31:0err_codeR0x0If 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

Table 10. hmac.WIPE_SECRET fields
BitsFieldAccessResetDescription
31:0secretW-Secret value

KEY[32]

Table 11. hmac.KEY[32] fields
BitsFieldAccessResetDescription
31:0key_0W-32-bit chunk of 1024-bit secret key

DIGEST[16]

Table 12. hmac.DIGEST[16] fields
BitsFieldAccessResetDescription
31:0digest_0RW-32-bit chunk of 512-bit digest

MSG_LENGTH_LOWER

Table 13. hmac.MSG_LENGTH_LOWER fields
BitsFieldAccessResetDescription
31:0vRW-Message Length [31:0]

MSG_LENGTH_UPPER

Table 14. hmac.MSG_LENGTH_UPPER fields
BitsFieldAccessResetDescription
31:0vRW-Message Length [63:32]