Skip to content

Commit fef0557

Browse files
committed
[ot] Add STOP/CONTINUE commands to HMAC
Adds the STOP/CONTINUE commands to the OpenTitan HMAC model. These commands allow you to stop a SHA/HMAC hash after the next full round of hashing/compression, and retrieve the partial digest so that this context can be restored later and computation can continue. This lets users stop/start the HMAC as needed, and better cache hash computations. To correctly implement these commands, in addition to writing back the partial intermediary digests of the `sha_process` operations, additional conditional logic is introduced on stop commands for only processing the FIFO until the next hash block boundary, and an additional check is added to the `process` call for the hash being completed. Note that this commit still hard-codes for SHA256, and does not update the corresponding DIGEST / MESSAGE LENGTH registers to be writable. Signed-off-by: Alex Jones <alex.jones@lowrisc.org>
1 parent e826ad8 commit fef0557

File tree

1 file changed

+57
-5
lines changed

1 file changed

+57
-5
lines changed

hw/opentitan/ot_hmac.c

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,17 +342,34 @@ static void ot_hmac_process_fifo(OtHMACState *s)
342342
{
343343
trace_ot_hmac_debug(s->ot_id, __func__);
344344

345-
if (!fifo8_is_empty(&s->input_fifo)) {
346-
while (!fifo8_is_empty(&s->input_fifo)) {
345+
const bool stop = s->regs->cmd & R_CMD_HASH_STOP_MASK;
346+
const bool process = s->regs->cmd & R_CMD_HASH_PROCESS_MASK;
347+
348+
if (!fifo8_is_empty(&s->input_fifo) &&
349+
(!stop || s->ctx->state.sha256.curlen != 0)) {
350+
while (!fifo8_is_empty(&s->input_fifo) &&
351+
(!stop || s->ctx->state.sha256.curlen != 0)) {
347352
uint8_t value = fifo8_pop(&s->input_fifo);
348353
ot_hmac_sha_process(s, &value, 1, false);
349354
}
350355

356+
/* write back updated digest state */
357+
if (fifo8_is_empty(&s->input_fifo) || stop) {
358+
ot_hmac_writeback_digest_state(s);
359+
}
360+
351361
/* assert FIFO Empty IRQ */
352-
s->regs->intr_state |= INTR_FIFO_EMPTY_MASK;
362+
if (fifo8_is_empty(&s->input_fifo)) {
363+
s->regs->intr_state |= INTR_FIFO_EMPTY_MASK;
364+
}
365+
}
366+
367+
if (stop && s->ctx->state.sha256.curlen == 0) {
368+
s->regs->intr_state |= INTR_HMAC_DONE_MASK;
369+
s->regs->cmd = 0;
353370
}
354371

355-
if (s->regs->cmd & R_CMD_HASH_PROCESS_MASK) {
372+
if (process && s->ctx->state.sha256.length >= 512) {
356373
ot_hmac_compute_digest(s);
357374
s->regs->intr_state |= INTR_HMAC_DONE_MASK;
358375
s->regs->cmd = 0;
@@ -631,7 +648,8 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
631648
}
632649

633650
if (val32 & R_CMD_HASH_PROCESS_MASK) {
634-
if (!(s->regs->cmd & R_CMD_HASH_START_MASK)) {
651+
if (!(s->regs->cmd &
652+
(R_CMD_HASH_START_MASK | R_CMD_HASH_CONTINUE_MASK))) {
635653
qemu_log_mask(
636654
LOG_GUEST_ERROR,
637655
"%s: CMD.PROCESS requested but hash not started yet\n",
@@ -651,6 +669,40 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
651669
ibex_irq_set(&s->clkmgr, true);
652670
ot_hmac_process_fifo(s);
653671
}
672+
673+
if (val32 & R_CMD_HASH_STOP_MASK) {
674+
s->regs->cmd = R_CMD_HASH_STOP_MASK;
675+
676+
/* trigger delayed processing of FIFO until the next block is processed. */
677+
ibex_irq_set(&s->clkmgr, true);
678+
ot_hmac_process_fifo(s);
679+
}
680+
681+
if (val32 & R_CMD_HASH_CONTINUE_MASK) {
682+
if (!(s->regs->cfg & R_CFG_SHA_EN_MASK)) {
683+
ot_hmac_report_error(s,
684+
R_ERR_CODE_HASH_START_WHEN_SHA_DISABLED);
685+
break;
686+
}
687+
if (s->regs->cmd) {
688+
ot_hmac_report_error(s, R_ERR_CODE_HASH_START_WHEN_ACTIVE);
689+
break;
690+
}
691+
692+
s->regs->cmd = R_CMD_HASH_CONTINUE_MASK;
693+
694+
// Restore SHA256 context
695+
s->ctx->state.sha256.curlen = 0;
696+
s->ctx->state.sha256.length = s->regs->msg_length;
697+
for (uint8_t i = 0; i < 8; i++) {
698+
s->ctx->state.sha256.state[i] = s->regs->digest[i];
699+
}
700+
701+
/* trigger delayed processing of FIFO */
702+
ibex_irq_set(&s->clkmgr, true);
703+
ot_hmac_process_fifo(s);
704+
}
705+
654706
break;
655707
case R_WIPE_SECRET:
656708
/* TODO ignore write if engine is not idle? */

0 commit comments

Comments
 (0)