Skip to content

Commit

Permalink
[aes_gcm,sca] Allow setting IV or key as FvsR
Browse files Browse the repository at this point in the history
WIth this commit, ot-sca can decide whether the key OR
the IV is FvsR. For the other one, random input is generated.

Signed-off-by: Pascal Nasahl <[email protected]>
  • Loading branch information
nasahlpa committed Jan 20, 2025
1 parent 4291748 commit 317fd46
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 19 deletions.
60 changes: 41 additions & 19 deletions sw/device/tests/penetrationtests/firmware/sca/aes_sca.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,8 @@ status_t handle_aes_sca_gcm_fvsr_batch(ujson_t *uj) {
// Receive the AES-GCM input data over uJSON.
aes_sca_num_ops_t uj_num_ops;
aes_sca_gcm_triggers_t uj_triggers;
aes_sca_block_t uj_iv;
aes_sca_key_t uj_key;
aes_sca_gcm_iv_key_t uj_fvsr;
aes_sca_key_t uj_key_iv;
aes_sca_num_blocks_t uj_aad_blocks;
aes_sca_num_blocks_t uj_ptx_blocks;
aes_sca_block_t uj_aad[kMaxGcmBlocks];
Expand All @@ -891,9 +891,12 @@ status_t handle_aes_sca_gcm_fvsr_batch(ujson_t *uj) {
// uj_triggers.triggers[3] = True/False - process TAG block.
// uj_triggers.block = int - which AAD or PTX block is captured?
TRY(ujson_deserialize_aes_sca_gcm_triggers_t(uj, &uj_triggers));
// Get fixed IV and fixed KEY.
TRY(ujson_deserialize_aes_sca_block_t(uj, &uj_iv));
TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key));
// Determine whether the IV or the key is FvsR.
// True: FvsR
// False: Random
TRY(ujson_deserialize_aes_sca_gcm_iv_key_t(uj, &uj_fvsr));
// Get fixed IV or key.
TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_iv));
// Get number of AAD and PTX blocks we are expecting.
TRY(ujson_deserialize_aes_sca_num_blocks_t(uj, &uj_aad_blocks));
TRY(ujson_deserialize_aes_sca_num_blocks_t(uj, &uj_ptx_blocks));
Expand All @@ -910,28 +913,47 @@ status_t handle_aes_sca_gcm_fvsr_batch(ujson_t *uj) {
TRY(ujson_deserialize_aes_sca_block_t(uj, &uj_ptx[it]));
}

// Prepare fixed AES IV.
dif_aes_iv_t aes_iv_fixed;
memset(aes_iv_fixed.iv, 0, 16);
memcpy(aes_iv_fixed.iv, uj_iv.block, uj_iv.num_valid_bytes);

// Generate Fvsr AES IV & key set.
// Generate FvsR key and random IV.
dif_aes_iv_t aes_iv_fvsr[kNumBatchOpsMax];
uint8_t batch_keys[kNumBatchOpsMax][kAesKeyLength];
bool sample_fixed = true;
// Either the IV or the key can be FvsR. The other one is random.
bool random_iv = !uj_fvsr.fvsr[0];
bool random_key = !uj_fvsr.fvsr[1];
bool fvsr_iv = uj_fvsr.fvsr[0];
bool fvsr_key = uj_fvsr.fvsr[1];
for (size_t it = 0; it < uj_num_ops.num_batch_ops; it++) {
memset(aes_iv_fvsr[it].iv, 0, 16);
memset(batch_keys[it], 0, kAesKeyLength);
if (sample_fixed) {
memcpy(aes_iv_fvsr[it].iv, aes_iv_fixed.iv, uj_iv.num_valid_bytes);
memcpy(batch_keys[it], uj_key.key, uj_key.key_length);
} else {

// Check whether key OR iv is Fvsr. The other one is random.
if (random_iv) {
// Generate random IV.
uint8_t rand_iv[16];
prng_rand_bytes(rand_iv, 16);
memcpy(aes_iv_fvsr[it].iv, rand_iv, uj_iv.num_valid_bytes);
memcpy(aes_iv_fvsr[it].iv, rand_iv, uj_key_iv.key_length);
} else if (random_key) {
// Generate random key.
prng_rand_bytes(batch_keys[it], uj_key.key_length);
prng_rand_bytes(batch_keys[it], uj_key_iv.key_length);
}

// Generate FvsR key or IV.
if (sample_fixed) {
// For the fixed set, take the IV or key received over uJSON.
if (fvsr_iv) {
memcpy(aes_iv_fvsr[it].iv, uj_key_iv.key, uj_key_iv.key_length);
} else if (fvsr_key) {
memcpy(batch_keys[it], uj_key_iv.key, uj_key_iv.key_length);
}
} else {
// For the random set, generate a random IV or key.
if (fvsr_iv) {
uint8_t rand_iv[16];
prng_rand_bytes(rand_iv, 16);
memcpy(aes_iv_fvsr[it].iv, rand_iv, uj_key_iv.key_length);
} else if (fvsr_key) {
prng_rand_bytes(batch_keys[it], uj_key_iv.key_length);
}
}
sample_fixed = prng_rand_uint32() & 0x1;
}
Expand All @@ -943,14 +965,14 @@ status_t handle_aes_sca_gcm_fvsr_batch(ujson_t *uj) {
memset(key_fvsr[it].share1, 0, sizeof(key_fvsr[it].share1));

// Mask the provided key.
for (int i = 0; i < uj_key.key_length / 4; ++i) {
for (int i = 0; i < kAesKeyLength / 4; ++i) {
key_fvsr[it].share1[i] = pentest_non_linear_layer(
pentest_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking)));
key_fvsr[it].share0[i] =
*((uint32_t *)batch_keys[it] + i) ^ key_fvsr[it].share1[i];
}
// Provide random shares for unused key bits.
for (size_t i = uj_key.key_length / 4; i < kAesKeyLengthMax / 4; ++i) {
for (size_t i = kAesKeyLength / 4; i < kAesKeyLengthMax / 4; ++i) {
key_fvsr[it].share1[i] =
pentest_non_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking));
key_fvsr[it].share0[i] =
Expand Down
4 changes: 4 additions & 0 deletions sw/device/tests/penetrationtests/json/aes_sca_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ UJSON_SERDE_STRUCT(CryptotestAesScaBlock, aes_sca_block_t, AES_SCA_BLOCK);
field(block, size_t)
UJSON_SERDE_STRUCT(CryptotestAesScaGcmTriggers, aes_sca_gcm_triggers_t, AES_SCA_GCM_TRIGGERS);

#define AES_SCA_GCM_IV_KEY(field, string) \
field(fvsr, bool, 2)
UJSON_SERDE_STRUCT(CryptotestAesScaGcmIvKey, aes_sca_gcm_iv_key_t, AES_SCA_GCM_IV_KEY);

#define AES_SCA_NUM_OPS(field, string) \
field(num_batch_ops, size_t)
UJSON_SERDE_STRUCT(CryptotestAesScaNumOps, aes_sca_num_ops_t, AES_SCA_NUM_OPS);
Expand Down

0 comments on commit 317fd46

Please sign in to comment.