Skip to content

Commit df3477b

Browse files
committed
[sw,rom_ext] Support incremental squeeze in kmac driver
This patch exports the `kmac_squeeze_words` and `kmac_done` functions from the kmac driver to allow caller to squeeze an arbitrary number of words from the Keccak state incrementally. Also, adds `kmac_shake128_configure` to support SHAKE-128 configuration. Signed-off-by: Yi-Hsuan Deng <yhdeng@google.com> Change-Id: Ide996b205dcd4cf41425571315cd0b496a6a6964
1 parent b51ae48 commit df3477b

2 files changed

Lines changed: 87 additions & 11 deletions

File tree

sw/device/silicon_creator/lib/drivers/kmac.c

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ typedef struct kmac_config {
8989
* The algorithm: SHA3, SHAKE or cSHAKE
9090
*/
9191
uint8_t mode;
92+
/**
93+
* Hashing strength: L128, L224, L256, L384 or L512
94+
*/
95+
uint8_t kstrength;
9296
} kmac_config_t;
9397

9498
/**
@@ -173,9 +177,9 @@ static rom_error_t kmac_configure(kmac_config_t config) {
173177
// poll `STATUS.fifo_depth` to avoid a specific EDN-KMAC-Ibex deadlock
174178
// scenario. See `absorb()` and the KMAC documentation for details.
175179
cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, 0);
176-
// Set `CFG.KSTRENGTH` field to 256-bit strength.
180+
// Set `CFG.KSTRENGTH` field.
177181
cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
178-
KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256);
182+
config.kstrength);
179183
// Set `CFG.MODE` field to SHAKE.
180184
cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
181185
config.mode);
@@ -246,6 +250,7 @@ rom_error_t kmac_keymgr_configure(void) {
246250
.sideload = true,
247251
.kmac_en = false,
248252
.mode = KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE,
253+
.kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256,
249254
});
250255
}
251256

@@ -257,6 +262,7 @@ rom_error_t kmac_kmac256_sw_configure(void) {
257262
.sideload = false,
258263
.kmac_en = true,
259264
.mode = KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE,
265+
.kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256,
260266
});
261267
}
262268

@@ -268,6 +274,18 @@ rom_error_t kmac_kmac256_hw_configure(void) {
268274
.sideload = true,
269275
.kmac_en = true,
270276
.mode = KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE,
277+
.kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256,
278+
});
279+
}
280+
281+
rom_error_t kmac_shake128_configure(void) {
282+
return kmac_configure((kmac_config_t){
283+
.entropy_fast_process = false,
284+
.msg_mask = false,
285+
.sideload = false,
286+
.kmac_en = false,
287+
.mode = KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE,
288+
.kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128,
271289
});
272290
}
273291

@@ -278,6 +296,7 @@ rom_error_t kmac_shake256_configure(void) {
278296
.sideload = false,
279297
.kmac_en = false,
280298
.mode = KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE,
299+
.kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256,
281300
});
282301
}
283302

@@ -350,20 +369,26 @@ void kmac_shake256_squeeze_start(void) {
350369
}
351370

352371
rom_error_t kmac_shake256_squeeze_end(uint32_t *out, size_t outlen) {
372+
HARDENED_RETURN_IF_ERROR(
373+
kmac_squeeze_words(out, outlen, kShake256KeccakRateWords));
374+
return kmac_done();
375+
}
376+
377+
rom_error_t kmac_squeeze_words(uint32_t *out, size_t out_words,
378+
size_t rate_words) {
353379
size_t idx = 0;
354-
while (launder32(idx) < outlen) {
355-
// Since we always read in increments of the SHAKE-256 rate, the index at
356-
// start should always be a multiple of the rate.
357-
HARDENED_CHECK_EQ(idx % kShake256KeccakRateWords, 0);
380+
while (launder32(idx) < out_words) {
381+
// Since we always read in increments of the rate, the index at the start
382+
// of each squeeze cycle must be a multiple of the rate.
383+
HARDENED_CHECK_EQ(idx % rate_words, 0);
358384

359385
// Poll the status register until in the 'squeeze' state.
360386
HARDENED_RETURN_IF_ERROR(poll_state(KMAC_STATUS_SHA3_SQUEEZE_BIT));
361387

362388
// Read words from the state registers (either `outlen` or the maximum
363389
// number of words available).
364390
size_t offset = 0;
365-
for (; launder32(idx) < outlen && offset < kShake256KeccakRateWords;
366-
++offset) {
391+
for (; launder32(idx) < out_words && offset < rate_words; ++offset) {
367392
uint32_t share0 =
368393
abs_mmio_read32(kAddrStateShare0 + offset * sizeof(uint32_t));
369394
uint32_t share1 =
@@ -372,15 +397,18 @@ rom_error_t kmac_shake256_squeeze_end(uint32_t *out, size_t outlen) {
372397
++idx;
373398
}
374399

375-
if (launder32(offset) == kShake256KeccakRateWords) {
400+
if (launder32(offset) == rate_words) {
376401
// If we read all the remaining words, issue `CMD.RUN` to generate more
377402
// state.
378-
HARDENED_CHECK_EQ(offset, kShake256KeccakRateWords);
403+
HARDENED_CHECK_EQ(offset, rate_words);
379404
issue_command(KMAC_CMD_CMD_VALUE_RUN);
380405
}
381406
}
382-
HARDENED_CHECK_EQ(idx, outlen);
407+
HARDENED_CHECK_EQ(idx, out_words);
408+
return kErrorOk;
409+
}
383410

411+
rom_error_t kmac_done(void) {
384412
// Poll the status register until in the 'squeeze' state.
385413
HARDENED_RETURN_IF_ERROR(poll_state(KMAC_STATUS_SHA3_SQUEEZE_BIT));
386414

@@ -390,6 +418,13 @@ rom_error_t kmac_shake256_squeeze_end(uint32_t *out, size_t outlen) {
390418
return kErrorOk;
391419
}
392420

421+
bool kmac_is_squeezing(void) {
422+
uint32_t status = abs_mmio_read32(kBase + KMAC_STATUS_REG_OFFSET);
423+
bool sha3_idle = bitfield_bit32_read(status, KMAC_STATUS_SHA3_IDLE_BIT);
424+
bool sha3_absorb = bitfield_bit32_read(status, KMAC_STATUS_SHA3_ABSORB_BIT);
425+
return !sha3_idle && !sha3_absorb;
426+
}
427+
393428
#define WORD_BITS (sizeof(uint32_t) * 8)
394429
#define KEY_CASE(x_) \
395430
case x_ / WORD_BITS: \

sw/device/silicon_creator/lib/drivers/kmac.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ rom_error_t kmac_kmac256_sw_configure(void);
4444
*/
4545
rom_error_t kmac_kmac256_hw_configure(void);
4646

