diff --git a/sw/device/sca/aes_serial.c b/sw/device/sca/aes_serial.c index 4ab4117a36dccb..563a99fc769b40 100644 --- a/sw/device/sca/aes_serial.c +++ b/sw/device/sca/aes_serial.c @@ -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. */ @@ -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 * @@ -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. * @@ -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. @@ -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. * @@ -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); } /** @@ -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);