Skip to content

Commit 6b0af3e

Browse files
committed
[ot] hw/opentitan: ot_random_src: rework interface and implementation
Get rid of the generation identifier. This mechanism had initially be implemented to verify early EarlGrey entropy source constraint, quoting: "CSRNG may only be enabled if ENTROPY_SRC is enabled. Once disabled, CSRNG may only be re-enabled after ENTROPY_SRC has been disabled and re-enabled." This constraint has been removed in recent EarlGrey implementations while Darjeeling implementation did not follow this constraint, as it did not make use of the entropy source IP. Generation number is therefore removed; get_random_generation API is no longer needed, neither is the genid argument of get_random_values. Error management can be simplified accordingly. Signed-off-by: Emmanuel Blot <eblot@rivosinc.com>
1 parent 45e4458 commit 6b0af3e

File tree

5 files changed

+26
-113
lines changed

5 files changed

+26
-113
lines changed

hw/opentitan/ot_ast_dj.c

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* QEMU OpenTitan Darjeeling Analog Sensor Top device
33
*
4-
* Copyright (c) 2023-2024 Rivos, Inc.
4+
* Copyright (c) 2023-2025 Rivos, Inc.
55
*
66
* Author(s):
77
* Emmanuel Blot <eblot@rivosinc.com>
@@ -152,26 +152,12 @@ struct OtASTDjState {
152152
/* Private implementation */
153153
/* -------------------------------------------------------------------------- */
154154

155-
static int ot_ast_dj_get_generation(OtRandomSrcIf *dev)
156-
{
157-
(void)dev;
158-
159-
return -1;
160-
}
161-
162-
static int ot_ast_dj_get_random(OtRandomSrcIf *dev, int genid,
163-
uint64_t random[OT_RANDOM_SRC_DWORD_COUNT],
164-
bool *fips)
155+
static int ot_ast_dj_get_random(
156+
OtRandomSrcIf *dev, uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], bool *fips)
165157
{
166158
OtASTDjState *s = OT_AST_DJ(dev);
167159
OtASTDjRandom *rnd = &s->random;
168160

169-
if (genid != -1) {
170-
qemu_log_mask(LOG_GUEST_ERROR, "%s: AST gennum mismatch req:%d\n",
171-
__func__, genid);
172-
return -2;
173-
}
174-
175161
if (!rnd->avail) {
176162
/* not ready */
177163
trace_ot_ast_no_entropy(0);
@@ -441,7 +427,6 @@ static void ot_ast_dj_class_init(ObjectClass *klass, void *data)
441427
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
442428

443429
OtRandomSrcIfClass *rdc = OT_RANDOM_SRC_IF_CLASS(klass);
444-
rdc->get_random_generation = &ot_ast_dj_get_generation;
445430
rdc->get_random_values = &ot_ast_dj_get_random;
446431
}
447432

hw/opentitan/ot_csrng.c

Lines changed: 12 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -343,12 +343,10 @@ struct OtCSRNGState {
343343
bool enabled;
344344
bool sw_app_granted;
345345
bool read_int_granted;
346-
bool es_available; /* guest warning if entropy power cycling is invalid */
347346
uint32_t scheduled_cmd;
348347
unsigned entropy_delay;
349348
unsigned es_retry_count;
350349
unsigned state_db_ix;
351-
int entropy_gennum;
352350
int aes_cipher; /* AES handle for tomcrypt */
353351
OtCSRNGFsmState state;
354352
OtCSRNGInstance *instances;
@@ -777,18 +775,6 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0)
777775
drng->seeded = false;
778776

779777
if (!flag0) {
780-
if (!s->es_available) {
781-
qemu_log_mask(LOG_GUEST_ERROR,
782-
"%s: Requesting entropy w/o power cycling ES\n",
783-
__func__);
784-
/*
785-
* Continue anyway as it seems HW does not enforce what is
786-
* documented. Force the flag so the warning message is only
787-
* shown once (it does not serve any other purpose).
788-
*/
789-
s->es_available = true;
790-
}
791-
792778
uint64_t buffer[OT_RANDOM_SRC_DWORD_COUNT];
793779
memset(buffer, 0, sizeof(buffer));
794780
unsigned len = drng->material_len * sizeof(uint32_t);
@@ -798,20 +784,21 @@ ot_csrng_drng_reseed(OtCSRNGInstance *inst, DeviceState *rand_dev, bool flag0)
798784
uint64_t entropy[OT_RANDOM_SRC_DWORD_COUNT];
799785
int res;
800786
bool fips;
801-
trace_ot_csrng_request_entropy(slot, s->entropy_gennum);
787+
trace_ot_csrng_request_entropy(slot);
802788
OtRandomSrcIfClass *cls = OT_RANDOM_SRC_IF_GET_CLASS(rand_dev);
803789
OtRandomSrcIf *randif = OT_RANDOM_SRC_IF(rand_dev);
804-
res = cls->get_random_values(randif, s->entropy_gennum, entropy, &fips);
805-
if (res) {
790+
res = cls->get_random_values(randif, entropy, &fips);
791+
792+
if (res < 0) {
793+
s->entropy_delay = 0;
794+
trace_ot_csrng_entropy_rejected(slot, "error", res);
795+
return CSRNG_CMD_STALLED;
796+
}
797+
798+
if (res > 0) {
806799
s->entropy_delay = (res > 1) ? (unsigned)res : 0;
807-
trace_ot_csrng_entropy_rejected(slot,
808-
res < 0 ? (res == -2 ? "stalled" :
809-
"error") :
810-
"not ready",
811-
res);
812-
return res < 0 ? (res == -2 ? CSRNG_CMD_STALLED :
813-
CSRNG_CMD_RESEED_CNT_EXCEEDED) :
814-
CSRNG_CMD_RETRY;
800+
trace_ot_csrng_entropy_rejected(slot, "not ready", res);
801+
return CSRNG_CMD_RETRY;
815802
}
816803

817804
/* always perform XOR which is a no-op if material_len is zero */
@@ -987,39 +974,11 @@ static void ot_csrng_release_hw_app(OtCSRNGInstance *inst)
987974

988975
static void ot_csrng_handle_enable(OtCSRNGState *s)
989976
{
990-
/*
991-
* As per EarlGrey 2.5.2-rc0:
992-
* "CSRNG may only be enabled if ENTROPY_SRC is enabled. CSRNG may only be
993-
* disabled if all EDNs are disabled. Once disabled, CSRNG may only be
994-
* re-enabled after ENTROPY_SRC has been disabled and re-enabled."
995-
*/
996-
OtRandomSrcIfClass *cls = OT_RANDOM_SRC_IF_GET_CLASS(s->random_src);
997-
OtRandomSrcIf *randif = OT_RANDOM_SRC_IF(s->random_src);
998-
999977
if (ot_csrng_is_ctrl_enabled(s)) {
1000978
xtrace_ot_csrng_info("enabling CSRNG", 0);
1001-
int gennum = cls->get_random_generation(randif);
1002-
if (gennum >= 0) {
1003-
/*
1004-
* however it is not re-enabling CSRNG w/o cycling the entropy_src
1005-
* that is prohibited, but to request entropy from it. The check is
1006-
* therefore deferred to the reseed handling which makes use of the
1007-
* entropy_src only if flag0 is not set.
1008-
*/
1009-
s->es_available = gennum > s->entropy_gennum;
1010-
xtrace_ot_csrng_info("enable: new ES generation", gennum);
1011-
} else {
1012-
/*
1013-
* tracking enablement/disablement order is not supported by the
1014-
* entropy source (such as on Darjeeling)
1015-
*/
1016-
s->es_available = true;
1017-
xtrace_ot_csrng_info("enable: no ES gen tracking", gennum);
1018-
}
1019979
s->enabled = true;
1020980
s->regs[R_SW_CMD_STS] |= R_SW_CMD_STS_CMD_RDY_MASK;
1021981
s->es_retry_count = ENTROPY_SRC_INITIAL_REQUEST_COUNT;
1022-
s->entropy_gennum = gennum;
1023982
}
1024983

1025984
if (ot_csrng_is_ctrl_disabled(s)) {
@@ -1040,8 +999,6 @@ static void ot_csrng_handle_enable(OtCSRNGState *s)
1040999
s->enabled = false;
10411000
s->regs[R_SW_CMD_STS] &= ~R_SW_CMD_STS_CMD_RDY_MASK;
10421001
s->es_retry_count = 0;
1043-
s->entropy_gennum = cls->get_random_generation(randif);
1044-
xtrace_ot_csrng_info("disable: last RS generation", s->entropy_gennum);
10451002

10461003
/* cancel any outstanding asynchronous request */
10471004
qemu_bh_cancel(s->cmd_scheduler);
@@ -2024,8 +1981,6 @@ static void ot_csrng_reset(DeviceState *dev)
20241981
s->regs[R_INT_STATE_READ_ENABLE] = 0x7u;
20251982
s->regs[R_MAIN_SM_STATE] = 0x4eu;
20261983
s->enabled = false;
2027-
s->es_available = false;
2028-
s->entropy_gennum = 0;
20291984
s->sw_app_granted = false;
20301985
s->read_int_granted = false;
20311986
s->es_retry_count = 0;

hw/opentitan/ot_entropy_src.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -473,23 +473,14 @@ static void ot_entropy_src_reset(DeviceState *dev);
473473
static void ot_entropy_src_update_alerts(OtEntropySrcState *s);
474474
static void ot_entropy_src_update_filler(OtEntropySrcState *s);
475475

476-
static int ot_entropy_src_get_generation(OtRandomSrcIf *dev)
476+
static int ot_entropy_src_get_random(
477+
OtRandomSrcIf *dev, uint64_t random[OT_RANDOM_SRC_DWORD_COUNT], bool *fips)
477478
{
478479
OtEntropySrcState *s = OT_ENTROPY_SRC(dev);
479480

480-
return ot_entropy_src_is_module_enabled(s) ? -1 : 0;
481-
}
482-
483-
static int ot_entropy_src_get_random(OtRandomSrcIf *dev, int genid,
484-
uint64_t random[OT_RANDOM_SRC_DWORD_COUNT],
485-
bool *fips)
486-
{
487-
OtEntropySrcState *s = OT_ENTROPY_SRC(dev);
488-
(void)genid; /* accept any generation identifier */
489-
490481
if (!ot_entropy_src_is_module_enabled(s)) {
491482
qemu_log_mask(LOG_GUEST_ERROR, "%s: entropy_src is down\n", __func__);
492-
return -2;
483+
return -1;
493484
}
494485

495486
bool fips_compliant;
@@ -1653,7 +1644,6 @@ static void ot_entropy_src_class_init(ObjectClass *klass, void *data)
16531644
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
16541645

16551646
OtRandomSrcIfClass *rdc = OT_RANDOM_SRC_IF_CLASS(klass);
1656-
rdc->get_random_generation = &ot_entropy_src_get_generation;
16571647
rdc->get_random_values = &ot_entropy_src_get_random;
16581648
}
16591649

hw/opentitan/trace-events

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ ot_csrng_irqs(uint32_t active, uint32_t mask, uint32_t eff) "act:0x%08x msk:0x%0
8383
ot_csrng_push_command(unsigned slot, const char *cmd, unsigned acmd, char code, unsigned len) "#%u: %s(%u) %clen: %u"
8484
ot_csrng_read_state_db(unsigned slot, unsigned pos, uint32_t val) "#%u [%u] = 0x%08x"
8585
ot_csrng_reject_command(unsigned slot, uint32_t command, int res) "#%u: cmd: 0x%08x res: %d"
86-
ot_csrng_request_entropy(unsigned slot, int gen) "#%u gen %d"
86+
ot_csrng_request_entropy(unsigned slot) "#%u"
8787
ot_csrng_reset(void) ""
8888
ot_csrng_retry_es_init(unsigned retry_count) "rescheduling initial ES request: %u to go"
8989
ot_csrng_schedule(unsigned slot, const char *kind) "#%u: %s"

include/hw/opentitan/ot_random_src.h

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
/*
22
* QEMU OpenTitan Random Source interface
33
*
4-
* Copyright (c) 2023 Rivos, Inc.
4+
* Copyright (c) 2023-2024 Rivos, Inc.
5+
* Copyright (c) 2025 lowRISC contributors.
6+
*
57
*
68
* Author(s):
79
* Emmanuel Blot <eblot@rivosinc.com>
@@ -48,39 +50,20 @@ typedef struct OtRandomSrcIf OtRandomSrcIf;
4850
struct OtRandomSrcIfClass {
4951
InterfaceClass parent_class;
5052

51-
/*
52-
* Tell whether the random source is available, i.e. whether the random
53-
* source module has been enabled.
54-
*
55-
* @dev the random source instance
56-
* @return 0 if the random_src is disabled, otherwise:
57-
* * a positive, monotonic increase generation number which indicates the
58-
* number of time the random_src has been cycled (enabled from a
59-
* disable state). This generation identifier should be passed on any
60-
* subsequent #get_random_values request, or
61-
* * a negative number, which indicates that the random source is enabled,
62-
* but the generation number should be simply ignored.
63-
*/
64-
int (*get_random_generation)(OtRandomSrcIf *dev);
65-
6653
/*
6754
* Fill up a buffer with random values
6855
*
6956
* @dev the random source instance
70-
* @genid the generation identifier, from #get_random_generation
7157
* @random the buffer to fill in with random data
7258
* @fips on success, updated to @true if random data are FIPS-compliant
7359
* @return 0 on success,
74-
* >=1 if the source is initializing, if >1, indicates the hint on
75-
* how many ns to wait before retrying,
60+
* >=1 if the random source is still initializing or not enough
61+
* entropy is available to fill the output buffer;
62+
* if >1, indicates a hint on how many ns to wait before retrying,
7663
* -1 if the random source is not available, i.e. if the module is
7764
* not enabled or if the selected route is not the HW one,
78-
* -2 if the generation ID does not match and execution cannot
79-
* process any further, 1 if the random source is still
80-
* initializing or not enough entropy is available to fill the
81-
* output buffer.
8265
*/
83-
int (*get_random_values)(OtRandomSrcIf *dev, int genid,
66+
int (*get_random_values)(OtRandomSrcIf *dev,
8467
uint64_t random[OT_RANDOM_SRC_DWORD_COUNT],
8568
bool *fips);
8669
};

0 commit comments

Comments
 (0)