diff --git a/hw/ip/hmac/doc/programmers_guide.md b/hw/ip/hmac/doc/programmers_guide.md index 05948e4200f9e9..be2785b4a7aa51 100644 --- a/hw/ip/hmac/doc/programmers_guide.md +++ b/hw/ip/hmac/doc/programmers_guide.md @@ -88,17 +88,22 @@ When SW doesn't know each instant at which a full message block is available, it The context that needs to be saved and restored is in the following registers: [`CFG`](registers.md#cfg), [`DIGEST_*`](registers.md#digest), and [`MSG_LENGTH_*`](registers.md#msg_length_lower). +**An RTL bug has been found where the HW is unable to recover if a stop command is issued after the HASH has been processed, more details [here](https://github.com/lowRISC/opentitan/issues/24767). A SW [workaround has been found](https://github.com/lowRISC/opentitan/pull/24944) and implies to adapt the way to use this feature. The temporary changes are marked in italics and replace the previous "normal" operations, which are striked through.** + Each new message stream needs to be started *once* by setting the `CMD.hash_start` bit and finalized *once* by setting the `CMD.hash_process` bit. -To switch from one message stream to another, set the `CMD.hash_stop` bit, wait for the `hmac_done` interrupt (or status bit), save one context and restore the other, and then set the `CMD.hash_continue` bit. +To switch from one message stream to another, ~~set the `CMD.hash_stop` bit, wait for the `hmac_done` interrupt (or status bit)~~ _at a block boundary, insert delay which should be equivalent to at least 80 clock cycles_, save one context, _trigger `CMD.hash_process` to move the FSMs into a stable state_ and restore the other context, and then set the `CMD.hash_continue` bit. Here is an example usage pattern of this feature: 1. Start processing message stream A by configuring HMAC and then setting the `CMD.hash_start` bit. 1. Write an arbitrary number of message blocks to HMAC's `MSG_FIFO`. -1. Stop HMAC by setting the `CMD.hash_stop` bit and wait for the `hmac_done` interrupt (or poll the interrupt status register). +1. _Insert a delay of least 80 clock cycles._ +~~1. Stop HMAC by setting the `CMD.hash_stop` bit and wait for the `hmac_done` interrupt (or poll the interrupt status register).~~ 1. Save the context by reading the `DIGEST_0`..`15` and `MSG_LENGTH_`{`LOWER`,`UPPER`} registers. If the operation is keyed HMAC, the values of `KEY_0`..`X` registers also need to be maintained as part of the context, where `X` is the last register used for the given key length (e.g. for HMAC-256, `X=7`). However, key registers cannot be read from SW, therefore SW must maintain key values as part of its own context during initialization. Similarly, the value of the `CFG` register must also be preserved, and SW should keep its value separately, instead of reading it from `CFG` register. +1. _Disable the `hmac_en` of `CFG` to avoid that HMAC will opad in order to make it faster._ +1. _Trigger `CMD.hash_process`._ 1. Disable `sha_en` by updating `CFG` register, in order to clear the digest from stream A. This is necessary to also prevent leakage of intermediate context of one SW thread to another. 1. Repeat steps 1-5 for message stream B.