5 #include "sw/device/lib/crypto/drivers/hmac.h"
11 #include "sw/device/lib/crypto/impl/status.h"
13 #include "hmac_regs.h"
17 #define MODULE_ID MAKE_MODULE_ID('d', 'h', 'm')
78 kNumIterTimeout = 200,
90 static status_t hmac_idle_wait(
void) {
94 uint32_t status_reg = 0;
95 uint32_t attempt_cnt = 0;
97 status_reg = abs_mmio_read32(kHmacBaseAddr + HMAC_STATUS_REG_OFFSET);
99 if (attempt_cnt >= kNumIterTimeout) {
100 return OTCRYPTO_FATAL_ERR;
106 abs_mmio_read32(kHmacBaseAddr + HMAC_INTR_STATE_REG_OFFSET);
108 return OTCRYPTO_FATAL_ERR;
112 abs_mmio_write32(kHmacBaseAddr + HMAC_INTR_STATE_REG_OFFSET, intr_reg);
126 static void hmac_hwip_clear(
void) {
128 uint32_t cfg_reg = abs_mmio_read32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET);
130 abs_mmio_write32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET, cfg_reg);
133 abs_mmio_write32(kHmacBaseAddr + HMAC_WIPE_SECRET_REG_OFFSET, UINT32_MAX);
147 static void key_write(
const uint32_t *key,
size_t key_wordlen) {
148 for (
size_t i = 0; i < key_wordlen; i++) {
149 abs_mmio_write32(kHmacBaseAddr + HMAC_KEY_0_REG_OFFSET + 4 * i, key[i]);
165 static void digest_read(uint32_t *digest,
size_t digest_wordlen) {
166 for (
size_t i = 0; i < digest_wordlen; i++) {
168 abs_mmio_read32(kHmacBaseAddr + HMAC_DIGEST_0_REG_OFFSET + 4 * i);
186 static void context_restore(
hmac_ctx_t *ctx) {
188 abs_mmio_write32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET, ctx->cfg_reg);
192 key_write(ctx->key, ctx->key_wordlen);
194 uint32_t cmd_reg = HMAC_CMD_REG_RESVAL;
196 if (ctx->hw_started) {
201 for (
size_t i = 0; i < kHmacMaxDigestWords; i++) {
202 abs_mmio_write32(kHmacBaseAddr + HMAC_DIGEST_0_REG_OFFSET + 4 * i,
205 abs_mmio_write32(kHmacBaseAddr + HMAC_MSG_LENGTH_LOWER_REG_OFFSET,
207 abs_mmio_write32(kHmacBaseAddr + HMAC_MSG_LENGTH_UPPER_REG_OFFSET,
216 uint32_t cfg_reg = abs_mmio_read32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET);
218 abs_mmio_write32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET, cfg_reg);
222 abs_mmio_write32(kHmacBaseAddr + HMAC_CMD_REG_OFFSET, cmd_reg);
236 digest_read(ctx->H, kHmacMaxDigestWords);
238 abs_mmio_read32(kHmacBaseAddr + HMAC_MSG_LENGTH_LOWER_REG_OFFSET);
240 abs_mmio_read32(kHmacBaseAddr + HMAC_MSG_LENGTH_UPPER_REG_OFFSET);
250 static void msg_fifo_write(
const uint8_t *message,
size_t message_len) {
256 abs_mmio_write8(kHmacBaseAddr + HMAC_MSG_FIFO_REG_OFFSET, message[i]);
260 for (; i +
sizeof(uint32_t) <= message_len; i +=
sizeof(uint32_t)) {
261 uint32_t next_word =
read_32(&message[i]);
262 abs_mmio_write32(kHmacBaseAddr + HMAC_MSG_FIFO_REG_OFFSET, next_word);
266 for (; i < message_len; i++) {
267 abs_mmio_write8(kHmacBaseAddr + HMAC_MSG_FIFO_REG_OFFSET, message[i]);
285 static status_t cfg_derive(hmac_mode_t hmac_mode, uint32_t *cfg_reg,
286 size_t *msg_block_bytelen,
size_t *digest_wordlen) {
287 *cfg_reg = HMAC_CFG_REG_RESVAL;
302 case kHmacModeHmac256:
305 HMAC_CFG_KEY_LENGTH_VALUE_KEY_512);
307 case kHmacModeSha256:
309 HMAC_CFG_DIGEST_SIZE_VALUE_SHA2_256);
310 *msg_block_bytelen = kHmacSha256BlockBytes;
311 *digest_wordlen = kHmacSha256DigestWords;
313 case kHmacModeHmac384:
316 HMAC_CFG_KEY_LENGTH_VALUE_KEY_1024);
318 case kHmacModeSha384:
320 HMAC_CFG_DIGEST_SIZE_VALUE_SHA2_384);
321 *msg_block_bytelen = kHmacSha512BlockBytes;
322 *digest_wordlen = kHmacSha384DigestWords;
324 case kHmacModeHmac512:
327 HMAC_CFG_KEY_LENGTH_VALUE_KEY_1024);
329 case kHmacModeSha512:
331 HMAC_CFG_DIGEST_SIZE_VALUE_SHA2_512);
332 *msg_block_bytelen = kHmacSha512BlockBytes;
333 *digest_wordlen = kHmacSha512DigestWords;
336 return OTCRYPTO_BAD_ARGS;
342 const uint32_t *key,
size_t key_wordlen) {
344 return OTCRYPTO_BAD_ARGS;
348 HARDENED_TRY(cfg_derive(hmac_mode, &ctx->cfg_reg, &ctx->msg_block_bytelen,
349 &ctx->digest_wordlen));
351 if (hmac_mode == kHmacModeHmac256 || hmac_mode == kHmacModeHmac384 ||
352 hmac_mode == kHmacModeHmac512) {
354 return OTCRYPTO_BAD_ARGS;
357 if (ctx->msg_block_bytelen != key_wordlen *
sizeof(uint32_t)) {
358 return OTCRYPTO_BAD_ARGS;
360 ctx->key_wordlen = key_wordlen;
361 for (
size_t i = 0; i < ctx->key_wordlen; i++) {
362 ctx->key[i] = key[i];
367 return OTCRYPTO_BAD_ARGS;
371 ctx->key_wordlen = 0;
375 ctx->partial_block_len = 0;
381 if (ctx == NULL || (data == NULL && len > 0)) {
382 return OTCRYPTO_BAD_ARGS;
389 if (ctx->partial_block_len + len < ctx->msg_block_bytelen) {
390 memcpy(ctx->partial_block + ctx->partial_block_len, data, len);
391 ctx->partial_block_len += len;
397 size_t leftover_len = (ctx->partial_block_len + len) % ctx->msg_block_bytelen;
404 context_restore(ctx);
407 msg_fifo_write(ctx->partial_block, ctx->partial_block_len);
410 msg_fifo_write(data, len - leftover_len);
416 abs_mmio_write32(kHmacBaseAddr + HMAC_CMD_REG_OFFSET, cmd_reg);
419 HARDENED_TRY(hmac_idle_wait());
426 memcpy(ctx->partial_block, data + len - leftover_len, leftover_len);
427 ctx->partial_block_len = leftover_len;
435 if (ctx == NULL || digest == NULL) {
436 return OTCRYPTO_BAD_ARGS;
440 if (ctx->digest_wordlen != digest_wordlen) {
441 return OTCRYPTO_BAD_ARGS;
450 context_restore(ctx);
453 msg_fifo_write(ctx->partial_block, ctx->partial_block_len);
458 abs_mmio_write32(kHmacBaseAddr + HMAC_CMD_REG_OFFSET, cmd_reg);
459 HARDENED_TRY(hmac_idle_wait());
461 digest_read(digest, ctx->digest_wordlen);
470 status_t hmac(
const hmac_mode_t hmac_mode,
const uint32_t *key,
471 size_t key_wordlen,
const uint8_t *data,
size_t len,
472 uint32_t *digest,
size_t digest_wordlen) {
473 if (data == NULL && len > 0) {
474 return OTCRYPTO_BAD_ARGS;
484 size_t derived_msg_block_bytelen;
485 size_t derived_digest_wordlen;
487 HARDENED_TRY(cfg_derive(hmac_mode, &cfg_reg, &derived_msg_block_bytelen,
488 &derived_digest_wordlen));
492 abs_mmio_write32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET, cfg_reg);
494 if (digest_wordlen != derived_digest_wordlen) {
495 return OTCRYPTO_BAD_ARGS;
498 if (hmac_mode == kHmacModeHmac256 || hmac_mode == kHmacModeHmac384 ||
499 hmac_mode == kHmacModeHmac512) {
501 derived_msg_block_bytelen != key_wordlen *
sizeof(uint32_t)) {
502 return OTCRYPTO_BAD_ARGS;
504 key_write(key, key_wordlen);
507 if (key != NULL || key_wordlen != 0) {
508 return OTCRYPTO_BAD_ARGS;
514 abs_mmio_write32(kHmacBaseAddr + HMAC_CFG_REG_OFFSET, cfg_reg);
518 abs_mmio_write32(kHmacBaseAddr + HMAC_CMD_REG_OFFSET, cmd_reg);
520 msg_fifo_write(data, len);
524 abs_mmio_write32(kHmacBaseAddr + HMAC_CMD_REG_OFFSET, cmd_reg);
527 HARDENED_TRY(hmac_idle_wait());
529 digest_read(digest, digest_wordlen);