diff --git a/hw/opentitan/ot_hmac.c b/hw/opentitan/ot_hmac.c index fd163e2d7f26..49ec989f572b 100644 --- a/hw/opentitan/ot_hmac.c +++ b/hw/opentitan/ot_hmac.c @@ -223,6 +223,22 @@ static const char *REG_NAMES[REGS_COUNT] = { }; #undef REG_NAME_ENTRY +enum OtHMACDigestSize { + HMAC_SHA2_256, + HMAC_SHA2_384, + HMAC_SHA2_512, + HMAC_SHA2_NONE, +}; + +enum OtHMACKeyLength { + HMAC_KEY_128, + HMAC_KEY_256, + HMAC_KEY_384, + HMAC_KEY_512, + HMAC_KEY_1024, + HMAC_KEY_NONE, +}; + struct OtHMACRegisters { uint32_t intr_state; uint32_t intr_enable; @@ -239,6 +255,7 @@ typedef struct OtHMACRegisters OtHMACRegisters; struct OtHMACContext { hash_state state; + enum OtHMACDigestSize digest_size_started; }; typedef struct OtHMACContext OtHMACContext; @@ -260,22 +277,6 @@ struct OtHMACState { char *ot_id; }; -enum OtHMACDigestSize { - HMAC_SHA2_256, - HMAC_SHA2_384, - HMAC_SHA2_512, - HMAC_SHA2_NONE, -}; - -enum OtHMACKeyLength { - HMAC_KEY_128, - HMAC_KEY_256, - HMAC_KEY_384, - HMAC_KEY_512, - HMAC_KEY_1024, - HMAC_KEY_NONE, -}; - static inline enum OtHMACDigestSize ot_hmac_get_digest_size(uint32_t cfg_reg) { switch ((cfg_reg & R_CFG_DIGEST_SIZE_MASK) >> R_CFG_DIGEST_SIZE_SHIFT) { @@ -291,9 +292,9 @@ static inline enum OtHMACDigestSize ot_hmac_get_digest_size(uint32_t cfg_reg) } } -static inline size_t ot_hmac_get_digest_bytes(OtHMACState *s) +static inline size_t ot_hmac_get_digest_bytes(enum OtHMACDigestSize digest_size) { - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (digest_size) { case HMAC_SHA2_256: return 32u; case HMAC_SHA2_384: @@ -399,7 +400,7 @@ static void ot_hmac_writeback_digest_state(OtHMACState *s) { /* copy intermediary digest to mock HMAC operation for stop/continue behaviour. */ - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (s->ctx->digest_size_started) { case HMAC_SHA2_256: for (unsigned idx = 0; idx < 8u; idx++) { STORE32H(s->ctx->state.sha256.state[idx], s->regs->digest + idx); @@ -426,7 +427,7 @@ static void ot_hmac_writeback_digest_state(OtHMACState *s) static void ot_hmac_restore_context(OtHMACState *s) { - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (s->ctx->digest_size_started) { case HMAC_SHA2_256: s->ctx->state.sha256.curlen = 0; s->ctx->state.sha256.length = s->regs->msg_length; @@ -458,7 +459,7 @@ static void ot_hmac_restore_context(OtHMACState *s) static size_t ot_hmac_get_curlen(OtHMACState *s) { - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (s->ctx->digest_size_started) { case HMAC_SHA2_256: return s->ctx->state.sha256.curlen; case HMAC_SHA2_384: @@ -476,7 +477,7 @@ static size_t ot_hmac_get_curlen(OtHMACState *s) static void ot_hmac_sha_init(OtHMACState *s, bool write_back) { - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (s->ctx->digest_size_started) { case HMAC_SHA2_256: sha256_init(&s->ctx->state); break; @@ -502,7 +503,7 @@ static void ot_hmac_sha_init(OtHMACState *s, bool write_back) static void ot_hmac_sha_process(OtHMACState *s, const uint8_t *in, size_t inlen, bool write_back) { - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (s->ctx->digest_size_started) { case HMAC_SHA2_256: sha256_process(&s->ctx->state, in, inlen); break; @@ -527,7 +528,7 @@ static void ot_hmac_sha_process(OtHMACState *s, const uint8_t *in, size_t inlen, static void ot_hmac_sha_done(OtHMACState *s) { - switch (ot_hmac_get_digest_size(s->regs->cfg)) { + switch (s->ctx->digest_size_started) { case HMAC_SHA2_256: sha256_done(&s->ctx->state, (uint8_t *)s->regs->digest); return; @@ -570,7 +571,9 @@ static void ot_hmac_compute_digest(OtHMACState *s) ot_hmac_sha_init(s, false); ot_hmac_sha_process(s, (const uint8_t *)opad, pad_length_b, false); ot_hmac_sha_process(s, (const uint8_t *)s->regs->digest, - ot_hmac_get_digest_bytes(s), true); + ot_hmac_get_digest_bytes( + s->ctx->digest_size_started), + true); } ot_hmac_sha_done(s); } @@ -910,6 +913,10 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value, ibex_irq_set(&s->clkmgr, true); + /* Hold the previous digest size until the HMAC is started with the + new digest size configured */ + s->ctx->digest_size_started = ot_hmac_get_digest_size(s->regs->cfg); + ot_hmac_sha_init(s, true); /* HMAC mode, process input padding */ @@ -975,6 +982,10 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value, s->regs->cmd = R_CMD_HASH_CONTINUE_MASK; + /* Hold the previous digest size until the HMAC is started with the + new digest size configured */ + s->ctx->digest_size_started = ot_hmac_get_digest_size(s->regs->cfg); + ot_hmac_restore_context(s); /* trigger delayed processing of FIFO */