Software APIs
otbn_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/otbn_sca.h"
6 
7 #include "ecc256_keygen_sca.h"
10 #include "sw/device/lib/base/status.h"
11 #include "sw/device/lib/crypto/drivers/keymgr.h"
12 #include "sw/device/lib/crypto/impl/keyblob.h"
13 #include "sw/device/lib/crypto/impl/status.h"
16 #include "sw/device/lib/testing/entropy_testutils.h"
17 #include "sw/device/lib/testing/keymgr_testutils.h"
18 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
19 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
20 #include "sw/device/lib/ujson/ujson.h"
21 #include "sw/device/sca/lib/prng.h"
22 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
23 #include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h"
24 
26 #include "otbn_regs.h" // Generated.
27 
28 static dif_otbn_t otbn;
29 static dif_keymgr_t keymgr;
30 static dif_kmac_t kmac;
31 
32 // NOP macros.
33 #define NOP1 "addi x0, x0, 0\n"
34 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
35 #define NOP30 NOP10 NOP10 NOP10
36 
37 enum {
38  kKeySideloadNumIt = 16,
39  /**
40  * Number of bytes for ECDSA P-256 private keys, message digests, and point
41  * coordinates.
42  */
43  kEcc256NumBytes = 256 / 8,
44  /**
45  * Number of 32b words for ECDSA P-256 private keys, message digests, and
46  * point coordinates.
47  */
48  kEcc256NumWords = kEcc256NumBytes / sizeof(uint32_t),
49  /**
50  * Max number of traces per batch.
51  */
52  kNumBatchOpsMax = 256,
53 };
54 
55 // Data structs for key sideloading test.
56 OTBN_DECLARE_APP_SYMBOLS(otbn_key_sideload_sca);
57 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s0_l);
58 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s0_h);
59 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s1_l);
60 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s1_h);
61 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_l);
62 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_h);
63 const otbn_app_t kOtbnAppKeySideloadSca =
64  OTBN_APP_T_INIT(otbn_key_sideload_sca);
65 static const otbn_addr_t kOtbnAppKeySideloadks0l =
66  OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s0_l);
67 static const otbn_addr_t kOtbnAppKeySideloadks0h =
68  OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s0_h);
69 static const otbn_addr_t kOtbnAppKeySideloadks1l =
70  OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s1_l);
71 static const otbn_addr_t kOtbnAppKeySideloadks1h =
72  OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s1_h);
73 static const otbn_addr_t kOtbnAppKeySideloadkl =
74  OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_l);
75 static const otbn_addr_t kOtbnAppKeySideloadkh =
76  OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_h);
77 
78 // RSA OTBN App.
80 OTBN_DECLARE_SYMBOL_ADDR(rsa, mode);
81 OTBN_DECLARE_SYMBOL_ADDR(rsa, n_limbs);
82 OTBN_DECLARE_SYMBOL_ADDR(rsa, inout);
83 OTBN_DECLARE_SYMBOL_ADDR(rsa, modulus);
84 OTBN_DECLARE_SYMBOL_ADDR(rsa, exp);
85 
86 static const otbn_app_t kOtbnAppRsa = OTBN_APP_T_INIT(rsa);
87 static const otbn_addr_t kOtbnVarRsaMode = OTBN_ADDR_T_INIT(rsa, mode);
88 static const otbn_addr_t kOtbnVarRsaNLimbs = OTBN_ADDR_T_INIT(rsa, n_limbs);
89 static const otbn_addr_t kOtbnVarRsaInOut = OTBN_ADDR_T_INIT(rsa, inout);
90 static const otbn_addr_t kOtbnVarRsaModulus = OTBN_ADDR_T_INIT(rsa, modulus);
91 static const otbn_addr_t kOtbnVarRsaExp = OTBN_ADDR_T_INIT(rsa, exp);
92 
93 // p256_ecdsa_sca has randomization removed.
94 OTBN_DECLARE_APP_SYMBOLS(p256_ecdsa_sca);
95 
96 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, mode);
97 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, msg);
98 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, r);
99 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, s);
100 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, x);
101 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, y);
102 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, d0);
103 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, d1);
104 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, k0);
105 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, k1);
106 OTBN_DECLARE_SYMBOL_ADDR(p256_ecdsa_sca, x_r);
107 
108 static const otbn_app_t kOtbnAppP256Ecdsa = OTBN_APP_T_INIT(p256_ecdsa_sca);
109 
110 static const otbn_addr_t kOtbnVarMode = OTBN_ADDR_T_INIT(p256_ecdsa_sca, mode);
111 static const otbn_addr_t kOtbnVarMsg = OTBN_ADDR_T_INIT(p256_ecdsa_sca, msg);
112 static const otbn_addr_t kOtbnVarR = OTBN_ADDR_T_INIT(p256_ecdsa_sca, r);
113 static const otbn_addr_t kOtbnVarS = OTBN_ADDR_T_INIT(p256_ecdsa_sca, s);
114 static const otbn_addr_t kOtbnVarD0 = OTBN_ADDR_T_INIT(p256_ecdsa_sca, d0);
115 static const otbn_addr_t kOtbnVarD1 = OTBN_ADDR_T_INIT(p256_ecdsa_sca, d1);
116 static const otbn_addr_t kOtbnVarK0 = OTBN_ADDR_T_INIT(p256_ecdsa_sca, k0);
117 static const otbn_addr_t kOtbnVarK1 = OTBN_ADDR_T_INIT(p256_ecdsa_sca, k1);
118 
119 /**
120  * Clears the OTBN DMEM and IMEM.
121  *
122  * @returns OK or error.
123  */
124 static status_t clear_otbn(void) {
125  // Clear OTBN memory.
126  TRY(otbn_dmem_sec_wipe());
127  TRY(otbn_imem_sec_wipe());
128 
129  return OK_STATUS();
130 }
131 
132 /**
133  * Generate masked shared.
134  *
135  * If mask_en is set, generate a random share.
136  * If mask_en is not set, set share to 0.
137  *
138  * @param dest_array Destination array.
139  * @param mask_en Masking enabled or disabled.
140  * @param len Length of the array.
141  */
142 void gen_mask_data(uint32_t *dest_array, bool mask_en, size_t len) {
143  if (mask_en) {
144  for (size_t j = 0; j < len; ++j) {
145  dest_array[j] = prng_rand_uint32();
146  }
147  } else {
148  memset(dest_array, 0, len * sizeof(dest_array[0]));
149  }
150 }
151 
152 /**
153  * Generate a FvsR data set.
154  *
155  * If fixed is set, copy src_fixed_array into dest_array.
156  * If fixed is not set, generate random data.
157  *
158  * @param dest_array Destination array.
159  * @param fixed Fixed or random set.
160  * @param src_fixed_array Source fixed array.
161  * @param len Length of the array.
162  */
163 void gen_fvsr_data(uint32_t *dest_array, bool fixed, uint32_t *src_fixed_array,
164  size_t len) {
165  if (fixed) {
166  memcpy(dest_array, src_fixed_array, len * sizeof(src_fixed_array[0]));
167  } else {
168  for (size_t j = 0; j < len; ++j) {
169  dest_array[j] = prng_rand_uint32();
170  }
171  }
172 }
173 
174 /**
175  * Signs a message with ECDSA using the P-256 curve.
176  *
177  * R = k*G
178  * r = x-coordinate of R
179  * s = k^(-1)(msg + r*d) mod n
180  *
181  * @param otbn_ctx The OTBN context object.
182  * @param msg The message to sign, msg (32B).
183  * @param private_key_d The private key, d (32B).
184  * @param k The ephemeral key, k (random scalar) (32B).
185  * @param[out] signature_r Signature component r (the x-coordinate of R).
186  * Provide a pre-allocated 32B buffer.
187  * @param[out] signature_s Signature component s (the proof).
188  * Provide a pre-allocated 32B buffer.
189  */
190 static status_t p256_ecdsa_sign(const uint32_t *msg,
191  const uint32_t *private_key_d,
192  uint32_t *signature_r, uint32_t *signature_s,
193  const uint32_t *k) {
194  uint32_t mode = 1; // mode 1 => sign
195  // Send operation mode to OTBN
196  TRY(otbn_dmem_write(/*num_words=*/1, &mode, kOtbnVarMode));
197  // Send Msg to OTBN
198  TRY(otbn_dmem_write(kEcc256NumWords, msg, kOtbnVarMsg));
199  // Send two shares of private_key_d to OTBN
200  TRY(otbn_dmem_write(kEcc256NumWords, private_key_d, kOtbnVarD0));
201  TRY(otbn_dmem_write(kEcc256NumWords, private_key_d + kEcc256NumWords,
202  kOtbnVarD1));
203  // Send two shares of secret_k to OTBN
204  TRY(otbn_dmem_write(kEcc256NumWords, k, kOtbnVarK0));
205  TRY(otbn_dmem_write(kEcc256NumWords, k + kEcc256NumWords, kOtbnVarK1));
206 
207  // Start OTBN execution
208  pentest_set_trigger_high();
209  // Give the trigger time to rise.
210  asm volatile(NOP30);
211  otbn_execute();
212  otbn_busy_wait_for_done();
213  pentest_set_trigger_low();
214 
215  // Read the results back (sig_r, sig_s)
216  TRY(otbn_dmem_read(kEcc256NumWords, kOtbnVarR, signature_r));
217  TRY(otbn_dmem_read(kEcc256NumWords, kOtbnVarS, signature_s));
218 
219  return OK_STATUS();
220 }
221 
222 status_t handle_otbn_sca_ecdsa_p256_sign(ujson_t *uj) {
223  // Get masks off or on.
224  penetrationtest_otbn_sca_en_masks_t uj_data_masks;
225 
226  // Get message and key.
227  penetrationtest_otbn_sca_ecdsa_p256_sign_t uj_data;
228  TRY(ujson_deserialize_penetrationtest_otbn_sca_ecdsa_p256_sign_t(uj,
229  &uj_data));
230 
231  // Set of share d1 for masking.
232  uint32_t ecc256_private_key_d1[kEcc256NumWords];
233  memset(ecc256_private_key_d1, 0, sizeof(ecc256_private_key_d1));
234  // If masking is activated, generate random share d1.
235  if (uj_data_masks.en_masks) {
236  for (size_t j = 0; j < kEcc256NumWords; j++) {
237  ecc256_private_key_d1[j] = prng_rand_uint32();
238  }
239  }
240 
241  // Set of share k1 for masking.
242  uint32_t ecc256_secret_k1[kEcc256NumWords];
243  memset(ecc256_secret_k1, 0, sizeof(ecc256_secret_k1));
244  // If masking is activated, generate random share d1.
245  if (uj_data_masks.en_masks) {
246  for (size_t j = 0; j < kEcc256NumWords; j++) {
247  ecc256_secret_k1[j] = prng_rand_uint32();
248  }
249  }
250 
251  // Combine D0 and D1 into the private key.
252  uint32_t ecc256_private_key_d[2 * kEcc256NumWords];
253  memset(ecc256_private_key_d, 0, sizeof(ecc256_private_key_d));
254  memcpy(ecc256_private_key_d, uj_data.d0, sizeof(uj_data.d0));
255  memcpy(ecc256_private_key_d + kEcc256NumWords, ecc256_private_key_d1,
256  sizeof(ecc256_private_key_d1));
257 
258  // Combine K0 and K1 into the secret key.
259  uint32_t ecc256_secret_k[2 * kEcc256NumWords];
260  memset(ecc256_secret_k, 0, sizeof(ecc256_secret_k));
261  memcpy(ecc256_secret_k, uj_data.k0, sizeof(uj_data.k0));
262  memcpy(ecc256_secret_k + kEcc256NumWords, ecc256_secret_k1,
263  sizeof(ecc256_secret_k1));
264 
265  otbn_load_app(kOtbnAppP256Ecdsa);
266 
267  // Signature output.
268  uint32_t ecc256_signature_r[kEcc256NumWords];
269  uint32_t ecc256_signature_s[kEcc256NumWords];
270 
271  // Start the operation.
272  p256_ecdsa_sign(uj_data.msg, ecc256_private_key_d, ecc256_signature_r,
273  ecc256_signature_s, ecc256_secret_k);
274 
275  // Send back signature to host.
276  penetrationtest_otbn_sca_ecdsa_p256_signature_t uj_output;
277  memcpy(uj_output.r, ecc256_signature_r, sizeof(ecc256_signature_r));
278  memcpy(uj_output.s, ecc256_signature_s, sizeof(ecc256_signature_s));
279  RESP_OK(ujson_serialize_penetrationtest_otbn_sca_ecdsa_p256_signature_t, uj,
280  &uj_output);
281 
282  // Clear OTBN memory
283  TRY(clear_otbn());
284 
285  return OK_STATUS();
286 }
287 
288 status_t handle_otbn_sca_ecdsa_p256_sign_batch(ujson_t *uj) {
289  // Get number of traces.
290  penetrationtest_otbn_sca_num_traces_t uj_data_num_traces;
291  TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(
292  uj, &uj_data_num_traces));
293 
294  if (uj_data_num_traces.num_traces > kNumBatchOpsMax) {
295  return OUT_OF_RANGE();
296  }
297 
298  // Get masks off or on.
299  penetrationtest_otbn_sca_en_masks_t uj_data_masks;
300  TRY(ujson_deserialize_penetrationtest_otbn_sca_en_masks_t(uj,
301  &uj_data_masks));
302 
303  // Create random message, k, and d.
304  uint32_t ecc256_message_batch[kNumBatchOpsMax][kEcc256NumWords];
305 
306  uint32_t ecc256_private_key_d0_batch[kNumBatchOpsMax][kEcc256NumWords];
307  uint32_t ecc256_private_key_d1_batch[kNumBatchOpsMax][kEcc256NumWords];
308  uint32_t ecc256_private_key_d_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
309 
310  uint32_t ecc256_secret_key_k0_batch[kNumBatchOpsMax][kEcc256NumWords];
311  uint32_t ecc256_secret_key_k1_batch[kNumBatchOpsMax][kEcc256NumWords];
312  uint32_t ecc256_secret_key_k_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
313 
314  // Generate the FvsR data set.
315  for (size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
316  // Generate random message.
317  gen_fvsr_data(ecc256_message_batch[i], false, NULL, kEcc256NumWords);
318 
319  // Set random private key d0.
320  gen_fvsr_data(ecc256_private_key_d0_batch[i], false, NULL, kEcc256NumWords);
321 
322  // When masks are on, set random private key d1. If masks are off, set to 0.
323  gen_mask_data(ecc256_private_key_d1_batch[i], uj_data_masks.en_masks,
324  kEcc256NumWords);
325 
326  // Combine both shares d0 and d1 to d.
327  memcpy(ecc256_private_key_d_batch[i], ecc256_private_key_d0_batch[i],
328  sizeof(ecc256_private_key_d0_batch[i]));
329  memcpy(ecc256_private_key_d_batch[i] + kEcc256NumWords,
330  ecc256_private_key_d1_batch[i],
331  sizeof(ecc256_private_key_d1_batch[i]));
332 
333  // Set random secret key k0.
334  gen_fvsr_data(ecc256_secret_key_k0_batch[i], false, NULL, kEcc256NumWords);
335 
336  // When masks are on, set random secret key k1. If masks are off, set to 0.
337  gen_mask_data(ecc256_secret_key_k1_batch[i], uj_data_masks.en_masks,
338  kEcc256NumWords);
339 
340  // Combine both shares k0 and k1 to k.
341  memcpy(ecc256_secret_key_k_batch[i], ecc256_secret_key_k0_batch[i],
342  sizeof(ecc256_secret_key_k0_batch[i]));
343  memcpy(ecc256_secret_key_k_batch[i] + kEcc256NumWords,
344  ecc256_secret_key_k1_batch[i],
345  sizeof(ecc256_secret_key_k1_batch[i]));
346  }
347 
348  // Last signature output.
349  uint32_t ecc256_signature_r[kEcc256NumWords];
350  uint32_t ecc256_signature_s[kEcc256NumWords];
351  // Run num_traces ECDSA operations.
352  for (size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
353  otbn_load_app(kOtbnAppP256Ecdsa);
354 
355  // Start the operation.
356  p256_ecdsa_sign(ecc256_message_batch[i], ecc256_private_key_d_batch[i],
357  ecc256_signature_r, ecc256_signature_s,
358  ecc256_secret_key_k_batch[i]);
359  }
360 
361  // Send back the last signature to host.
362  penetrationtest_otbn_sca_ecdsa_p256_signature_t uj_output;
363  memcpy(uj_output.r, ecc256_signature_r, sizeof(ecc256_signature_r));
364  memcpy(uj_output.s, ecc256_signature_s, sizeof(ecc256_signature_s));
365  RESP_OK(ujson_serialize_penetrationtest_otbn_sca_ecdsa_p256_signature_t, uj,
366  &uj_output);
367 
368  // Clear OTBN memory
369  TRY(clear_otbn());
370 
371  return OK_STATUS();
372 }
373 
374 status_t handle_otbn_sca_ecdsa_p256_sign_fvsr_batch(ujson_t *uj) {
375  // Get number of traces.
376  penetrationtest_otbn_sca_num_traces_t uj_data_num_traces;
377  TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(
378  uj, &uj_data_num_traces));
379 
380  if (uj_data_num_traces.num_traces > kNumBatchOpsMax) {
381  return OUT_OF_RANGE();
382  }
383 
384  // Get masks off or on.
385  penetrationtest_otbn_sca_en_masks_t uj_data_masks;
386  TRY(ujson_deserialize_penetrationtest_otbn_sca_en_masks_t(uj,
387  &uj_data_masks));
388 
389  // Get fixed message and key.
390  penetrationtest_otbn_sca_ecdsa_p256_sign_t uj_data;
391  TRY(ujson_deserialize_penetrationtest_otbn_sca_ecdsa_p256_sign_t(uj,
392  &uj_data));
393 
394  uint32_t ecc256_message_batch[kNumBatchOpsMax][kEcc256NumWords];
395 
396  uint32_t ecc256_private_key_d0_batch[kNumBatchOpsMax][kEcc256NumWords];
397  uint32_t ecc256_private_key_d1_batch[kNumBatchOpsMax][kEcc256NumWords];
398  uint32_t ecc256_private_key_d_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
399 
400  uint32_t ecc256_secret_key_k0_batch[kNumBatchOpsMax][kEcc256NumWords];
401  uint32_t ecc256_secret_key_k1_batch[kNumBatchOpsMax][kEcc256NumWords];
402  uint32_t ecc256_secret_key_k_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
403 
404  // Generate the FvsR data set. For each trace, message, k, and d is either set
405  // to fixed received from the host over uJSON or random.
406  bool run_fixed = true;
407  for (size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
408  // Set message.
409  gen_fvsr_data(ecc256_message_batch[i], run_fixed, uj_data.msg,
410  kEcc256NumWords);
411 
412  // If the run is fixed, take the private key received over uJSON. Else,
413  // generate a random private key.
414  gen_fvsr_data(ecc256_private_key_d0_batch[i], run_fixed, uj_data.d0,
415  kEcc256NumWords);
416 
417  // When masks are on, set fixed or random private key d1. If masks are off,
418  // set to 0.
419  gen_mask_data(ecc256_private_key_d1_batch[i], uj_data_masks.en_masks,
420  kEcc256NumWords);
421 
422  // Combine both shares
423  memcpy(ecc256_private_key_d_batch[i], ecc256_private_key_d0_batch[i],
424  sizeof(ecc256_private_key_d0_batch[i]));
425  memcpy(ecc256_private_key_d_batch[i] + kEcc256NumWords,
426  ecc256_private_key_d1_batch[i],
427  sizeof(ecc256_private_key_d1_batch[i]));
428 
429  // Set random secret key k0.
430  // If the run is fixed, take the private key received over uJSON. Else,
431  // generate a random private key.
432  gen_fvsr_data(ecc256_secret_key_k0_batch[i], run_fixed, uj_data.k0,
433  kEcc256NumWords);
434 
435  // When masks are on, set random secret key k1. If masks are off, set to 0.
436  gen_mask_data(ecc256_secret_key_k1_batch[i], uj_data_masks.en_masks,
437  kEcc256NumWords);
438 
439  // Combine both shares k0 and k1 to k.
440  memcpy(ecc256_secret_key_k_batch[i], ecc256_secret_key_k0_batch[i],
441  sizeof(ecc256_secret_key_k0_batch[i]));
442  memcpy(ecc256_secret_key_k_batch[i] + kEcc256NumWords,
443  ecc256_secret_key_k1_batch[i],
444  sizeof(ecc256_secret_key_k1_batch[i]));
445 
446  run_fixed = prng_rand_uint32() & 0x1;
447  }
448 
449  // Last signature output.
450  uint32_t ecc256_signature_r[kEcc256NumWords];
451  uint32_t ecc256_signature_s[kEcc256NumWords];
452  // Run num_traces ECDSA operations.
453  for (size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
454  otbn_load_app(kOtbnAppP256Ecdsa);
455 
456  // Start the operation.
457  p256_ecdsa_sign(uj_data.msg, ecc256_private_key_d_batch[i],
458  ecc256_signature_r, ecc256_signature_s,
459  ecc256_secret_key_k_batch[i]);
460  }
461 
462  // Send back the last signature to host.
463  penetrationtest_otbn_sca_ecdsa_p256_signature_t uj_output;
464  memcpy(uj_output.r, ecc256_signature_r, sizeof(ecc256_signature_r));
465  memcpy(uj_output.s, ecc256_signature_s, sizeof(ecc256_signature_s));
466  RESP_OK(ujson_serialize_penetrationtest_otbn_sca_ecdsa_p256_signature_t, uj,
467  &uj_output);
468 
469  // Clear OTBN memory
470  TRY(clear_otbn());
471 
472  return OK_STATUS();
473 }
474 
475 status_t handle_otbn_pentest_init(ujson_t *uj) {
476  penetrationtest_cpuctrl_t uj_data;
477  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
478 
479  // Configure the entropy complex for OTBN. Set the reseed interval to max
480  // to avoid a non-constant trigger window.
481  TRY(pentest_configure_entropy_source_max_reseed_interval());
482 
483  pentest_init(kPentestTriggerSourceOtbn,
484  kPentestPeripheralEntropy | kPentestPeripheralIoDiv4 |
485  kPentestPeripheralOtbn | kPentestPeripheralCsrng |
486  kPentestPeripheralEdn | kPentestPeripheralHmac |
487  kPentestPeripheralKmac);
488 
489  // Init the OTBN core.
490  TRY(dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn));
491 
492  // Load p256 keygen from seed app into OTBN.
493  if (otbn_load_app(kOtbnAppP256KeyFromSeed).value != OTCRYPTO_OK.value) {
494  return ABORTED();
495  }
496 
497  // Configure the CPU for the pentest.
498  penetrationtest_device_info_t uj_output;
499  TRY(pentest_configure_cpu(
500  uj_data.icache_disable, uj_data.dummy_instr_disable,
501  uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
502  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
503  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
504  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
505 
506  // Read device ID and return to host.
507  TRY(pentest_read_device_id(uj_output.device_id));
508  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
509 
510  return OK_STATUS();
511 }
512 
513 status_t handle_otbn_pentest_init_keymgr(ujson_t *uj) {
514  if (kBootStage != kBootStageOwner) {
515  TRY(keymgr_testutils_startup(&keymgr, &kmac));
516  // Advance to OwnerIntermediateKey state.
517  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
518  TRY(keymgr_testutils_check_state(&keymgr,
520  LOG_INFO("Keymgr entered OwnerIntKey State");
521  } else {
523  &keymgr));
524  TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey));
525  }
526 
527  dif_otbn_t otbn;
528  TRY(dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn));
529 
530  return OK_STATUS();
531 }
532 
533 status_t handle_otbn_sca_insn_carry_flag(ujson_t *uj) {
534  // Get big number (256 bit).
535  penetrationtest_otbn_sca_big_num_t uj_data;
536  TRY(ujson_deserialize_penetrationtest_otbn_sca_big_num_t(uj, &uj_data));
537 
538  // INSN Carry Flag OTBN App.
539  OTBN_DECLARE_APP_SYMBOLS(otbn_insn_carry_flag);
540  OTBN_DECLARE_SYMBOL_ADDR(otbn_insn_carry_flag, big_num);
541  OTBN_DECLARE_SYMBOL_ADDR(otbn_insn_carry_flag, big_num_out);
542 
543  static const otbn_app_t kOtbnAppInsnCarryFlag =
544  OTBN_APP_T_INIT(otbn_insn_carry_flag);
545  static const otbn_addr_t kOtbnVarInsnCarryFlagBigNum =
546  OTBN_ADDR_T_INIT(otbn_insn_carry_flag, big_num);
547  static const otbn_addr_t kOtbnVarInsnCarryFlagBigNumOut =
548  OTBN_ADDR_T_INIT(otbn_insn_carry_flag, big_num_out);
549 
550  // Load app and write received big_num into DMEM.
551  otbn_load_app(kOtbnAppInsnCarryFlag);
552  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarInsnCarryFlagBigNum, uj_data.big_num,
553  sizeof(uj_data.big_num)));
554 
555  pentest_set_trigger_high();
556  otbn_execute();
557  otbn_busy_wait_for_done();
558  pentest_set_trigger_low();
559 
560  penetrationtest_otbn_sca_big_num_t uj_output;
561  memset(uj_output.big_num, 0, sizeof(uj_output.big_num));
562  TRY(dif_otbn_dmem_read(&otbn, kOtbnVarInsnCarryFlagBigNumOut,
563  uj_output.big_num, sizeof(uj_output.big_num)));
564 
565  RESP_OK(ujson_serialize_penetrationtest_otbn_sca_big_num_t, uj, &uj_output);
566 
567  return OK_STATUS();
568 }
569 
570 status_t handle_otbn_sca_key_sideload_fvsr(ujson_t *uj) {
571  // Get fixed seed.
572  penetrationtest_otbn_sca_fixed_seed_t uj_data;
573  TRY(ujson_deserialize_penetrationtest_otbn_sca_fixed_seed_t(uj, &uj_data));
574 
575  // Key generation parameters.
576  dif_keymgr_versioned_key_params_t sideload_params[kKeySideloadNumIt];
577 
578  // Generate FvsR values.
579  bool sample_fixed = true;
580  for (size_t it = 0; it < kKeySideloadNumIt; it++) {
581  sideload_params[it].version = 0x0;
582  sideload_params[it].dest = kDifKeymgrVersionedKeyDestOtbn;
583  memset(sideload_params[it].salt, 0, sizeof(sideload_params[it].salt));
584  if (sample_fixed) {
585  sideload_params[it].salt[0] = uj_data.fixed_seed;
586  } else {
587  sideload_params[it].salt[0] = prng_rand_uint32();
588  }
589  sample_fixed = prng_rand_uint32() & 0x1;
590  }
591 
592  otbn_load_app(kOtbnAppKeySideloadSca);
593 
594  uint32_t key_share_0_l[kKeySideloadNumIt], key_share_0_h[kKeySideloadNumIt];
595  uint32_t key_share_1_l[16], key_share_1_h[kKeySideloadNumIt];
596  uint32_t key_l[kKeySideloadNumIt], key_h[kKeySideloadNumIt];
597 
598  // SCA code target.
599  for (size_t it = 0; it < kKeySideloadNumIt; it++) {
600  TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params[it]));
601 
602  TRY(dif_otbn_set_ctrl_software_errs_fatal(&otbn, /*enable=*/false));
603 
604  pentest_set_trigger_high();
605  // Give the trigger time to rise.
606  asm volatile(NOP30);
607  otbn_execute();
608  otbn_busy_wait_for_done();
609  pentest_set_trigger_low();
610  asm volatile(NOP30);
611 
612  otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l[it]);
613  otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h[it]);
614  otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l[it]);
615  otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h[it]);
616  otbn_dmem_read(1, kOtbnAppKeySideloadkl, &key_l[it]);
617  otbn_dmem_read(1, kOtbnAppKeySideloadkh, &key_h[it]);
618  }
619 
620  // Write back shares and keys to host.
621  penetrationtest_otbn_sca_key_t uj_output;
622  for (size_t it = 0; it < kKeySideloadNumIt; it++) {
623  uj_output.shares[0] = key_share_0_l[it];
624  uj_output.shares[1] = key_share_0_h[it];
625  uj_output.shares[2] = key_share_1_l[it];
626  uj_output.shares[3] = key_share_1_h[it];
627  uj_output.keys[0] = key_l[it];
628  uj_output.keys[1] = key_h[it];
629  RESP_OK(ujson_serialize_penetrationtest_otbn_sca_key_t, uj, &uj_output);
630  }
631 
632  return OK_STATUS();
633 }
634 
635 status_t handle_otbn_sca_rsa512_decrypt(ujson_t *uj) {
636  // Get RSA256 parameters.
637  penetrationtest_otbn_sca_rsa512_dec_t uj_data;
638  TRY(ujson_deserialize_penetrationtest_otbn_sca_rsa512_dec_t(uj, &uj_data));
639 
640  otbn_load_app(kOtbnAppRsa);
641 
642  uint32_t mode = 2; // Decrypt.
643  // RSA512 configuration.
644  uint32_t n_limbs = 2;
645 
646  // Write data into OTBN DMEM.
647  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarRsaMode, &mode, sizeof(mode)));
648  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarRsaNLimbs, &n_limbs, sizeof(n_limbs)));
649  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarRsaModulus, uj_data.mod,
650  sizeof(uj_data.mod)));
651  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarRsaExp, uj_data.exp,
652  sizeof(uj_data.exp)));
653  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarRsaInOut, uj_data.msg,
654  sizeof(uj_data.msg)));
655 
656  pentest_set_trigger_high();
657  // Give the trigger time to rise.
658  asm volatile(NOP30);
659  otbn_execute();
660  otbn_busy_wait_for_done();
661  pentest_set_trigger_low();
662 
663  // Send back decryption result to host.
664  penetrationtest_otbn_sca_rsa512_dec_out_t uj_output;
665  TRY(dif_otbn_dmem_read(&otbn, kOtbnVarRsaInOut, uj_output.out,
666  sizeof(uj_output.out)));
667  RESP_OK(ujson_serialize_penetrationtest_otbn_sca_rsa512_dec_out_t, uj,
668  &uj_output);
669  return OK_STATUS();
670 }
671 
672 status_t handle_otbn_sca(ujson_t *uj) {
673  otbn_sca_subcommand_t cmd;
674  TRY(ujson_deserialize_otbn_sca_subcommand_t(uj, &cmd));
675  switch (cmd) {
676  case kOtbnScaSubcommandEcc256EcdsaKeygenFvsrKeyBatch:
677  return handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_key_batch(uj);
678  case kOtbnScaSubcommandEcc256EcdsaKeygenFvsrSeedBatch:
679  return handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_seed_batch(uj);
680  case kOtbnScaSubcommandEcc256EnMasks:
681  return handle_otbn_sca_ecc256_en_masks(uj);
682  case kOtbnScaSubcommandEcc256SetC:
683  return handle_otbn_sca_ecc256_set_c(uj);
684  case kOtbnScaSubcommandEcc256SetSeed:
685  return handle_otbn_sca_ecc256_set_seed(uj);
686  case kOtbnScaSubcommandEcdsaP256Sign:
687  return handle_otbn_sca_ecdsa_p256_sign(uj);
688  case kOtbnScaSubcommandEcdsaP256SignBatch:
689  return handle_otbn_sca_ecdsa_p256_sign_batch(uj);
690  case kOtbnScaSubcommandEcdsaP256SignFvsrBatch:
691  return handle_otbn_sca_ecdsa_p256_sign_fvsr_batch(uj);
692  case kOtbnScaSubcommandInit:
693  return handle_otbn_pentest_init(uj);
694  case kOtbnScaSubcommandInitKeyMgr:
695  return handle_otbn_pentest_init_keymgr(uj);
696  case kOtbnScaSubcommandInsnCarryFlag:
697  return handle_otbn_sca_insn_carry_flag(uj);
698  case kOtbnScaSubcommandKeySideloadFvsr:
699  return handle_otbn_sca_key_sideload_fvsr(uj);
700  case kOtbnScaSubcommandRsa512Decrypt:
701  return handle_otbn_sca_rsa512_decrypt(uj);
702  default:
703  LOG_ERROR("Unrecognized OTBN SCA subcommand: %d", cmd);
704  return INVALID_ARGUMENT();
705  }
706  return OK_STATUS();
707 }