47+
/**
48+
* Configure the KMAC block at startup for SHAKE-128 operation.
49+
*
50+
* Sets the KMAC block to use software entropy and sets the mode to SHAKE-128.
51+
*
52+
* @return Error code indicating if the operation succeeded.
53+
*/
54+
OT_WARN_UNUSED_RESULT
55+
rom_error_t kmac_shake128_configure(void);
56+
4757
/**
4858
* Configure the KMAC block at startup.
4959
*
@@ -145,6 +155,37 @@ void kmac_shake256_squeeze_start(void);
145155
OT_WARN_UNUSED_RESULT
146156
rom_error_t kmac_shake256_squeeze_end(uint32_t *out, size_t outlen);
147157

158+
/**
159+
* Squeeze arbitrary number of words from the Keccak state.
160+
*
161+
* This function will read out_words from the Keccak state, and if necessary
162+
* triggers additional hardware permutation runs using the rate_words.
163+
* Unlike squeeze_end, it does not mark the operation as DONE.
164+
*
165+
* @param out Output buffer.
166+
* @param out_words Desired length of output in 32-bit words.
167+
* @param rate_words Keccak rate in 32-bit words.
168+
* @return Error code indicating if the operation succeeded.
169+
*/
170+
OT_WARN_UNUSED_RESULT
171+
rom_error_t kmac_squeeze_words(uint32_t *out, size_t out_words,
172+
size_t rate_words);
173+
174+
/**
175+
* End the squeeze phase and release the KMAC hardware block.
176+
*
177+
* @return Error code indicating if the operation succeeded.
178+
*/
179+
OT_WARN_UNUSED_RESULT
180+
rom_error_t kmac_done(void);
181+
182+
/**
183+
* Check if the KMAC block is in the squeezing phase.
184+
*
185+
* @return True if KMAC is squeezing, false otherwise.
186+
*/
187+
bool kmac_is_squeezing(void);
188+
148189
/**
149190
* Load an unmasked software key into KMAC.
150191
*

0 commit comments

Comments
 (0)