Skip to content

Commit b9aa9ff

Browse files
committed
[ot] hw/opentitan: ot_hmac: Add HMAC SHA-2 384/512 & key size support
This commit introduces full support for using the SHA-2 384 and SHA-2 512 algorithms for hashing alongside the existing SHA-2 256 algorithm, by setting the `digest_size` field in the configuration register. It likewise adds support for using a range of key sizes (128/256/384/512/ 1024), and not just always using a 512 bit key - this is set in the `key_length` field in the configuration register. The existing tomcrypt library is used to support the additional hash functionality, which uses `sha512` functionality for both sha384 and sha512 in its implementation.
1 parent b2ab5f3 commit b9aa9ff

File tree

1 file changed

+131
-18
lines changed

1 file changed

+131
-18
lines changed

hw/opentitan/ot_hmac.c

Lines changed: 131 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -399,16 +399,101 @@ static void ot_hmac_writeback_digest_state(OtHMACState *s)
399399
{
400400
/* copy intermediary digest to mock HMAC operation for stop/continue
401401
behaviour. */
402-
/* TODO: add support for SHA2-384 and SHA2-512 */
403-
for (unsigned i = 0; i < 8u; i++) {
404-
STORE32H(s->ctx->state.sha256.state[i], s->regs->digest + i);
402+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
403+
case HMAC_SHA2_256:
404+
for (unsigned idx = 0; idx < 8u; idx++) {
405+
STORE32H(s->ctx->state.sha256.state[idx], s->regs->digest + idx);
406+
}
407+
break;
408+
case HMAC_SHA2_384:
409+
/* Even though SHA384 only uses the first six uint64_t values of
410+
the SHA512 digest, we must store them all for intermediary
411+
computation. */
412+
case HMAC_SHA2_512:
413+
for (unsigned idx = 0; idx < 8u; idx++) {
414+
STORE64H(s->ctx->state.sha512.state[idx],
415+
s->regs->digest + 2 * idx);
416+
}
417+
break;
418+
case HMAC_SHA2_NONE:
419+
default:
420+
qemu_log_mask(
421+
LOG_GUEST_ERROR,
422+
"%s: Cannot write back digest when no valid digest size is set. \n",
423+
__func__);
424+
}
425+
}
426+
427+
static void ot_hmac_restore_context(OtHMACState *s)
428+
{
429+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
430+
case HMAC_SHA2_256:
431+
s->ctx->state.sha256.curlen = 0;
432+
s->ctx->state.sha256.length = s->regs->msg_length;
433+
for (unsigned idx = 0; idx < 8u; idx++) {
434+
s->ctx->state.sha256.state[idx] = s->regs->digest[idx];
435+
}
436+
break;
437+
case HMAC_SHA2_384:
438+
/* Even though SHA384 only uses the first six uint64_t values of
439+
the SHA512 digest, we must restore them all for intermediary
440+
computation. */
441+
case HMAC_SHA2_512:
442+
s->ctx->state.sha512.curlen = 0;
443+
s->ctx->state.sha512.length = s->regs->msg_length;
444+
for (unsigned idx = 0; idx < 8u; idx++) {
445+
s->ctx->state.sha512.state[idx] =
446+
((uint64_t)s->regs->digest[idx + 1] << 32u) |
447+
s->regs->digest[idx];
448+
}
449+
break;
450+
case HMAC_SHA2_NONE:
451+
default:
452+
qemu_log_mask(
453+
LOG_GUEST_ERROR,
454+
"%s: Cannot restore digest when no valid digest size is set. \n",
455+
__func__);
456+
}
457+
}
458+
459+
static size_t ot_hmac_get_curlen(OtHMACState *s)
460+
{
461+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
462+
case HMAC_SHA2_256:
463+
return s->ctx->state.sha256.curlen;
464+
case HMAC_SHA2_384:
465+
case HMAC_SHA2_512:
466+
return s->ctx->state.sha512.curlen;
467+
case HMAC_SHA2_NONE:
468+
default:
469+
qemu_log_mask(LOG_GUEST_ERROR,
470+
"%s: Cannot get the current hash length when no valid "
471+
"digest size is set. \n",
472+
__func__);
473+
return 0u;
405474
}
406475
}
407476

