Skip to content

Commit 5d6ba55

Browse files
committed
[crypto/entropy] Avoid infinite polls
Add timeouts to all polling of registers. This is just to add reliability in situations where the chips experiences a malfunction. Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent a1b143b commit 5d6ba55

File tree

1 file changed

+57
-7
lines changed

1 file changed

+57
-7
lines changed

sw/device/lib/crypto/drivers/entropy.c

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ enum {
3434
* CSRNG genbits buffer size in uint32_t words.
3535
*/
3636
kEntropyCsrngBitsBufferNumWords = 4,
37+
38+
// Fast timeout for checking if hardware is ready to accept a command word
39+
kEntropyPollReadyTimeout = 100,
40+
// Longer timeout for waiting for a command to finish executing
41+
kEntropyPollCmdDoneTimeout = 1000000,
42+
// Timeout for waiting for GenBits to become valid
43+
kEntropyPollGenBitsTimeout = 131071,
3744
};
3845

3946
/**
@@ -362,10 +369,15 @@ static status_t csrng_send_app_cmd(uint32_t base_address,
362369
if ((cmd_type == kEntropyCsrngSendAppCmdTypeCsrng) ||
363370
(cmd_type == kEntropyCsrngSendAppCmdTypeEdnSw)) {
364371
// Wait for the status register to be ready to accept the next command.
372+
uint32_t timeout = kEntropyPollReadyTimeout;
365373
do {
366374
reg = abs_mmio_read32(sts_reg_addr);
367375
ready = bitfield_bit32_read(reg, rdy_bit_offset);
368-
} while (!ready);
376+
} while (!ready && --timeout);
377+
378+
if (timeout == 0) {
379+
return OTCRYPTO_RECOV_ERR;
380+
}
369381
}
370382

371383
#define ENTROPY_CMD(m, i) ((bitfield_field32_t){.mask = m, .index = i})
@@ -420,10 +432,15 @@ static status_t csrng_send_app_cmd(uint32_t base_address,
420432
// SW register of EDN, respectively.
421433
if (cmd_type == kEntropyCsrngSendAppCmdTypeCsrng ||
422434
cmd_type == kEntropyCsrngSendAppCmdTypeEdnSw) {
435+
uint32_t timeout = kEntropyPollReadyTimeout;
423436
do {
424437
reg = abs_mmio_read32(sts_reg_addr);
425438
ready = bitfield_bit32_read(reg, reg_rdy_bit_offset);
426-
} while (!ready);
439+
} while (!ready && --timeout);
440+
441+
if (timeout == 0) {
442+
return OTCRYPTO_RECOV_ERR;
443+
}
427444
}
428445
abs_mmio_write32(cmd_reg_addr, cmd.seed_material->data[i]);
429446
}
@@ -433,17 +450,32 @@ static status_t csrng_send_app_cmd(uint32_t base_address,
433450
// The Generate command is complete only after all entropy bits have been
434451
// consumed. Thus poll the register that indicates if entropy bits are
435452
// available.
453+
uint32_t timeout = kEntropyPollGenBitsTimeout;
436454
do {
437455
reg = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_VLD_REG_OFFSET);
438-
} while (!bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT));
456+
} while (!bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT) &&
457+
--timeout);
458+
459+
if (timeout == 0) {
460+
return OTCRYPTO_RECOV_ERR;
461+
}
439462

440463
} else {
441464
// The non-Generate commands complete earlier, so poll the "command
442465
// request done" interrupt bit. Once it is set, the "status" bit is
443466
// updated.
467+
uint32_t timeout = (cmd.id == kEntropyDrbgOpInstantiate)
468+
? kEntropyPollCmdDoneTimeout
469+
: kEntropyPollReadyTimeout;
444470
do {
445471
reg = abs_mmio_read32(kBaseCsrng + CSRNG_INTR_STATE_REG_OFFSET);
446-
} while (!bitfield_bit32_read(reg, CSRNG_INTR_STATE_CS_CMD_REQ_DONE_BIT));
472+
} while (
473+
!bitfield_bit32_read(reg, CSRNG_INTR_STATE_CS_CMD_REQ_DONE_BIT) &&
474+
--timeout);
475+
476+
if (timeout == 0) {
477+
return OTCRYPTO_RECOV_ERR;
478+
}
447479

448480
// Check the "status" bit, which will be 0 unless there was an error.
449481
reg = abs_mmio_read32(kBaseCsrng + CSRNG_SW_CMD_STS_REG_OFFSET);
@@ -458,9 +490,15 @@ static status_t csrng_send_app_cmd(uint32_t base_address,
458490
// entropy is consumed. Thus the acknowledgement bit shall only be polled
459491
// for non-generate commands.
460492
if (cmd.id != kEntropyDrbgOpGenerate) {
493+
uint32_t timeout = kEntropyPollCmdDoneTimeout;
461494
do {
462495
reg = abs_mmio_read32(sts_reg_addr);
463-
} while (!bitfield_bit32_read(reg, EDN_SW_CMD_STS_CMD_ACK_BIT));
496+
} while (!bitfield_bit32_read(reg, EDN_SW_CMD_STS_CMD_ACK_BIT) &&
497+
--timeout);
498+
499+
if (timeout == 0) {
500+
return OTCRYPTO_RECOV_ERR;
501+
}
464502

465503
// Check the "status" bit, which will be 0 unless there was an error.
466504
if (bitfield_field32_read(reg, CSRNG_SW_CMD_STS_CMD_STS_FIELD)) {
@@ -533,9 +571,14 @@ static void edn_stop(uint32_t edn_address) {
533571
OT_WARN_UNUSED_RESULT
534572
static status_t edn_ready_block(uint32_t edn_address) {
535573
uint32_t reg;
574+
uint32_t timeout = kEntropyPollReadyTimeout;
536575
do {
537576
reg = abs_mmio_read32(edn_address + EDN_SW_CMD_STS_REG_OFFSET);
538-
} while (!bitfield_bit32_read(reg, EDN_SW_CMD_STS_CMD_RDY_BIT));
577+
} while (!bitfield_bit32_read(reg, EDN_SW_CMD_STS_CMD_RDY_BIT) && --timeout);
578+
579+
if (timeout == 0) {
580+
return OTCRYPTO_RECOV_ERR;
581+
}
539582

540583
if (bitfield_field32_read(reg, CSRNG_SW_CMD_STS_CMD_STS_FIELD)) {
541584
return OTCRYPTO_RECOV_ERR;
@@ -965,9 +1008,16 @@ status_t entropy_csrng_generate_data_get(uint32_t *buf, size_t len,
9651008
// Block until there is more data available in the genbits buffer. CSRNG
9661009
// generates data in 128bit chunks (i.e. 4 words).
9671010
uint32_t reg;
1011+
uint32_t timeout = kEntropyPollGenBitsTimeout;
1012+
9681013
do {
9691014
reg = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_VLD_REG_OFFSET);
970-
} while (!bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT));
1015+
} while (!bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT) &&
1016+
--timeout);
1017+
1018+
if (timeout == 0) {
1019+
return OTCRYPTO_RECOV_ERR;
1020+
}
9711021

9721022
if (fips_check != kHardenedBoolFalse &&
9731023
!bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_FIPS_BIT)) {

0 commit comments

Comments
 (0)