Skip to content

Commit

Permalink
[ot] hw/opentitan: ot_hmac: Digest size write should not affect curre…
Browse files Browse the repository at this point in the history
…nt hash

This commit updates the functionality for the HMAC's digest size
configuration register field, updating it to match the current hardware
behaviour. The hardware uses a `digest_size_started` field to allow the
user to write a digest size at any time, while ensuring that if a hash
is in progress it will carry on using the existing digest size.

A similar field is introduced into the context/state struct to allow the
QEMU HMAC model to keep track of the digest size when the last
START/CONTINUE command was sent, and use that in place of checking the
register value every time.
  • Loading branch information
AlexJones0 committed Dec 16, 2024
1 parent b8ad30d commit f603875
Showing 1 changed file with 40 additions and 25 deletions.
65 changes: 40 additions & 25 deletions hw/opentitan/ot_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,22 @@ static const char *REG_NAMES[REGS_COUNT] = {
};
#undef REG_NAME_ENTRY

typedef enum OtHMACDigestSize {
HMAC_SHA2_NONE,
HMAC_SHA2_256,
HMAC_SHA2_384,
HMAC_SHA2_512,
} OtHMACDigestSize;

typedef enum OtHMACKeyLength {
HMAC_KEY_NONE,
HMAC_KEY_128,
HMAC_KEY_256,
HMAC_KEY_384,
HMAC_KEY_512,
HMAC_KEY_1024,
} OtHMACKeyLength;

struct OtHMACRegisters {
uint32_t intr_state;
uint32_t intr_enable;
Expand All @@ -245,6 +261,7 @@ typedef struct OtHMACRegisters OtHMACRegisters;

struct OtHMACContext {
hash_state state;
OtHMACDigestSize digest_size_started;
};
typedef struct OtHMACContext OtHMACContext;

Expand All @@ -266,22 +283,6 @@ struct OtHMACState {
char *ot_id;
};

typedef enum OtHMACDigestSize {
HMAC_SHA2_NONE,
HMAC_SHA2_256,
HMAC_SHA2_384,
HMAC_SHA2_512,
} OtHMACDigestSize;

typedef enum OtHMACKeyLength {
HMAC_KEY_NONE,
HMAC_KEY_128,
HMAC_KEY_256,
HMAC_KEY_384,
HMAC_KEY_512,
HMAC_KEY_1024,
} OtHMACKeyLength;

static inline OtHMACDigestSize ot_hmac_get_digest_size(uint32_t cfg_reg)
{
switch ((cfg_reg & R_CFG_DIGEST_SIZE_MASK) >> R_CFG_DIGEST_SIZE_SHIFT) {
Expand All @@ -297,9 +298,9 @@ static inline OtHMACDigestSize ot_hmac_get_digest_size(uint32_t cfg_reg)
}
}

static size_t ot_hmac_get_digest_bytes(OtHMACState *s)
static size_t ot_hmac_get_digest_bytes(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:
Expand Down Expand Up @@ -412,7 +413,7 @@ static void ot_hmac_report_error(OtHMACState *s, uint32_t error)
static void ot_hmac_writeback_digest_state(OtHMACState *s)
{
/* copy intermediary digest to mock HMAC's 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);
Expand Down Expand Up @@ -441,7 +442,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;
Expand Down Expand Up @@ -473,7 +474,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:
Expand All @@ -492,7 +493,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;
Expand All @@ -519,7 +520,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;
Expand All @@ -546,7 +547,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;
Expand Down Expand Up @@ -589,7 +590,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);
}
Expand Down Expand Up @@ -931,6 +934,12 @@ 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 */
Expand Down Expand Up @@ -998,6 +1007,12 @@ 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 */
Expand Down

0 comments on commit f603875

Please sign in to comment.