Software APIs
kmac_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/kmac_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/prng.h"
15 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
16 #include "sw/device/tests/penetrationtests/json/commands.h"
17 #include "sw/device/tests/penetrationtests/json/kmac_sca_commands.h"
18 
20 #include "kmac_regs.h"
21 
22 enum {
23  /**
24  * Key length in bytes.
25  */
26  kKeyLength = 16,
27  /**
28  * Message length in bytes.
29  */
30  kMessageLength = 16,
31  /**
32  * Digest length in 32-bit words.
33  */
34  kDigestLength = 8,
35  /**
36  * Number of cycles (at `kClockFreqCpuHz`) that Ibex should sleep to minimize
37  * noise during SHA3 operations. Caution: This number should be chosen to
38  * provide enough time. Otherwise, Ibex might wake up while SHA3 is still busy
39  * and disturb the capture. Currently, we use a start trigger delay of 320
40  * clock cycles and the scope captures 160 clock cycles at kClockFreqCpuHz.
41  * On the scope side, an offset of 395 clock cycles is used to ignore 1) the
42  * start trigger delay for the PROCESS command, and 2) the absorb phase for
43  * the fixed prefix.
44  */
45  kIbexSha3SleepCycles = 1180,
46  /**
47  * Number of cycles (at `kClockFreqCpuHz`) that Ibex should sleep to minimize
48  * noise during loading and hashing the prefix as well as loading and hashing
49  * the key.
50  */
51  kIbexLoadHashPrefixKeySleepCycles = 300,
52  /**
53  * Number of cycles (at `kClockFreqCpuHz`) that Ibex should sleep to minimize
54  * noise during loading and hashing the message.
55  */
56  kIbexLoadHashMessageSleepCycles = 500,
57  /**
58  * Max number of traces per batch.
59  */
60  kNumBatchOpsMax = 128,
61 };
62 
63 /**
64  * Enable FPGA mode.
65  */
66 static bool fpga_mode = false;
67 
68 /**
69  * A handle to KMAC.
70  */
71 static dif_kmac_t kmac;
72 
73 /**
74  * KMAC operation state.
75  */
76 static dif_kmac_operation_state_t kmac_operation_state;
77 
78 /**
79  * KMAC key.
80  *
81  * Used for caching the key in the 'k' (set key) command packet until it is used
82  * when handling a 'p' (absorb) command.
83  */
84 static dif_kmac_key_t kmac_key;
85 
86 /**
87  * KMAC fixed key.
88  *
89  * Used for caching the fixed key in the 't' (set fixed key) command packet
90  * until it is used when handling a 'b' (batch capture) command.
91  */
92 uint8_t key_fixed[kKeyLength];
93 
94 /**
95  * Fixed-key indicator.
96  *
97  * Used in the 'b' (batch capture) command for indicating whether to use fixed
98  * or random key.
99  */
100 static bool run_fixed = false;
101 
102 /**
103  * An array of keys to be used in a batch
104  */
105 uint8_t kmac_batch_keys[kNumBatchOpsMax][kKeyLength];
106 
107 /**
108  * An array of messages to be used in a batch
109  */
110 uint8_t batch_messages[kNumBatchOpsMax][kMessageLength];
111 
112 /**
113  * Blocks until KMAC is idle.
114  */
115 static void kmac_block_until_idle(void) {
116  // TODO(#7842): Remove when `dif_kmac_get_status()` is implemented.
117  uint32_t reg;
118  do {
119  reg = mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
120  } while (!bitfield_bit32_read(reg, KMAC_STATUS_SHA3_IDLE_BIT));
121 }
122 
123 /**
124  * Resets KMAC to idle state.
125  */
126 static void kmac_reset(void) {
127  // TODO(#7842): Remove when `dif_kmac_reset()` is implemented.
128  mmio_region_write32(
129  kmac.base_addr, KMAC_CMD_REG_OFFSET,
130  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_DONE));
131  kmac_block_until_idle();
132 }
133 
134 /**
135  * Report whether the hardware is currently idle.
136  *
137  * If the hardware is not idle then the `CFG` register is locked.
138  *
139  * @param params Hardware parameters.
140  * @returns Whether the hardware is currently idle or not.
141  */
142 static bool is_state_idle(void) {
143  uint32_t reg = mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
144  return bitfield_bit32_read(reg, KMAC_STATUS_SHA3_IDLE_BIT);
145 }
146 
147 /**
148  * Calculate the rate (r) in bits from the given security level.
149  *
150  * @param security_level Security level in bits.
151  * @returns Rate in bits.
152  */
153 static uint32_t calculate_rate_bits(uint32_t security_level) {
154  // Formula for the rate in bits is:
155  //
156  // r = 1600 - c
157  //
158  // Where c is the capacity (the security level in bits multiplied by two).
159  return 1600 - 2 * security_level;
160 }
161 
162 /**
163  * Starts KMAC message without sending START command.
164  *
165  * Based on dif_kmac_mode_kmac_start().
166  *
167  * Unlike dif_kmac_mode_kmac_start(), this function doesn't provide the START
168  * command to the hardware, i.e., just the key is provided and the initial setup
169  * for starting a new message is performed.
170  */
171 static kmac_sca_error_t kmac_msg_start(
172  dif_kmac_mode_kmac_t mode, size_t l, const dif_kmac_key_t *k,
174  if (k == NULL || l > kDifKmacMaxOutputLenWords) {
175  return kmacScaOutOfRange;
176  }
177 
178  // Set key strength and calculate rate (r).
179  uint32_t kstrength;
180  switch (mode) {
182  kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128;
183  kmac_operation_state.r = calculate_rate_bits(128) / 32;
184  break;
186  kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256;
187  kmac_operation_state.r = calculate_rate_bits(256) / 32;
188  break;
189  default:
190  return kmacScaOutOfRange;
191  }
192  kmac_operation_state.offset = 0;
193  kmac_operation_state.d = l;
194  kmac_operation_state.append_d = true;
195 
196  uint32_t key_len;
197  switch (k->length) {
198  case kDifKmacKeyLen128:
199  key_len = KMAC_KEY_LEN_LEN_VALUE_KEY128;
200  break;
201  case kDifKmacKeyLen192:
202  key_len = KMAC_KEY_LEN_LEN_VALUE_KEY192;
203  break;
204  case kDifKmacKeyLen256:
205  key_len = KMAC_KEY_LEN_LEN_VALUE_KEY256;
206  break;
207  case kDifKmacKeyLen384:
208  key_len = KMAC_KEY_LEN_LEN_VALUE_KEY384;
209  break;
210  case kDifKmacKeyLen512:
211  key_len = KMAC_KEY_LEN_LEN_VALUE_KEY512;
212  break;
213  default:
214  return kmacScaOutOfRange;
215  }
216 
217  // Hardware must be idle to start an operation.
218  if (!is_state_idle()) {
219  return kmacScaAborted;
220  }
221 
222  // Set key length and shares.
223  // Uniform sharing is achieved by XORing a random number into both shares.
224  mmio_region_write32(kmac.base_addr, KMAC_KEY_LEN_REG_OFFSET, key_len);
225  for (int i = 0; i < ARRAYSIZE(k->share0); ++i) {
226  // Run LFSR for 32 steps to ensure that all state bits are updated.
227  const uint32_t a = pentest_next_lfsr(32, kPentestLfsrMasking);
228  mmio_region_write32(kmac.base_addr,
229  KMAC_KEY_SHARE0_0_REG_OFFSET +
230  (ptrdiff_t)i * (ptrdiff_t)sizeof(uint32_t),
231  k->share0[i] ^ a);
232  mmio_region_write32(kmac.base_addr,
233  KMAC_KEY_SHARE1_0_REG_OFFSET +
234  (ptrdiff_t)i * (ptrdiff_t)sizeof(uint32_t),
235  k->share1[i] ^ a);
236  }
237 
238  // Configure cSHAKE mode with the given strength and enable KMAC mode.
239  uint32_t cfg_reg =
240  mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
241  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, true);
242  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
243  kstrength);
244  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
245  KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
246  mmio_region_write32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
247  mmio_region_write32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
248 
249  // Initialize prefix registers with function name ("KMAC") and empty
250  // customization string. The empty customization string will be overwritten if
251  // a non-empty string is provided.
252  uint32_t prefix_regs[11] = {
253  0x4D4B2001, // 1 32 'K' 'M'
254  0x00014341, // 'A' 'C' 1 0
255  };
256 
257  // Encoded customization string (s) must be at least 3 bytes long if it is not
258  // the empty string.
259  if (s != NULL && s->length >= 3) {
260  // First two bytes overwrite the pre-encoded empty customization string.
261  prefix_regs[1] &= 0xFFFF;
262  prefix_regs[1] |= (uint32_t)((uint8_t)s->buffer[0]) << 16;
263  prefix_regs[1] |= (uint32_t)((uint8_t)s->buffer[1]) << 24;
264  memcpy(&prefix_regs[2], &s->buffer[2], s->length - 2);
265  }
266 
267  // Write PREFIX register values.
268  const mmio_region_t base = kmac.base_addr;
269  mmio_region_write32(base, KMAC_PREFIX_0_REG_OFFSET, prefix_regs[0]);
270  mmio_region_write32(base, KMAC_PREFIX_1_REG_OFFSET, prefix_regs[1]);
271  mmio_region_write32(base, KMAC_PREFIX_2_REG_OFFSET, prefix_regs[2]);
272  mmio_region_write32(base, KMAC_PREFIX_3_REG_OFFSET, prefix_regs[3]);
273  mmio_region_write32(base, KMAC_PREFIX_4_REG_OFFSET, prefix_regs[4]);
274  mmio_region_write32(base, KMAC_PREFIX_5_REG_OFFSET, prefix_regs[5]);
275  mmio_region_write32(base, KMAC_PREFIX_6_REG_OFFSET, prefix_regs[6]);
276  mmio_region_write32(base, KMAC_PREFIX_7_REG_OFFSET, prefix_regs[7]);
277  mmio_region_write32(base, KMAC_PREFIX_8_REG_OFFSET, prefix_regs[8]);
278  mmio_region_write32(base, KMAC_PREFIX_9_REG_OFFSET, prefix_regs[9]);
279  mmio_region_write32(base, KMAC_PREFIX_10_REG_OFFSET, prefix_regs[10]);
280 
281  return kmacScaOk;
282 }
283 
284 /**
285  * Writes the message including its length to the message FIFO.
286  *
287  * Based on dif_kmac_absorb().
288  *
289  * Unlike dif_kmac_absorb(), this function 1) doesn't require the hardware
290  * to enter the 'absorb' state before writing the message into the message
291  * FIFO, and 2) appends the output length afterwards (normally done as
292  * part of dif_kmac_squeeze()).
293  */
294 static kmac_sca_error_t kmac_msg_write(const void *msg, size_t msg_len,
295  size_t *processed) {
296  // Set the number of bytes processed to 0.
297  if (processed != NULL) {
298  *processed = 0;
299  }
300 
301  if (msg == NULL && msg_len != 0) {
302  return kmacScaOutOfRange;
303  }
304 
305  // Check that an operation has been started.
306  if (kmac_operation_state.r == 0) {
307  return kmacScaAborted;
308  }
309 
310  // Copy the message one byte at a time.
311  // This could be sped up copying a word at a time but be careful
312  // about message endianness (e.g. only copy a word at a time when in
313  // little-endian mode).
314  for (size_t i = 0; i < msg_len; ++i) {
315  mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET,
316  ((const uint8_t *)msg)[i]);
317  }
318 
319  if (processed != NULL) {
320  *processed = msg_len;
321  }
322 
323  // The KMAC operation requires that the output length (d) in bits be right
324  // encoded and appended to the end of the message.
325  // Note: kDifKmacMaxOutputLenWords could be reduced to make this code
326  // simpler. For example, a maximum of `(UINT16_MAX - 32) / 32` (just under
327  // 8 KiB) would mean that d is guaranteed to be less than 0xFFFF.
328  uint32_t d = kmac_operation_state.d * 32;
329  int out_len = 1 + (d > 0xFF) + (d > 0xFFFF) + (d > 0xFFFFFF);
330  int shift = (out_len - 1) * 8;
331  while (shift >= 8) {
332  mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET,
333  (uint8_t)(d >> shift));
334  shift -= 8;
335  }
336  mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET, (uint8_t)d);
337  mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET,
338  (uint8_t)out_len);
339  kmac_operation_state.squeezing = true;
340 
341  return kmacScaOk;
342 }
343 
344 /**
345  * Starts actual processing of a previously provided message.
346  *
347  * This function issues a PROCESS command.
348  */
349 static void kmac_process_cmd(void) {
350  // Issue PROCESS command.
351  uint32_t cmd_reg =
352  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_PROCESS);
353  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
354 }
355 
356 /**
357  * Prepares KMAC to receive the message via the FIFO.
358  *
359  * This function issues a START command.
360  */
361 static void kmac_start_cmd(void) {
362  // Issue START command.
363  uint32_t cmd_reg =
364  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
365  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
366 }
367 
368 /**
369  * Starts actual processing of a previously provided message.
370  *
371  * This function issues a START command directly followed by a PROCESS command.
372  */
373 static void kmac_start_process_cmd(void) {
374  // Issue START command.
375  kmac_start_cmd();
376 
377  // Issue PROCESS command.
378  kmac_process_cmd();
379 }
380 
381 /**
382  * Waits until the hardware enters the 'squeeze' state.
383  *
384  * If the hardware enters the `squeeze` state, this means the output state is
385  * valid and can be read by software.
386  */
387 static void kmac_msg_done(void) {
388  // TODO(#7841, #7842): Remove when we finalize the way we capture traces.
389  uint32_t reg;
390  do {
391  reg = mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
392  } while (!bitfield_bit32_read(reg, KMAC_STATUS_SHA3_SQUEEZE_BIT));
393 }
394 
395 /**
396  * Reads the digest from the hardware.
397  *
398  * Based on dif_kmac_squeeze().
399  *
400  * Unlike dif_kmac_squeeze(), this function 1) doesn't wait until the hardware
401  * enters the 'squeeze' state, 2) doesn't append the output length, 3) doesn't
402  * support the generation of more state.
403  */
404 kmac_sca_error_t kmac_get_digest(uint32_t *out, size_t len) {
405  if (out == NULL && len != 0) {
406  return kmacScaOutOfRange;
407  }
408 
409  while (len > 0) {
410  size_t n = len;
411  size_t remaining = kmac_operation_state.r - kmac_operation_state.offset;
412  if (kmac_operation_state.d != 0 &&
413  kmac_operation_state.d < kmac_operation_state.r) {
414  remaining = kmac_operation_state.d - kmac_operation_state.offset;
415  }
416  if (n > remaining) {
417  n = remaining;
418  }
419  if (n == 0) {
420  // Normally, the hardware would now have to generate more state. But
421  // since at this point, the power measurement is already stopped, we don't
422  // support that here.
423  return kmacScaAborted;
424  }
425 
426  ptrdiff_t offset =
427  KMAC_STATE_REG_OFFSET +
428  (ptrdiff_t)kmac_operation_state.offset * (ptrdiff_t)sizeof(uint32_t);
429  for (size_t i = 0; i < n; ++i) {
430  // Read both shares from state register and combine using XOR.
431  uint32_t share0 = mmio_region_read32(kmac.base_addr, offset);
432  uint32_t share1 =
433  mmio_region_read32(kmac.base_addr, offset + kDifKmacStateShareOffset);
434  *out++ = share0 ^ share1;
435  offset += sizeof(uint32_t);
436  }
437  kmac_operation_state.offset += n;
438  len -= n;
439  }
440  return kmacScaOk;
441 }
442 
443 /**
444  * Initializes the KMAC peripheral.
445  *
446  * This function configures KMAC to use software entropy.
447  */
448 status_t handle_kmac_pentest_init(ujson_t *uj) {
449  // Read mode. FPGA or discrete.
450  cryptotest_kmac_sca_fpga_mode_t uj_data;
451  TRY(ujson_deserialize_cryptotest_kmac_sca_fpga_mode_t(uj, &uj_data));
452  if (uj_data.fpga_mode == 0x01) {
453  fpga_mode = true;
454  }
455 
456  penetrationtest_cpuctrl_t uj_cpuctrl;
457  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_cpuctrl));
458 
459  // Setup the trigger.
460  pentest_init(kPentestTriggerSourceKmac,
461  kPentestPeripheralIoDiv4 | kPentestPeripheralKmac);
462  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
463 
465  .entropy_mode = kDifKmacEntropyModeSoftware,
466  .entropy_fast_process = kDifToggleDisabled,
467  .entropy_seed = {0xb153e3fe, 0x09596819, 0x3e85a6e8, 0xb6dcdaba,
468  0x50dc409c, 0x11e1ebd1},
469  .message_big_endian = kDifToggleDisabled,
470  .output_big_endian = kDifToggleDisabled,
471  .sideload = kDifToggleDisabled,
472  .msg_mask = kDifToggleEnabled,
473  };
474  TRY(dif_kmac_configure(&kmac, config));
475 
476  kmac_block_until_idle();
477 
478  // Configure the CPU for the pentest.
479  penetrationtest_device_info_t uj_output;
480  TRY(pentest_configure_cpu(
481  uj_cpuctrl.icache_disable, uj_cpuctrl.dummy_instr_disable,
482  uj_cpuctrl.enable_jittery_clock, uj_cpuctrl.enable_sram_readback,
483  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
484  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
485  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
486 
487  // Read device ID and return to host.
488  TRY(pentest_read_device_id(uj_output.device_id));
489  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
490 
491  return OK_STATUS();
492 }
493 
494 /**
495  * Set key command handler.
496  *
497  * This function simply caches the provided key in the static `kmac_key`
498  * variable so that it can be used in subsequent operations. This function does
499  * not use key shares to simplify side-channel analysis. The key must be
500  * `kKeyLength` bytes long.
501  *
502  * The uJSON data contains:
503  * - key Key. Must be `kKeyLength` bytes long.
504  * - key_len Key length. Must be equal to `kKeyLength`.
505  *
506  * @param uj The received uJSON data.
507  */
508 status_t handle_kmac_sca_set_key(ujson_t *uj) {
509  cryptotest_kmac_sca_key_t uj_key;
510  TRY(ujson_deserialize_cryptotest_kmac_sca_key_t(uj, &uj_key));
511 
512  if (uj_key.key_length != kKeyLength) {
513  return OUT_OF_RANGE();
514  }
515 
516  kmac_key = (dif_kmac_key_t){
517  .length = kDifKmacKeyLen128,
518  };
519  memcpy(kmac_key.share0, uj_key.key, kKeyLength);
520 
521  return OK_STATUS();
522 }
523 
524 /**
525  * Absorbs a message using KMAC128 without a customization string.
526  *
527  * Two modes are supported: FPGA and non-FPGA mode.
528  * The FPGA mode can be used to improve KMAC SCA. Here, features only available
529  * on the FPGA bitstream are used (i.e., SecKmacCmdDelay and
530  * SecKmacIdleAcceptSwMsg). The non-FPGA mode represents the chip where these
531  * features are disabled.
532  *
533  * In the FPGA mode, this function performs:
534  * - Configure mode/key/...
535  * - Write data to the message FIFO.
536  * - Send START and PROCESS commands, put Ibex into sleep.
537  *
538  * In the non-FPGA mode, this function performs:
539  * - Configure mode/key/...
540  * - Send START command, put Ibex into sleep.
541  * - Write message FIFO.
542  * - Send PROCESS command, put Ibex into sleep.
543  *
544  * @param msg Message.
545  * @param msg_len Message length.
546  */
547 static kmac_sca_error_t sha3_ujson_absorb(const uint8_t *msg, size_t msg_len) {
548  // Start a new message.
549  if (kmac_msg_start(kDifKmacModeKmacLen128, kDigestLength, &kmac_key, NULL) !=
550  kmacScaOk) {
551  return kmacScaAborted;
552  }
553 
554  if (fpga_mode == false) {
555  // Start command. On the chip, we need to first issue a START command
556  // before writing to the message FIFO.
557  pentest_call_and_sleep(kmac_start_cmd, kIbexLoadHashPrefixKeySleepCycles,
558  false, false);
559  }
560 
561  // Write data to message FIFO.
562  if (kmac_msg_write(msg, msg_len, NULL) != kmacScaOk) {
563  return kmacScaAborted;
564  }
565 
566  if (fpga_mode) {
567  // On the FPGA, start the SHA3 processing (this triggers the capture) and
568  // go to sleep. Using the SecCmdDelay hardware parameter, the KMAC unit is
569  // configured to start operation 320 cycles after receiving the START and
570  // PROC commands. This allows Ibex to go to sleep in order to not disturb
571  // the capture.
572  pentest_call_and_sleep(kmac_start_process_cmd, kIbexSha3SleepCycles, false,
573  false);
574  } else {
575  // On the chip, issue a PROCESS command to start operation and put Ibex
576  // into sleep.
577  pentest_call_and_sleep(kmac_process_cmd, kIbexLoadHashMessageSleepCycles,
578  false, false);
579  }
580 
581  return kmacScaOk;
582 }
583 
584 /**
585  * Absorb command handler.
586  *
587  * Absorbs the given message using KMAC128 without a customization string,
588  * and sends the digest over UART. This function also handles the trigger
589  * signal.
590  *
591  * The uJSON data contains:
592  * - msg: Message.
593  * - msg_len: Message length.
594  *
595  * @param uj The received uJSON data.
596  */
597 status_t handle_kmac_sca_single_absorb(ujson_t *uj) {
598  cryptotest_kmac_sca_msg_t uj_msg;
599  TRY(ujson_deserialize_cryptotest_kmac_sca_msg_t(uj, &uj_msg));
600 
601  if (uj_msg.msg_length != kMessageLength) {
602  return OUT_OF_RANGE();
603  }
604 
605  // Ungate the capture trigger signal and then start the operation.
606  pentest_set_trigger_high();
607  if (sha3_ujson_absorb(uj_msg.msg, uj_msg.msg_length) != kmacScaOk) {
608  return ABORTED();
609  }
610  pentest_set_trigger_low();
611 
612  // Check KMAC has finished processing the message.
613  kmac_msg_done();
614 
615  // Read the digest and send it to the host for verification.
616  uint32_t out[kDigestLength];
617  if (kmac_get_digest(out, kDigestLength) != kmacScaOk) {
618  return ABORTED();
619  }
620 
621  cryptotest_kmac_sca_batch_digest_t uj_output;
622  memcpy(uj_output.batch_digest, (uint8_t *)out, kDigestLength * 4);
623  RESP_OK(ujson_serialize_cryptotest_kmac_sca_batch_digest_t, uj, &uj_output);
624 
625  // Reset before the next absorb since KMAC must be idle before starting
626  // another absorb.
627  kmac_reset();
628 
629  return OK_STATUS();
630 }
631 
632 /**
633  * Fixed key set command handler.
634  *
635  * * The uJSON data contains:
636  * - key: The key to use.
637  * - key_length: The length of the key.
638  *
639  * @param uj The received uJSON data.
640  */
641 status_t handle_kmac_sca_fixed_key_set(ujson_t *uj) {
642  cryptotest_kmac_sca_key_t uj_key;
643  TRY(ujson_deserialize_cryptotest_kmac_sca_key_t(uj, &uj_key));
644 
645  if (uj_key.key_length != kKeyLength) {
646  return OUT_OF_RANGE();
647  }
648 
649  memcpy(key_fixed, uj_key.key, uj_key.key_length);
650 
651  return OK_STATUS();
652 }
653 
654 /**
655  * Batch command handler.
656  *
657  * Start batch mode.
658  *
659  * The uJSON data contains:
660  * - data: The number of encryptions.
661  *
662  * @param uj The received uJSON data.
663  */
664 status_t handle_kmac_sca_batch(ujson_t *uj) {
665  penetrationtest_num_enc_t uj_data;
666  TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
667 
668  uint32_t out[kDigestLength];
669  uint32_t batch_digest[kDigestLength];
670 
671  for (uint32_t j = 0; j < kDigestLength; ++j) {
672  batch_digest[j] = 0;
673  }
674 
675  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
676  if (run_fixed) {
677  memcpy(kmac_batch_keys[i], key_fixed, kKeyLength);
678  } else {
679  prng_rand_bytes(kmac_batch_keys[i], kKeyLength);
680  }
681  prng_rand_bytes(batch_messages[i], kMessageLength);
682  run_fixed = batch_messages[i][0] & 0x1;
683  }
684 
685  for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
686  kmac_reset();
687  memcpy(kmac_key.share0, kmac_batch_keys[i], kKeyLength);
688 
689  pentest_set_trigger_high();
690  if (sha3_ujson_absorb(batch_messages[i], kMessageLength) != kmacScaOk) {
691  return ABORTED();
692  }
693  pentest_set_trigger_low();
694 
695  kmac_msg_done();
696  if (kmac_get_digest(out, kDigestLength) != kmacScaOk) {
697  return ABORTED();
698  }
699 
700  // The correctness of each batch is verified by computing and sending
701  // the batch digest. This digest is computed by XORing all outputs of
702  // the batch.
703  for (uint32_t j = 0; j < kDigestLength; ++j) {
704  batch_digest[j] ^= out[j];
705  }
706  }
707  // Send the batch digest to the host for verification.
708  cryptotest_kmac_sca_batch_digest_t uj_output;
709  memcpy(uj_output.batch_digest, (uint8_t *)batch_digest, kDigestLength * 4);
710  RESP_OK(ujson_serialize_cryptotest_kmac_sca_batch_digest_t, uj, &uj_output);
711 
712  return OK_STATUS();
713 }
714 
715 /**
716  * Seed lfsr command handler.
717  *
718  * This function only supports 4-byte seeds.
719  *
720  * * The uJSON data contains:
721  * - seed: A buffer holding the seed.
722  *
723  * @param uj The received uJSON data.
724  */
725 status_t handle_kmac_pentest_seed_lfsr(ujson_t *uj) {
726  cryptotest_kmac_sca_lfsr_t uj_lfsr_data;
727  TRY(ujson_deserialize_cryptotest_kmac_sca_lfsr_t(uj, &uj_lfsr_data));
728  pentest_seed_lfsr(read_32(uj_lfsr_data.seed), kPentestLfsrMasking);
729 
730  return OK_STATUS();
731 }
732 
733 /**
734  * Ibex FI command handler.
735  *
736  * Command handler for the Ibex FI command.
737  *
738  * @param uj The received uJSON data.
739  */
740 status_t handle_kmac_sca(ujson_t *uj) {
741  kmac_sca_subcommand_t cmd;
742  TRY(ujson_deserialize_kmac_sca_subcommand_t(uj, &cmd));
743  switch (cmd) {
744  case kKmacScaSubcommandInit:
745  return handle_kmac_pentest_init(uj);
746  case kKmacScaSubcommandSetKey:
747  return handle_kmac_sca_set_key(uj);
748  case kKmacScaSubcommandSingleAbsorb:
749  return handle_kmac_sca_single_absorb(uj);
750  case kKmacScaSubcommandBatch:
751  return handle_kmac_sca_batch(uj);
752  case kKmacScaSubcommandFixedKeySet:
753  return handle_kmac_sca_fixed_key_set(uj);
754  case kKmacScaSubcommandSeedLfsr:
755  return handle_kmac_pentest_seed_lfsr(uj);
756  default:
757  LOG_ERROR("Unrecognized KMAC SCA FI subcommand: %d", cmd);
758  return INVALID_ARGUMENT();
759  }
760  return OK_STATUS();
761 }