Software APIs
aes_sca.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/tests/penetrationtests/firmware/sca/aes_sca.h"
6 
8 #include "sw/device/lib/base/status.h"
11 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
12 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
13 #include "sw/device/lib/ujson/ujson.h"
14 #include "sw/device/sca/lib/aes.h"
15 #include "sw/device/sca/lib/prng.h"
16 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
17 #include "sw/device/tests/penetrationtests/json/aes_sca_commands.h"
18 #include "sw/device/tests/penetrationtests/json/commands.h"
19 
20 #ifndef OPENTITAN_IS_ENGLISHBREAKFAST
21 #include "sw/device/lib/testing/aes_testutils.h"
22 #endif
23 
25 
26 /**
27  * Enable FPGA mode.
28  */
29 static bool fpga_mode = false;
30 
31 enum {
32  kAesKeyLengthMax = 32,
33  kAesKeyLength = 16,
34  kAesTextLength = 16,
35  kTestTimeout = (1000 * 1000),
36  /**
37  * Number of cycles (at `kClockFreqCpuHz`) that Ibex should sleep to minimize
38  * noise during AES operations. Caution: This number should be chosen to
39  * provide enough time. Otherwise, Ibex might wake up while AES is still busy
40  * and disturb the capture. Currently, we use a start trigger delay of 320
41  * clock cycles and the scope captures 60 clock cycles at kClockFreqCpuHz.
42  */
43  kIbexAesSleepCycles = 680,
44  /**
45  * The maximum number of encryptions to do per batch. The ChipWhisperer Husky
46  * scope determines how many encryptions (capture segments) it wants to record
47  * per batch based on the number of samples per segment. As the plaintexts
48  * and keys are generated in advance for fixed-vs-random batch captures, we
49  * need to make sure the corresponding buffers are sufficiently large. Note
50  * that on both CW305 and CW310, the main SRAM has a size of 128 kBytes. So it
51  * should be fine to allocate space for 256 segments (2 * 16 Bytes * 256 = 8
52  * kBytes).
53  */
54  kNumBatchOpsMax = 256,
55  /**
56  * Max number of encryptions that can be captured before we rewrite the key to
57  * reset the internal block counter. Otherwise, the AES peripheral might
58  * trigger the reseeding of the internal masking PRNG which disturbs SCA
59  * measurements.
60  */
61  kBlockCtrMax = 8191,
62 };
63 
64 /**
65  * An array of keys to be used in a batch.
66  */
67 uint8_t batch_keys[kNumBatchOpsMax][kAesKeyLength];
68 
69 /**
70  * An array of plaintexts to be used in a batch.
71  */
72 uint8_t batch_plaintexts[kNumBatchOpsMax][kAesTextLength];
73 
74 /**
75  * Key selection between fixed and random key during the batch capture.
76  */
77 bool sample_fixed = true;
78 
79 /**
80  * An array to store pre-computed round keys derived from the generation key.
81  * The generation key (key_gen) is specified in [DTR] Section 5.1.
82  * This key is used for generating all pseudo-random data for batch captures.
83  * kKeyGen[kAesKeyLength] = {0x12, 0x34, 0x56, 0x78,
84  * 0x9a, 0xbc, 0xde, 0xf1,
85  * 0x23, 0x45, 0x67, 0x89,
86  * 0xab, 0xcd, 0xe0, 0xf0};
87  */
88 static const uint32_t kKeyGenRoundKeys[(kAesKeyLength / 4) * 11] = {
89  0xab239a12, 0xcd45bc34, 0xe067de56, 0xf089f178, 0xbc1734ae, 0xe12c69d5,
90  0x836304da, 0x9262eb1a, 0xcb776054, 0x9d7c5039, 0x71f29195, 0x64f6947f,
91  0xd2196e0e, 0x2bb6ca9a, 0xc4b547d6, 0x6602f460, 0x528099f7, 0xd1fa4c86,
92  0xd317a2e5, 0x452321d5, 0x92c040d9, 0x8756ace0, 0xed3e298b, 0x92d7f4d5,
93  0xfc6eaeee, 0xc84f19b5, 0x3ed3edc4, 0x2bb96e9a, 0x7a86e846, 0x99511e07,
94  0x350bd835, 0xd6fd442a, 0x3c46c028, 0x47de8f91, 0x25101bc3, 0x9f49b4f0,
95  0x29155393, 0xb8ff21ae, 0x36130318, 0x79e6af1b, 0xa68f9ac9, 0xcd758aab,
96  0x88beadae, 0x8ef711be};
97 
98 /**
99  * Plaintext of the fixed set of fixed-vs-random-key TVLA
100  */
101 static uint8_t plaintext_fixed[kAesTextLength] = {
102  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
103  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
104 /**
105  * Key of the of the fixed set of fixed-vs-random-key TVLA
106  */
107 static uint8_t key_fixed[kAesTextLength] = {0x81, 0x1E, 0x37, 0x31, 0xB0, 0x12,
108  0x0A, 0x78, 0x42, 0x78, 0x1E, 0x22,
109  0xB2, 0x5C, 0xDD, 0xF9};
110 /**
111  * Plaintext of the random set of fixed-vs-random-key TVLA
112  */
113 static uint8_t plaintext_random[kAesTextLength] = {
114  0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
115  0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
116 /**
117  * Key of the random set of fixed-vs-random-key TVLA
118  */
119 static uint8_t key_random[kAesTextLength] = {0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
120  0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
121  0x53, 0x53, 0x53, 0x53};
122 /**
123  * Temp ciphertext variable
124  */
125 static uint8_t ciphertext_temp[kAesTextLength];
126 
127 /**
128  * batch_plaintext for batch capture to initially set it using command.
129  */
130 static uint8_t batch_plaintext[kAesTextLength];
131 
132 /**
133  * Block counter variable for manually handling reseeding operations of the
134  * masking PRNG inside the AES peripheral.
135  */
136 static uint32_t block_ctr;
137 
138 static dif_aes_t aes;
139 
140 dif_aes_transaction_t transaction = {
141  .operation = kDifAesOperationEncrypt,
142  .mode = kDifAesModeEcb,
143  .key_len = kDifAesKey128,
144  .manual_operation = kDifAesManualOperationManual,
145  .key_provider = kDifAesKeySoftwareProvided,
146  .mask_reseeding = kDifAesReseedPer8kBlock,
147  .reseed_on_key_change = false,
148  .force_masks = false,
149  .ctrl_aux_lock = false,
150 };
151 
152 /**
153  * Load fixed seed into AES.
154  *
155  * Before calling this function, use
156  * aes_testutils_masking_prng_zero_output_seed() to initialize the entropy
157  * complex for performing AES SCA measurements with masking switched off. This
158  * function then loads the fixed seed into the AES, allowing the disable the
159  * masking.
160  *
161  * @param key Key.
162  * @param key_len Key length.
163  */
164 static status_t aes_sca_load_fixed_seed(void) {
165  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kTestTimeout);
166  // Load magic seed such that masking is turned off. We need to do this after
167  // dif_aes_start() as then the force_masks is correctly set.
169  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kTestTimeout);
170 
171  return OK_STATUS();
172 }
173 
174 /**
175  * Mask and configure key.
176  *
177  * This function masks the provided key using a software LFSR and then
178  * configures the key into the AES peripheral. The masking can be disabled by
179  * initializing the LFSR to 0 (see `aes_serial_seed_lfsr()`). The key must be
180  * `kAesKeyLength` bytes long.
181  *
182  * @param key Key.
183  * @param key_len Key length.
184  */
185 static status_t aes_key_mask_and_config(const uint8_t *key, size_t key_len) {
186  if (key_len != kAesKeyLength) {
187  return ABORTED();
188  }
189  dif_aes_key_share_t key_shares;
190  // Mask the provided key.
191  for (int i = 0; i < key_len / 4; ++i) {
192  key_shares.share1[i] = pentest_non_linear_layer(
193  pentest_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking)));
194  key_shares.share0[i] = *((uint32_t *)key + i) ^ key_shares.share1[i];
195  }
196  // Provide random shares for unused key bits.
197  for (size_t i = key_len / 4; i < kAesKeyLengthMax / 4; ++i) {
198  key_shares.share1[i] =
199  pentest_non_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking));
200  key_shares.share0[i] =
201  pentest_non_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking));
202  }
203  TRY(dif_aes_start(&aes, &transaction, &key_shares, NULL));
204 
205 #ifndef OPENTITAN_IS_ENGLISHBREAKFAST
206  if (transaction.force_masks) {
207  // Disable masking. Force the masking PRNG output value to 0.
208  TRY(aes_sca_load_fixed_seed());
209  }
210 #endif
211 
212  return OK_STATUS();
213 }
214 
215 /**
216  * Callback wrapper for AES manual trigger function.
217  */
218 static void aes_manual_trigger(void) {
220 }
221 
222 /**
223  * Encrypts a plaintext using the AES peripheral.
224  *
225  * This function uses `pentest_call_and_sleep()` from the pentest library to put
226  * Ibex to sleep in order to minimize noise during captures. The plaintext must
227  * be `kAesTextLength` bytes long.
228  *
229  * @param plaintext Plaintext.
230  * @param plaintext_len Length of the plaintext.
231  */
232 static status_t aes_encrypt(const uint8_t *plaintext, size_t plaintext_len) {
233  bool ready = false;
234  do {
235  TRY(dif_aes_get_status(&aes, kDifAesStatusInputReady, &ready));
236  } while (!ready);
237 
238  dif_aes_data_t data;
239  if (plaintext_len != sizeof(data.data)) {
240  return ABORTED();
241  }
242  memcpy(data.data, plaintext, plaintext_len);
243  TRY(dif_aes_load_data(&aes, data));
244 
245  // Start AES operation (this triggers the capture) and go to sleep.
246  if (fpga_mode) {
247  // On FPGA, the trigger is AND-ed with AES !IDLE and creates a LO-HI-LO per.
248  // Activate the GPIO by setting the GPIO.
249  pentest_set_trigger_high();
250  pentest_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, false,
251  false);
252  pentest_set_trigger_low();
253  } else {
254  // On the chip, we need to manually set and unset the trigger. This is done
255  // in this function to have the trigger as close as possible to the AES
256  // operation.
257  pentest_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, true,
258  false);
259  }
260  return OK_STATUS();
261 }
262 
263 /**
264  * Wait until AES output is valid and then get ciphertext and send it over
265  * serial communication.
266  *
267  * @param only_first_word Send only the first word of the ciphertext.
268  */
269 static status_t aes_send_ciphertext(bool only_first_word, ujson_t *uj) {
270  bool ready = false;
271  do {
272  TRY(dif_aes_get_status(&aes, kDifAesStatusOutputValid, &ready));
273  } while (!ready);
274 
275  dif_aes_data_t ciphertext;
276  if (dif_aes_read_output(&aes, &ciphertext) != kDifOk) {
277  return OUT_OF_RANGE();
278  }
279 
280  aes_sca_ciphertext_t uj_output;
281  memset(uj_output.ciphertext, 0, AESSCA_CMD_MAX_DATA_BYTES);
282  uj_output.ciphertext_length = kAesTextLength;
283  if (only_first_word) {
284  uj_output.ciphertext_length = 4;
285  }
286  memcpy(uj_output.ciphertext, (uint8_t *)ciphertext.data,
287  uj_output.ciphertext_length);
288  RESP_OK(ujson_serialize_aes_sca_ciphertext_t, uj, &uj_output);
289  return OK_STATUS();
290 }
291 
292 /**
293  * Advances data for fvsr-key TVLA - fixed set.
294  *
295  * This function updates plaintext_fixed for fvsr-key TVLA, according
296  * to DTR recommendations.
297  */
298 static void aes_serial_advance_fixed(void) {
299  aes_sw_encrypt_block(plaintext_fixed, kKeyGenRoundKeys, ciphertext_temp);
300  memcpy(plaintext_fixed, ciphertext_temp, kAesTextLength);
301 }
302 
303 /**
304  * Advances data for fvsr-key TVLA - random set.
305  *
306  * This function updates plaintext_random and key_random for fvsr-key and
307  * random TVLA, according to DTR recommendations.
308  */
309 static void aes_serial_advance_random(void) {
310  aes_sw_encrypt_block(plaintext_random, kKeyGenRoundKeys, ciphertext_temp);
311  memcpy(plaintext_random, ciphertext_temp, kAesTextLength);
312  aes_sw_encrypt_block(key_random, kKeyGenRoundKeys, ciphertext_temp);
313  memcpy(key_random, ciphertext_temp, kAesTextLength);
314 }
315 
316 /**
317  * Advances data for fvsr-data TVLA - random set.
318  *
319  * This function updates plaintext_random for fvsr-data and
320  * TVLA, according to DTR recommendations, Section 5.1.
321  */
322 static void aes_serial_advance_random_data(void) {
323  aes_sw_encrypt_block(plaintext_random, kKeyGenRoundKeys, ciphertext_temp);
324  memcpy(plaintext_random, ciphertext_temp, kAesTextLength);
325 }
326 
327 /**
328  * Fixed vs random key batch generate command handler.
329  *
330  * This command generates random plaintexts and fixed or random keys using PRNG
331  * for AES fixed vs random key batch capture in order to remove fake leakage.
332  * Fixed or random key sequence is also determined here by using the lsb bit of
333  * the plaintext. In order to simplify the analysis, the first encryption has to
334  * use fixed key. The data collection method is based on the derived test
335  * requirements (DTR) for TVLA:
336  * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf
337  * The measurements are taken by using either fixed or randomly selected keys.
338  * In addition, a PRNG is used for random key and plaintext generation instead
339  * of AES algorithm as specified in the TVLA DTR.
340  *
341  * Packet payload must be a `uint32_t` representation of the number of
342  * encryptions to perform. Number of operations of a batch should not be greater
343  * than the 'kNumBatchOpsMax' value.
344  *
345  * The PRNG should be initialized using the 's' (seed PRNG) command before
346  * starting batch captures. In addition, the fixed key should also be set
347  * using 't' (fvsr key set) command before starting batch captures.
348  *
349  * The uJSON data contains:
350  * - data: The number of encryptions.
351  *
352  * @param uj The received uJSON data.
353  */
354 static status_t aes_sca_fvsr_key_batch_generate(
355  penetrationtest_num_enc_t uj_data) {
356  if (uj_data.num_enc > kNumBatchOpsMax) {
357  return OUT_OF_RANGE();
358  }
359 
360  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
361  if (sample_fixed) {
362  memcpy(batch_keys[i], key_fixed, kAesKeyLength);
363  memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength);
364  aes_serial_advance_fixed();
365  } else {
366  memcpy(batch_keys[i], key_random, kAesKeyLength);
367  memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength);
368  aes_serial_advance_random();
369  }
370  sample_fixed = batch_plaintexts[i][0] & 0x1;
371  }
372 
373  return OK_STATUS();
374 }
375 
376 status_t handle_aes_sca_batch_alternative_encrypt(ujson_t *uj) {
377  penetrationtest_num_enc_t uj_data;
378  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
379 
380  // Add to current block_ctr to check if > kBlockCtrMax
381  block_ctr += uj_data.num_enc;
382  // Rewrite the key to reset the internal block counter. Otherwise, the AES
383  // peripheral might trigger the reseeding of the internal masking PRNG which
384  // disturbs SCA measurements.
385  if (block_ctr > kBlockCtrMax) {
386  TRY(aes_key_mask_and_config(key_fixed, kAesKeyLength));
387  block_ctr = uj_data.num_enc;
388  }
389 
390  // First plaintext has been set through command into batch_plaintext
391 
392  dif_aes_data_t ciphertext;
393  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
394  // Encrypt
395  TRY(aes_encrypt(batch_plaintext, kAesTextLength));
396 
397  // Get ciphertext
398  bool ready = false;
399  do {
400  TRY(dif_aes_get_status(&aes, kDifAesStatusOutputValid, &ready));
401  } while (!ready);
402 
403  if (dif_aes_read_output(&aes, &ciphertext)) {
404  return ABORTED();
405  }
406 
407  // Use ciphertext as next plaintext (incl. next call to this function)
408  memcpy(batch_plaintext, ciphertext.data, kAesTextLength);
409  }
410 
411  // send last ciphertext
412  aes_sca_ciphertext_t uj_output;
413  memcpy(uj_output.ciphertext, (uint8_t *)ciphertext.data, kAesTextLength);
414  RESP_OK(ujson_serialize_aes_sca_ciphertext_t, uj, &uj_output);
415 
416  return OK_STATUS();
417 }
418 
419 status_t handle_aes_sca_batch_encrypt(ujson_t *uj) {
420  penetrationtest_num_enc_t uj_data;
421  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
422 
423  block_ctr += uj_data.num_enc;
424  // Rewrite the key to reset the internal block counter. Otherwise, the AES
425  // peripheral might trigger the reseeding of the internal masking PRNG which
426  // disturbs SCA measurements.
427  if (block_ctr > kBlockCtrMax) {
428  TRY(aes_key_mask_and_config(key_fixed, kAesKeyLength));
429  block_ctr = uj_data.num_enc;
430  }
431 
432  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
433  TRY(aes_encrypt(plaintext_random, kAesTextLength));
434  aes_serial_advance_random();
435  }
436 
437  TRY(aes_send_ciphertext(true, uj));
438 
439  return OK_STATUS();
440 }
441 
442 status_t handle_aes_sca_batch_encrypt_random(ujson_t *uj) {
443  penetrationtest_num_enc_t uj_data;
444  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
445 
446  block_ctr += uj_data.num_enc;
447  // Rewrite the key to reset the internal block counter. Otherwise, the AES
448  // peripheral might trigger the reseeding of the internal masking PRNG which
449  // disturbs SCA measurements.
450  if (block_ctr > kBlockCtrMax) {
451  TRY(aes_key_mask_and_config(key_random, kAesKeyLength));
452  block_ctr = uj_data.num_enc;
453  }
454 
455  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
456  TRY(aes_key_mask_and_config(key_random, kAesKeyLength));
457  TRY(aes_encrypt(plaintext_random, kAesTextLength));
458  aes_serial_advance_random();
459  }
460 
461  TRY(aes_send_ciphertext(true, uj));
462 
463  return OK_STATUS();
464 }
465 
466 status_t handle_aes_sca_batch_plaintext_set(ujson_t *uj) {
467  aes_sca_text_t uj_data;
468  TRY(ujson_deserialize_aes_sca_text_t(uj, &uj_data));
469 
470  if (uj_data.text_length != kAesTextLength) {
471  return OUT_OF_RANGE();
472  }
473  memcpy(batch_plaintext, uj_data.text, uj_data.text_length);
474 
475  return OK_STATUS();
476 }
477 
478 status_t handle_aes_sca_fvsr_data_batch_encrypt(ujson_t *uj) {
479  penetrationtest_num_enc_t uj_data;
480  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
481 
482  if (uj_data.num_enc > kNumBatchOpsMax) {
483  return OUT_OF_RANGE();
484  }
485 
486  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
487  memcpy(batch_keys[i], key_fixed, kAesKeyLength);
488  if (sample_fixed) {
489  memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength);
490  } else {
491  memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength);
492  aes_serial_advance_random_data();
493  }
494  sample_fixed = pentest_next_lfsr(1, kPentestLfsrOrder) & 0x1;
495  }
496 
497  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
498  TRY(aes_key_mask_and_config(batch_keys[i], kAesKeyLength));
499  TRY(aes_encrypt(batch_plaintexts[i], kAesTextLength));
500  }
501 
502  TRY(aes_send_ciphertext(false, uj));
503 
504  return OK_STATUS();
505 }
506 
507 status_t handle_aes_sca_fvsr_key_batch_encrypt(ujson_t *uj) {
508  penetrationtest_num_enc_t uj_data;
509  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
510 
511  if (uj_data.num_enc > kNumBatchOpsMax) {
512  return OUT_OF_RANGE();
513  }
514 
515  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
516  TRY(aes_key_mask_and_config(batch_keys[i], kAesKeyLength));
517  TRY(aes_encrypt(batch_plaintexts[i], kAesTextLength));
518  }
519 
520  TRY(aes_send_ciphertext(false, uj));
521 
522  // Start to generate random keys and plaintexts for the next batch when the
523  // waves are getting from scope by the host to increase capture rate.
524  return aes_sca_fvsr_key_batch_generate(uj_data);
525 }
526 
527 status_t handle_aes_sca_fvsr_key_batch_generate(ujson_t *uj) {
528  penetrationtest_num_enc_t uj_data;
529  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
530 
531  return aes_sca_fvsr_key_batch_generate(uj_data);
532 }
533 
534 status_t handle_aes_sca_fvsr_key_set(ujson_t *uj) {
535  aes_sca_key_t uj_key_data;
536  TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_data));
537 
538  if (uj_key_data.key_length != kAesKeyLength) {
539  return OUT_OF_RANGE();
540  }
541  memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length);
542  return OK_STATUS();
543 }
544 
545 status_t handle_aes_sca_fvsr_key_start_batch_generate(ujson_t *uj) {
546  aes_sca_cmd_t uj_data;
547  TRY(ujson_deserialize_aes_sca_cmd_t(uj, &uj_data));
548 
549  static const uint8_t kPlaintextFixedStartFvsrKey[kAesTextLength] = {
550  0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
551  0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
552  static const uint8_t kKeyFixedStartFvsrKey[kAesTextLength] = {
553  0x81, 0x1E, 0x37, 0x31, 0xB0, 0x12, 0x0A, 0x78,
554  0x42, 0x78, 0x1E, 0x22, 0xB2, 0x5C, 0xDD, 0xF9};
555  static const uint8_t kPlaintextRandomStartFvsrKey[kAesTextLength] = {
556  0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
557  0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
558  static const uint8_t kKeyRandomStartFvsrKey[kAesTextLength] = {
559  0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
560  0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53};
561  // Starting constants for fixed-vs-random data, DTR Section 5.1
562  static const uint8_t kPlaintextFixedStartFvsrData[kAesTextLength] = {
563  0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D,
564  0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90};
565  static const uint8_t kPlaintextRandomStartFvsrData[kAesTextLength] = {
566  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
568  static const uint8_t kKeyStartFvsrData[kAesTextLength] = {
569  0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
570  0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
571 
572  // Initial state of the prng
573  static const uint32_t kPrngInitialState = 0x99999999;
574 
575  // If fixed-vs-random key analysis
576  if (uj_data.cmd == 1) {
577  memcpy(plaintext_fixed, kPlaintextFixedStartFvsrKey, kAesTextLength);
578  memcpy(key_fixed, kKeyFixedStartFvsrKey, kAesKeyLength);
579  memcpy(plaintext_random, kPlaintextRandomStartFvsrKey, kAesTextLength);
580  memcpy(key_random, kKeyRandomStartFvsrKey, kAesKeyLength);
581  }
582 
583  // If fixed-vs-random data analysis
584  if (uj_data.cmd == 2) {
585  memcpy(plaintext_fixed, kPlaintextFixedStartFvsrData, kAesTextLength);
586  memcpy(key_fixed, kKeyStartFvsrData, kAesKeyLength);
587  memcpy(plaintext_random, kPlaintextRandomStartFvsrData, kAesTextLength);
588  }
589 
590  pentest_seed_lfsr(kPrngInitialState, kPentestLfsrOrder);
591 
592  return OK_STATUS();
593 }
594 
595 status_t handle_aes_pentest_init(ujson_t *uj) {
596  // Read mode. FPGA or discrete.
597  aes_sca_fpga_mode_t uj_data;
598  TRY(ujson_deserialize_aes_sca_fpga_mode_t(uj, &uj_data));
599  if (uj_data.fpga_mode == 0x01) {
600  fpga_mode = true;
601  }
602 
603  penetrationtest_cpuctrl_t uj_cpuctrl;
604  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_cpuctrl));
605 
606  pentest_init(kPentestTriggerSourceAes,
607  kPentestPeripheralIoDiv4 | kPentestPeripheralAes);
608 
609  if (dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes) !=
610  kDifOk) {
611  return ABORTED();
612  }
613 
614  if (dif_aes_reset(&aes) != kDifOk) {
615  return ABORTED();
616  }
617 
618  // Configure the CPU for the pentest.
619  penetrationtest_device_info_t uj_output;
620  TRY(pentest_configure_cpu(
621  uj_cpuctrl.icache_disable, uj_cpuctrl.dummy_instr_disable,
622  uj_cpuctrl.enable_jittery_clock, uj_cpuctrl.enable_sram_readback,
623  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
624  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
625  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
626 
627  // Read device ID and return to host.
628  TRY(pentest_read_device_id(uj_output.device_id));
629  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
630 
631  return OK_STATUS();
632 }
633 
634 status_t handle_aes_sca_key_set(ujson_t *uj) {
635  aes_sca_key_t uj_key_data;
636  TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_data));
637 
638  memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length);
639  block_ctr = 0;
640  TRY(aes_key_mask_and_config(key_fixed, uj_key_data.key_length));
641  return OK_STATUS();
642 }
643 
644 status_t handle_aes_pentest_seed_lfsr(ujson_t *uj) {
645  aes_sca_lfsr_t uj_lfsr_data;
646  TRY(ujson_deserialize_aes_sca_lfsr_t(uj, &uj_lfsr_data));
647 
648  uint32_t seed_local = read_32(uj_lfsr_data.seed);
649  if (seed_local == 0) {
650  // disable masking
651  transaction.force_masks = true;
652  } else {
653  // enable masking
654  transaction.force_masks = false;
655  }
656  pentest_seed_lfsr(seed_local, kPentestLfsrMasking);
657 
658 #ifndef OPENTITAN_IS_ENGLISHBREAKFAST
659  if (transaction.force_masks) {
660  LOG_INFO("Disabling masks.");
661  const dif_csrng_t csrng = {
663  const dif_edn_t edn0 = {
665 
666  status_t res = aes_testutils_masking_prng_zero_output_seed(&csrng, &edn0);
667  if (res.value != 0) {
668  return ABORTED();
669  }
670  // Load the magic seed into the PRNG. After this, the PRNG outputs
671  // an all-zero vector.
672  TRY(aes_sca_load_fixed_seed());
673  }
674 #endif
675 
677  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, true, kTestTimeout);
678  return OK_STATUS();
679 }
680 
681 status_t handle_aes_pentest_seed_lfsr_order(ujson_t *uj) {
682  aes_sca_lfsr_t uj_lfsr_data;
683  TRY(ujson_deserialize_aes_sca_lfsr_t(uj, &uj_lfsr_data));
684 
685  uint32_t seed_local = read_32(uj_lfsr_data.seed);
686  pentest_seed_lfsr(seed_local, kPentestLfsrOrder);
687 
688  return OK_STATUS();
689 }
690 
691 status_t handle_aes_sca_single_encrypt(ujson_t *uj) {
692  aes_sca_text_t uj_data;
693  TRY(ujson_deserialize_aes_sca_text_t(uj, &uj_data));
694  if (uj_data.text_length != kAesTextLength) {
695  return OUT_OF_RANGE();
696  }
697 
698  block_ctr++;
699  // Rewrite the key to reset the internal block counter. Otherwise, the AES
700  // peripheral might trigger the reseeding of the internal masking PRNG which
701  // disturbs SCA measurements.
702  if (block_ctr > kBlockCtrMax) {
703  TRY(aes_key_mask_and_config(key_fixed, kAesKeyLength));
704  block_ctr = 1;
705  }
706 
707  TRY(aes_encrypt(uj_data.text, uj_data.text_length));
708 
709  TRY(aes_send_ciphertext(false, uj));
710  return OK_STATUS();
711 }
712 
713 status_t handle_aes_sca(ujson_t *uj) {
714  aes_sca_subcommand_t cmd;
715  TRY(ujson_deserialize_aes_sca_subcommand_t(uj, &cmd));
716  switch (cmd) {
717  case kAesScaSubcommandBatchAlternativeEncrypt:
718  return handle_aes_sca_batch_alternative_encrypt(uj);
719  case kAesScaSubcommandBatchEncrypt:
720  return handle_aes_sca_batch_encrypt(uj);
721  case kAesScaSubcommandBatchEncryptRandom:
722  return handle_aes_sca_batch_encrypt_random(uj);
723  case kAesScaSubcommandBatchPlaintextSet:
724  return handle_aes_sca_batch_plaintext_set(uj);
725  case kAesScaSubcommandFvsrDataBatchEncrypt:
726  return handle_aes_sca_fvsr_data_batch_encrypt(uj);
727  case kAesScaSubcommandFvsrKeyBatchEncrypt:
728  return handle_aes_sca_fvsr_key_batch_encrypt(uj);
729  case kAesScaSubcommandFvsrKeyBatchGenerate:
730  return handle_aes_sca_fvsr_key_batch_generate(uj);
731  case kAesScaSubcommandFvsrKeySet:
732  return handle_aes_sca_fvsr_key_set(uj);
733  case kAesScaSubcommandFvsrKeyStartBatchGenerate:
734  return handle_aes_sca_fvsr_key_start_batch_generate(uj);
735  case kAesScaSubcommandInit:
736  return handle_aes_pentest_init(uj);
737  case kAesScaSubcommandKeySet:
738  return handle_aes_sca_key_set(uj);
739  case kAesScaSubcommandSeedLfsr:
740  return handle_aes_pentest_seed_lfsr(uj);
741  case kAesScaSubcommandSeedLfsrOrder:
742  return handle_aes_pentest_seed_lfsr_order(uj);
743  case kAesScaSubcommandSingleEncrypt:
744  return handle_aes_sca_single_encrypt(uj);
745  default:
746  LOG_ERROR("Unrecognized AES SCA subcommand: %d", cmd);
747  return INVALID_ARGUMENT();
748  }
749  return OK_STATUS();
750 }