Skip to content

Commit

Permalink
[sca] Add fvsr Data mode to aes_serial
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Rozic <[email protected]>
  • Loading branch information
vrozic committed Jan 12, 2024
1 parent 2f67fda commit 686ef97
Showing 1 changed file with 121 additions and 18 deletions.
139 changes: 121 additions & 18 deletions sw/device/sca/aes_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ static uint8_t key_random[kAesTextLength] = {0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
*/
static uint8_t ciphertext_temp[kAesTextLength];

/**
* Prng state
*/
static uint8_t prng_state[kAesTextLength];

/**
* batch_plaintext for batch capture to initially set it using command.
*/
Expand Down Expand Up @@ -298,6 +303,14 @@ static void aes_serial_single_encrypt(const uint8_t *plaintext,
aes_send_ciphertext(false);
}

/**
* Advances PRNG to determine the order of measurements for fvsr-data TVLA
*/
static void aes_serial_advance_prng(void) {
aes_sw_encrypt_block(prng_state, kKeyGenRoundKeys, ciphertext_temp);
memcpy(prng_state, ciphertext_temp, kAesTextLength);
}

/**
* Advances data for fvsr-key TVLA - fixed set
*
Expand All @@ -322,6 +335,17 @@ static void aes_serial_advance_random(void) {
memcpy(key_random, ciphertext_temp, kAesTextLength);
}

/**
* Advances data for fvsr-data TVLA - random set
*
* This function updates plaintext_random for fvsr-data and
* TVLA, according to DTR recommendations, Section 5.1.
*/
static void aes_serial_advance_random_data(void) {
aes_sw_encrypt_block(plaintext_random, kKeyGenRoundKeys, ciphertext_temp);
memcpy(plaintext_random, ciphertext_temp, kAesTextLength);
}

/**
* Simple serial 'b' (batch encrypt) command handler.
*
Expand Down Expand Up @@ -529,20 +553,13 @@ static void aes_serial_fvsr_key_batch_generate(const uint8_t *data,
* https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf
* The measurements are taken by using either fixed or randomly selected keys.
* In order to simplify the analysis, the first encryption has to use fixed key.
* In addition, a PRNG is used for random key and plaintext generation instead
* of AES algorithm as specified in the TVLA DTR.
* This minimizes the overhead of UART communication and significantly improves
* the capture rate. The host must use the same PRNG to be able to compute the
* random plaintext, random key and the ciphertext of each trace.
* the capture rate.
*
* Packet payload must be a `uint32_t` representation of the number of
* encryptions to perform. Number of operations of a batch should not be greater
* than the 'kNumBatchOpsMax' value.
*
* The PRNG should be initialized using the 's' (seed PRNG) command before
* starting batch encryption. In addition, the fixed key should also be set
* using 't' (fvsr key set) command before starting batch encryption.
*
* Note that the host can partially verify this operation by checking the
* contents of the 'r' (last ciphertext) packet that is sent at the end of every
* batch.
Expand Down Expand Up @@ -572,6 +589,63 @@ static void aes_serial_fvsr_key_batch_encrypt(const uint8_t *data,
aes_serial_fvsr_key_batch_generate(data, data_len);
}

/**
* Simple serial 'h' (fixed vs random data batch encrypt) command handler.
*
* This command is designed to maximize the capture rate for side-channel
* attacks. Instead of expecting a plaintext and sending the resulting
* ciphertext from and to the host for each encryption, this command repeatedly
* encrypts plaintexts that are generated on the device. The data
* collection method is based on the derived test requirements (DTR) for TVLA:
* https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf
* The measurements are taken by using either fixed or randomly selected plaintexts.
* In order to simplify the analysis, the first encryption has to use fixed plaintext.
* This minimizes the overhead of UART communication and significantly improves
* the capture rate. The host must use the same PRNG to be able to compute the
* random plaintext and the ciphertext of each trace.
*
* Packet payload must be a `uint32_t` representation of the number of
* encryptions to perform. Number of operations of a batch should not be greater
* than the 'kNumBatchOpsMax' value.
*
* Note that the host can partially verify this operation by checking the
* contents of the 'r' (last ciphertext) packet that is sent at the end of every
* batch.
*
* @param data Packet payload.
* @param data_len Packet payload length.
*/
static void aes_serial_fvsr_data_batch_encrypt(const uint8_t *data,
size_t data_len) {
uint32_t num_encryptions = 0;
SS_CHECK(data_len == sizeof(num_encryptions));
num_encryptions = read_32(data);
SS_CHECK(num_encryptions <= kNumBatchOpsMax);

for (uint32_t i = 0; i < num_encryptions; ++i) {
if (sample_fixed) {
memcpy(batch_keys[i], key_fixed, kAesKeyLength);
memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength);
} else {
memcpy(batch_keys[i], key_random, kAesKeyLength);
memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength);
aes_serial_advance_random_data();
}
sample_fixed = prng_state[0] & 0x1;
aes_serial_advance_prng();
}