408477
static void ot_hmac_sha_init(OtHMACState *s, bool write_back)
409478
{
410-
/* TODO: add support for SHA2-384 and SHA2-512 */
411-
sha256_init(&s->ctx->state);
479+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
480+
case HMAC_SHA2_256:
481+
sha256_init(&s->ctx->state);
482+
break;
483+
case HMAC_SHA2_384:
484+
sha384_init(&s->ctx->state);
485+
break;
486+
case HMAC_SHA2_512:
487+
sha512_init(&s->ctx->state);
488+
break;
489+
case HMAC_SHA2_NONE:
490+
default:
491+
qemu_log_mask(
492+
LOG_GUEST_ERROR,
493+
"%s: Cannot initialise digest when no valid digest size is set. \n",
494+
__func__);
495+
return;
496+
}
412497
if (write_back) {
413498
ot_hmac_writeback_digest_state(s);
414499
}
@@ -417,17 +502,50 @@ static void ot_hmac_sha_init(OtHMACState *s, bool write_back)
417502
static void ot_hmac_sha_process(OtHMACState *s, const uint8_t *in, size_t inlen,
418503
bool write_back)
419504
{
420-
/* TODO: add support for SHA2-384 and SHA2-512 */
421-
sha256_process(&s->ctx->state, in, inlen);
505+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
506+
case HMAC_SHA2_256:
507+
sha256_process(&s->ctx->state, in, inlen);
508+
break;
509+
/* NOLINTNEXTLINE */
510+
case HMAC_SHA2_384:
511+
sha384_process(&s->ctx->state, in, inlen);
512+
break;
513+
case HMAC_SHA2_512:
514+
sha512_process(&s->ctx->state, in, inlen);
515+
break;
516+
case HMAC_SHA2_NONE:
517+
default:
518+
qemu_log_mask(
519+
LOG_GUEST_ERROR,
520+
"%s: Cannot process the hash when no valid digest size is set. \n",
521+
__func__);
522+
return;
523+
}
422524
if (write_back) {
423525
ot_hmac_writeback_digest_state(s);
424526
}
425527
}
426528

427529
static void ot_hmac_sha_done(OtHMACState *s)
428530
{
429-
/* TODO: add support for SHA2-384 and SHA2-512 */
430-
sha256_done(&s->ctx->state, (uint8_t *)s->regs->digest);
531+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
532+
case HMAC_SHA2_256:
533+
sha256_done(&s->ctx->state, (uint8_t *)s->regs->digest);
534+
return;
535+
case HMAC_SHA2_384:
536+
sha384_done(&s->ctx->state, (uint8_t *)s->regs->digest);
537+
return;
538+
case HMAC_SHA2_512:
539+
sha512_done(&s->ctx->state, (uint8_t *)s->regs->digest);
540+
return;
541+
case HMAC_SHA2_NONE:
542+
default:
543+
qemu_log_mask(LOG_GUEST_ERROR,
544+
"%s: Cannot terminate the hash when no valid digest size "
545+
"is set. \n",
546+
__func__);
547+
return;
548+
}
431549
}
432550

433551
static void ot_hmac_compute_digest(OtHMACState *s)
@@ -465,9 +583,9 @@ static void ot_hmac_process_fifo(OtHMACState *s)
465583
bool stop = s->regs->cmd & R_CMD_HASH_STOP_MASK;
466584

467585
if (!fifo8_is_empty(&s->input_fifo) &&
468-
(!stop || s->ctx->state.sha256.curlen != 0)) {
586+
(!stop || ot_hmac_get_curlen(s) != 0)) {
469587
while (!fifo8_is_empty(&s->input_fifo) &&
470-
(!stop || s->ctx->state.sha256.curlen != 0)) {
588+
(!stop || ot_hmac_get_curlen(s) != 0)) {
471589
uint8_t value = fifo8_pop(&s->input_fifo);
472590
ot_hmac_sha_process(s, &value, 1u, false);
473591
}
@@ -483,7 +601,7 @@ static void ot_hmac_process_fifo(OtHMACState *s)
483601
}
484602
}
485603

486-
if (stop && s->ctx->state.sha256.curlen == 0) {
604+
if (stop && ot_hmac_get_curlen(s) == 0) {
487605
s->regs->intr_state |= INTR_HMAC_DONE_MASK;
488606
s->regs->cmd = 0;
489607
}
@@ -858,12 +976,7 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
858976

859977
s->regs->cmd = R_CMD_HASH_CONTINUE_MASK;
860978

861-
/* Restore SHA256 context */
862-
s->ctx->state.sha256.curlen = 0;
863-
s->ctx->state.sha256.length = s->regs->msg_length;
864-
for (unsigned i = 0; i < 8u; i++) {
865-
s->ctx->state.sha256.state[i] = s->regs->digest[i];
866-
}
979+
ot_hmac_restore_context(s);
867980

868981
/* trigger delayed processing of FIFO */
869982
ibex_irq_set(&s->clkmgr, true);

0 commit comments

Comments
 (0)