Skip to content

Commit

Permalink
[ot] Make HMAC msg_length / digest writable & implement key swap
Browse files Browse the repository at this point in the history
This commit adds the checks and functionality for writing to the HMAC
MESSAGE_LENGTH and DIGEST registers whilst the HMAC is not active and
the SHA Engine is disabled, to permit the restoration of saved contexts
(partial computations) using the STOP and CONTINUE commands.

Also implements the KEY_SWAP config option, which now makes the default
configuration use little endian key values, and allows you to use big
endian key values as before by setting the relevant config field to 1.

Signed-off-by: Alex Jones <[email protected]>
  • Loading branch information
AlexJones0 committed Dec 10, 2024
1 parent 1b48d99 commit 0283b05
Showing 1 changed file with 67 additions and 4 deletions.
71 changes: 67 additions & 4 deletions hw/opentitan/ot_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,8 @@ static uint64_t ot_hmac_regs_read(void *opaque, hwaddr addr, unsigned size)
case R_DIGEST_13:
case R_DIGEST_14:
case R_DIGEST_15:
/* We use a sha library in little endian by default, so we only need to
swap if the swap config is 1 (big endian digest). */
if (s->regs->cfg & R_CFG_DIGEST_SWAP_MASK) {
val32 = s->regs->digest[reg - R_DIGEST_0];
} else {
Expand Down Expand Up @@ -747,10 +749,21 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
ot_hmac_report_error(s, R_ERR_CODE_UPDATE_SECRET_KEY_INPROCESS);
break;
}
s->regs->key[reg - R_KEY_0] = bswap32(val32);

/* We use a sha library in little endian by default, so we only need to
swap if the swap config is 0 (i.e. use big endian key). */
if (s->regs->cfg & R_CFG_KEY_SWAP_MASK) {
s->regs->key[reg - R_KEY_0] = val32;
} else {
s->regs->key[reg - R_KEY_0] = bswap32(val32);
}
break;
case R_STATUS:
case R_ERR_CODE:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__,
addr, REG_NAME(reg));
break;
case R_DIGEST_0:
case R_DIGEST_1:
case R_DIGEST_2:
Expand All @@ -767,11 +780,61 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
case R_DIGEST_13:
case R_DIGEST_14:
case R_DIGEST_15:
/* ignore write and report error if engine is not idle */
if (s->regs->cmd) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Cannot W register 0x%02" HWADDR_PRIx
" (%s) whilst non-idle\n",
__func__, addr, REG_NAME(reg));
break;
} else if (s->regs->cfg & R_CFG_SHA_EN_MASK) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Cannot W register 0x%02" HWADDR_PRIx
" (%s) whilst SHA Engine is enabled\n",
__func__, addr, REG_NAME(reg));
}

/* We use a sha library in little endian by default, so we only need to
swap if the swap config is 1 (big endian digest). */
if (s->regs->cfg & R_CFG_DIGEST_SWAP_MASK) {
s->regs->digest[reg - R_DIGEST_0] = bswap32(val32);
} else {
s->regs->digest[reg - R_DIGEST_0] = val32;
}
break;
case R_MSG_LENGTH_LOWER:
/* ignore write and report error if engine is not idle */
if (s->regs->cmd) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Cannot W register 0x%02" HWADDR_PRIx
" (%s) whilst non-idle\n",
__func__, addr, REG_NAME(reg));
break;
} else if (s->regs->cfg & R_CFG_SHA_EN_MASK) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Cannot W register 0x%02" HWADDR_PRIx
" (%s) whilst SHA Engine is enabled\n",
__func__, addr, REG_NAME(reg));
}
s->regs->msg_length =
(s->regs->msg_length & (0xFFFFFFFFull << 32u)) | val32;
break;
case R_MSG_LENGTH_UPPER:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: R/O register 0x%02" HWADDR_PRIx " (%s)\n", __func__,
addr, REG_NAME(reg));
/* ignore write and report error if engine is not idle */
if (s->regs->cmd) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Cannot W register 0x%02" HWADDR_PRIx
" (%s) whilst non-idle\n",
__func__, addr, REG_NAME(reg));
break;
} else if (s->regs->cfg & R_CFG_SHA_EN_MASK) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Cannot W register 0x%02" HWADDR_PRIx
" (%s) whilst SHA Engine is enabled\n",
__func__, addr, REG_NAME(reg));
}
s->regs->msg_length =
((uint64_t)val32 << 32u) | (s->regs->msg_length & 0xFFFFFFFFull);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
Expand Down

0 comments on commit 0283b05

Please sign in to comment.