Skip to content

Commit b2ab5f3

Browse files
committed
[ot] hw/opentitan: ot_hmac: Make HMAC outer hash independent of key/digest size
This commit updates the size of the key and digest registers to their new maximum sizes in support of HMAC Multi-Mode (SHA-2 256/384/512 Engine), which is 64 bytes for the digest and 128 bytes for the key. The current HMAC logic which processes the input padding and performs the outer hash (using the outer padding) by default assumes that the key length is 64 bytes (512 bits), and that you are hence using the entire set of registers. They also assume that the digest is 32 bytes (256 bits), and that you are again hence using the entire register set. The new logic now uses the key_length and digest_size config register fields to determine the exact padding and digest sizes that should be used in the HMAC calculations.
1 parent 70e9305 commit b2ab5f3

File tree

1 file changed

+87
-21
lines changed

1 file changed

+87
-21
lines changed

hw/opentitan/ot_hmac.c

Lines changed: 87 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@
4444
/* Input FIFO length is 64 bytes (16 x 32 bits) */
4545
#define OT_HMAC_FIFO_LENGTH 64u
4646

47-
/* Digest length is 32 bytes (256 bits) */
48-
#define OT_HMAC_DIGEST_LENGTH 32u
47+
/* (Maximum) digest length is 64 bytes (512 bits) */
48+
#define OT_HMAC_MAX_DIGEST_LENGTH 64u
4949

50-
/* HMAC key length is 32 bytes (256 bits) */
51-
#define OT_HMAC_KEY_LENGTH 32u
50+
/* HMAC (maximum) key length is 128 bytes (1024 bits) */
51+
#define OT_HMAC_MAX_KEY_LENGTH 128u
5252

5353
#define PARAM_NUM_IRQS 3u
5454

@@ -231,8 +231,8 @@ struct OtHMACRegisters {
231231
uint32_t cmd;
232232
uint32_t err_code;
233233
uint32_t wipe_secret;
234-
uint32_t key[OT_HMAC_KEY_LENGTH / sizeof(uint32_t)];
235-
uint32_t digest[OT_HMAC_DIGEST_LENGTH / sizeof(uint32_t)];
234+
uint32_t key[OT_HMAC_MAX_KEY_LENGTH / sizeof(uint32_t)];
235+
uint32_t digest[OT_HMAC_MAX_DIGEST_LENGTH / sizeof(uint32_t)];
236236
uint64_t msg_length;
237237
};
238238
typedef struct OtHMACRegisters OtHMACRegisters;
@@ -291,6 +291,41 @@ static inline enum OtHMACDigestSize ot_hmac_get_digest_size(uint32_t cfg_reg)
291291
}
292292
}
293293

294+
static inline size_t ot_hmac_get_digest_bytes(OtHMACState *s)
295+
{
296+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
297+
case HMAC_SHA2_256:
298+
return 32u;
299+
case HMAC_SHA2_384:
300+
return 48u;
301+
case HMAC_SHA2_512:
302+
return 64u;
303+
case HMAC_SHA2_NONE:
304+
default:
305+
qemu_log_mask(LOG_GUEST_ERROR,
306+
"%s: Cannot get digest size if it is not set. \n",
307+
__func__);
308+
return 0u;
309+
}
310+
}
311+
312+
static inline size_t ot_hmac_get_block_size_bytes(OtHMACState *s)
313+
{
314+
switch (ot_hmac_get_digest_size(s->regs->cfg)) {
315+
case HMAC_SHA2_256:
316+
return 64u;
317+
case HMAC_SHA2_384:
318+
case HMAC_SHA2_512:
319+
return 128u;
320+
case HMAC_SHA2_NONE:
321+
default:
322+
qemu_log_mask(LOG_GUEST_ERROR,
323+
"%s: Cannot get block size if digest size is not set. \n",
324+
__func__);
325+
return 0u;
326+
}
327+
}
328+
294329
static inline enum OtHMACKeyLength ot_hmac_get_key_length(uint32_t cfg_reg)
295330
{
296331
switch ((cfg_reg & R_CFG_KEY_LENGTH_MASK) >> R_CFG_KEY_LENGTH_SHIFT) {
@@ -310,6 +345,27 @@ static inline enum OtHMACKeyLength ot_hmac_get_key_length(uint32_t cfg_reg)
310345
}
311346
}
312347