sca_set_trigger_high();
for (uint32_t i = 0; i < num_encryptions; ++i) {
aes_key_mask_and_config(batch_keys[i], kAesKeyLength);
aes_encrypt(batch_plaintexts[i], kAesTextLength);
}
sca_set_trigger_low();

// Only send the first word to increase capture rate
aes_send_ciphertext(true);
}

/**
* Simple serial 'l' (seed lfsr) command handler.
*
Expand Down Expand Up @@ -607,24 +681,52 @@ static void aes_serial_set_default_values(const uint8_t *data,
SS_CHECK(data_len == sizeof(uint32_t));
uint32_t command = 0;
command = read_32(data);
static const uint8_t kPlaintextFixedStart[kAesTextLength] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
static const uint8_t kKeyFixedStart[kAesTextLength] = {
// Staring constants for fixed-vs-random key, DTR Section 5.3
static const uint8_t kPlaintextFixedStartFvsrKey[kAesTextLength] = {
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
static const uint8_t kKeyFixedStartFvsrKey[kAesTextLength] = {
0x81, 0x1E, 0x37, 0x31, 0xB0, 0x12, 0x0A, 0x78,
0x42, 0x78, 0x1E, 0x22, 0xB2, 0x5C, 0xDD, 0xF9};
static const uint8_t kPlaintextRandomStart[kAesTextLength] = {
static const uint8_t kPlaintextRandomStartFvsrKey[kAesTextLength] = {
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
static const uint8_t kKeyRandomStart[kAesTextLength] = {
static const uint8_t kKeyRandomStartFvsrKey[kAesTextLength] = {
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53};
// Staring constants for fixed-vs-random data, DTR Section 5.1
static const uint8_t kPlaintextFixedStartFvsrData[kAesTextLength] = {
0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D,
0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90};
static const uint8_t kPlaintextRandomStartFvsrData[kAesTextLength] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t kKeyStartFvsrData[kAesTextLength] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};

// Initial state of the prng
static const uint8_t kPrngInitialState[kAesTextLength] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// If fixed-vs-random key analysis
if (command == 1) {
memcpy(plaintext_fixed, kPlaintextFixedStart, kAesTextLength);
memcpy(key_fixed, kKeyFixedStart, kAesKeyLength);
memcpy(plaintext_random, kPlaintextRandomStart, kAesTextLength);
memcpy(key_random, kKeyRandomStart, kAesKeyLength);
memcpy(plaintext_fixed, kPlaintextFixedStartFvsrKey, kAesTextLength);
memcpy(key_fixed, kKeyFixedStartFvsrKey, kAesKeyLength);
memcpy(plaintext_random, kPlaintextRandomStartFvsrKey, kAesTextLength);
memcpy(key_random, kKeyRandomStartFvsrKey, kAesKeyLength);
}

// If fixed-vs-random data analysis
if (command == 2) {
memcpy(plaintext_fixed, kPlaintextFixedStartFvsrData, kAesTextLength);
memcpy(key_fixed, kKeyStartFvsrData, kAesKeyLength);
memcpy(plaintext_random, kPlaintextRandomStartFvsrData, kAesTextLength);
memcpy(key_random, kKeyStartFvsrData, kAesKeyLength);
}

memcpy(prng_state, kPrngInitialState, kAesKeyLength);
}

/**
Expand Down Expand Up @@ -655,6 +757,7 @@ bool test_main(void) {
simple_serial_register_handler('f', aes_serial_fvsr_key_set);
simple_serial_register_handler('g', aes_serial_fvsr_key_batch_generate);
simple_serial_register_handler('e', aes_serial_fvsr_key_batch_encrypt);
simple_serial_register_handler('h', aes_serial_fvsr_data_batch_encrypt);
simple_serial_register_handler('l', aes_serial_seed_lfsr);
simple_serial_register_handler('a', aes_serial_batch_alternative_encrypt);
simple_serial_register_handler('i', aes_serial_batch_plaintext_set);
Expand Down

0 comments on commit 686ef97

Please sign in to comment.