Skip to content

Commit b99c478

Browse files
committed
[ot] hw/opentitan: ot_aes: fix IV updates in CFB mode
In AES CFB mode after a block operation the IV registers are updated with the ciphertext from the previous block operation. See: - https://opentitan.org/book/hw/ip/aes/doc/theory_of_operation.html#datapath-architecture-and-operation - https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_(CFB) LibTomCrypt does not provide this, so we just read it directly from our own data. Previously, we were using the updated IV value that LibTomCrypt provides, which is instead updated to be the output of the block operation (without the XOR with the plaintext). This fix allows the aes_functest to pass. Signed-off-by: Luís Marques <luismarques@lowrisc.org>
1 parent 3d24136 commit b99c478

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

hw/opentitan/ot_aes.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* QEMU OpenTitan AES device
33
*
44
* Copyright (c) 2022-2024 Rivos, Inc.
5+
* Copyright (c) 2025 lowRISC contributors.
56
*
67
* Author(s):
78
* Emmanuel Blot <eblot@rivosinc.com>
@@ -430,9 +431,11 @@ static void ot_aes_init_keyshare(OtAESState *s, bool randomize)
430431
OtAESRegisters *r = s->regs;
431432
OtAESContext *c = s->ctx;
432433

433-
trace_ot_aes_init("keyshare");
434434
if (randomize) {
435+
trace_ot_aes_init("keyshare init (randomize data)");
435436
ot_aes_randomize(s, r->keyshare, ARRAY_SIZE(r->keyshare));
437+
} else {
438+
trace_ot_aes_init("keyshare init (data preserved)");
436439
}
437440
bitmap_zero(r->keyshare_bm, (int64_t)(PARAM_NUM_REGS_KEY * 2u));
438441
c->key_ready = false;
@@ -443,9 +446,11 @@ static void ot_aes_init_iv(OtAESState *s, bool randomize)
443446
OtAESRegisters *r = s->regs;
444447
OtAESContext *c = s->ctx;
445448

446-
trace_ot_aes_init("iv");
447449
if (randomize) {
450+
trace_ot_aes_init("iv init (randomize data)");
448451
ot_aes_randomize(s, r->iv, ARRAY_SIZE(r->iv));
452+
} else {
453+
trace_ot_aes_init("iv init (data preserved)");
449454
}
450455
bitmap_zero(r->iv_bm, PARAM_NUM_REGS_IV);
451456
c->iv_ready = false;
@@ -873,13 +878,18 @@ static void ot_aes_process(OtAESState *s)
873878
c->di_full = false;
874879

875880
if (rc == CRYPT_OK) {
876-
/* IV registers are updated on each round */
881+
/*
882+
* IV registers are updated on each round. For details, see:
883+
* https://opentitan.org/book/hw/ip/aes/doc/theory_of_operation.html
884+
* https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
885+
*/
877886
switch (mode) {
878887
case AES_CBC:
879888
memcpy(c->iv, c->cbc.IV, sizeof(c->iv));
880889
break;
881890
case AES_CFB:
882-
memcpy(c->iv, c->cfb.IV, sizeof(c->iv));
891+
/* In CFB mode the next IV register value is the ciphertext */
892+
memcpy(c->iv, encrypt ? c->dst : c->src, sizeof(c->iv));
883893
break;
884894
case AES_OFB:
885895
memcpy(c->iv, c->ofb.IV, sizeof(c->iv));

0 commit comments

Comments
 (0)