348+
static inline size_t ot_hmac_get_key_bytes(OtHMACState *s)
349+
{
350+
switch (ot_hmac_get_key_length(s->regs->cfg)) {
351+
case HMAC_KEY_128:
352+
return 16u;
353+
case HMAC_KEY_256:
354+
return 32u;
355+
case HMAC_KEY_384:
356+
return 48u;
357+
case HMAC_KEY_512:
358+
return 64u;
359+
case HMAC_KEY_1024:
360+
return 128u;
361+
case HMAC_KEY_NONE:
362+
default:
363+
qemu_log_mask(LOG_GUEST_ERROR,
364+
"%s: Cannot get key size if it is not set. \n", __func__);
365+
return 0u;
366+
}
367+
}
368+
313369
static inline bool ot_hmac_key_length_supported(
314370
enum OtHMACDigestSize digest_size, enum OtHMACKeyLength key_length)
315371
{
@@ -344,8 +400,7 @@ static void ot_hmac_writeback_digest_state(OtHMACState *s)
344400
/* copy intermediary digest to mock HMAC operation for stop/continue
345401
behaviour. */
346402
/* TODO: add support for SHA2-384 and SHA2-512 */
347-
unsigned digest_length = OT_HMAC_DIGEST_LENGTH / sizeof(uint32_t);
348-
for (unsigned i = 0; i < digest_length; i++) {
403+
for (unsigned i = 0; i < 8u; i++) {
349404
STORE32H(s->ctx->state.sha256.state[i], s->regs->digest + i);
350405
}
351406
}
@@ -383,16 +438,22 @@ static void ot_hmac_compute_digest(OtHMACState *s)
383438
if (s->regs->cfg & R_CFG_HMAC_EN_MASK) {
384439
ot_hmac_sha_done(s);
385440

386-
uint64_t opad[8u];
441+
size_t key_length_b = ot_hmac_get_key_bytes(s);
442+
size_t block_size_b = ot_hmac_get_block_size_bytes(s);
443+
/* If the key is smaller than the block size, we must pad it to the
444+
right with 0s. */
445+
size_t pad_length_b = MAX(key_length_b, block_size_b);
446+
size_t pad_length_w = pad_length_b / sizeof(uint32_t);
447+
uint32_t opad[OT_HMAC_MAX_KEY_LENGTH / sizeof(uint32_t)];
387448
memset(opad, 0, sizeof(opad));
388-
memcpy(opad, s->regs->key, sizeof(s->regs->key));
389-
for (unsigned i = 0; i < ARRAY_SIZE(opad); i++) {
390-
opad[i] ^= 0x5c5c5c5c5c5c5c5cull;
449+
memcpy(opad, s->regs->key, key_length_b);
450+
for (unsigned i = 0; i < pad_length_w; i++) {
451+
opad[i] ^= 0x5c5c5c5cul;
391452
}
392453
ot_hmac_sha_init(s, false);
393-
ot_hmac_sha_process(s, (const uint8_t *)opad, sizeof(opad), false);
454+
ot_hmac_sha_process(s, (const uint8_t *)opad, pad_length_b, false);
394455
ot_hmac_sha_process(s, (const uint8_t *)s->regs->digest,
395-
sizeof(s->regs->digest), true);
456+
ot_hmac_get_digest_bytes(s), true);
396457
}
397458
ot_hmac_sha_done(s);
398459
}
@@ -736,13 +797,19 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
736797

737798
/* HMAC mode, process input padding */
738799
if (s->regs->cfg & R_CFG_HMAC_EN_MASK) {
739-
uint64_t ipad[8u];
800+
size_t key_length_b = ot_hmac_get_key_bytes(s);
801+
size_t block_size_b = ot_hmac_get_block_size_bytes(s);
802+
/* If the key is smaller than the block size, we must pad it to
803+
the right with 0s. */
804+
size_t pad_length_b = MAX(key_length_b, block_size_b);
805+
size_t pad_length_w = pad_length_b / sizeof(uint32_t);
806+
uint32_t ipad[OT_HMAC_MAX_KEY_LENGTH / sizeof(uint32_t)];
740807
memset(ipad, 0, sizeof(ipad));
741-
memcpy(ipad, s->regs->key, sizeof(s->regs->key));
742-
for (unsigned i = 0; i < ARRAY_SIZE(ipad); i++) {
743-
ipad[i] ^= 0x3636363636363636u;
808+
memcpy(ipad, s->regs->key, key_length_b);
809+
for (unsigned i = 0; i < pad_length_w; i++) {
810+
ipad[i] ^= 0x36363636ul;
744811
}
745-
ot_hmac_sha_process(s, (const uint8_t *)ipad, sizeof(ipad),
812+
ot_hmac_sha_process(s, (const uint8_t *)ipad, pad_length_b,
746813
true);
747814
}
748815
}
@@ -794,8 +861,7 @@ static void ot_hmac_regs_write(void *opaque, hwaddr addr, uint64_t value,
794861
/* Restore SHA256 context */
795862
s->ctx->state.sha256.curlen = 0;
796863
s->ctx->state.sha256.length = s->regs->msg_length;
797-
unsigned digest_length = OT_HMAC_DIGEST_LENGTH / sizeof(uint32_t);
798-
for (unsigned i = 0; i < digest_length; i++) {
864+
for (unsigned i = 0; i < 8u; i++) {
799865
s->ctx->state.sha256.state[i] = s->regs->digest[i];
800866
}
801867

0 commit comments

Comments
 (0)