Software APIs
otbn_fi.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/fi/otbn_fi.h"
6 
8 #include "sw/device/lib/base/status.h"
9 #include "sw/device/lib/crypto/drivers/keymgr.h"
10 #include "sw/device/lib/crypto/drivers/otbn.h"
12 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
14 #include "sw/device/lib/testing/entropy_testutils.h"
15 #include "sw/device/lib/testing/keymgr_testutils.h"
16 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
17 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
18 #include "sw/device/lib/ujson/ujson.h"
19 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
20 #include "sw/device/tests/penetrationtests/json/otbn_fi_commands.h"
21 
23 #include "otbn_regs.h"
24 
25 // Interface to Ibex.
26 static dif_rv_core_ibex_t rv_core_ibex;
27 
28 static dif_otbn_t otbn;
29 static dif_keymgr_t keymgr;
30 
31 // Indicates whether the load_integrity test is already initialized.
32 static bool load_integrity_init;
33 // Indicates whether the char mem test is already initialized.
34 static bool char_mem_init;
35 // Indicates whether the char mem test config is valid.
36 static bool char_mem_test_cfg_valid;
37 // Reference checksum for the load integrity test.
38 static uint32_t load_checksum_ref;
39 // Load integrity test. Initialize OTBN app, load it, and get interface to
40 // OTBN data memory.
41 OTBN_DECLARE_APP_SYMBOLS(otbn_load_integrity);
42 OTBN_DECLARE_SYMBOL_ADDR(otbn_load_integrity, refval1);
43 OTBN_DECLARE_SYMBOL_ADDR(otbn_load_integrity, refval2);
44 OTBN_DECLARE_SYMBOL_ADDR(otbn_load_integrity, refval3);
45 static const otbn_app_t kOtbnAppLoadIntegrity =
46  OTBN_APP_T_INIT(otbn_load_integrity);
47 static const otbn_addr_t kOtbnAppLoadIntegrityRefVal1 =
48  OTBN_ADDR_T_INIT(otbn_load_integrity, refval1);
49 static const otbn_addr_t kOtbnAppLoadIntegrityRefVal2 =
50  OTBN_ADDR_T_INIT(otbn_load_integrity, refval2);
51 static const otbn_addr_t kOtbnAppLoadIntegrityRefVal3 =
52  OTBN_ADDR_T_INIT(otbn_load_integrity, refval3);
53 
54 // Indicates whether the key sideloading test is already initialized.
55 static bool key_sideloading_init;
56 // Key sideloading test. Initialize OTBN app, load it, and get interface to
57 // OTBN data memory.
58 OTBN_DECLARE_APP_SYMBOLS(otbn_key_sideload);
59 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s0_l);
60 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s0_h);
61 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s1_l);
62 OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s1_h);
63 const otbn_app_t kOtbnAppKeySideload = OTBN_APP_T_INIT(otbn_key_sideload);
64 static const otbn_addr_t kOtbnAppKeySideloadks0l =
65  OTBN_ADDR_T_INIT(otbn_key_sideload, k_s0_l);
66 static const otbn_addr_t kOtbnAppKeySideloadks0h =
67  OTBN_ADDR_T_INIT(otbn_key_sideload, k_s0_h);
68 static const otbn_addr_t kOtbnAppKeySideloadks1l =
69  OTBN_ADDR_T_INIT(otbn_key_sideload, k_s1_l);
70 static const otbn_addr_t kOtbnAppKeySideloadks1h =
71  OTBN_ADDR_T_INIT(otbn_key_sideload, k_s1_h);
72 
73 // Config for the otbn.fi.char_mem test.
74 static bool char_mem_imem;
75 static bool char_mem_dmem;
76 static uint32_t char_mem_byte_offset;
77 static uint32_t char_mem_num_words;
78 
79 uint32_t key_share_0_l_ref, key_share_0_h_ref;
80 uint32_t key_share_1_l_ref, key_share_1_h_ref;
81 
82 // NOP macros.
83 #define NOP1 "addi x0, x0, 0\n"
84 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
85 #define NOP30 NOP10 NOP10 NOP10
86 #define NOP100 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10
87 
88 // Reference values.
89 static const uint32_t ref_values[32] = {
90  0x1BADB002, 0x8BADF00D, 0xA5A5A5A5, 0xABABABAB, 0xABBABABE, 0xABADCAFE,
91  0xBAAAAAAD, 0xBAD22222, 0xBBADBEEF, 0xBEBEBEBE, 0xBEEFCACE, 0xC00010FF,
92  0xCAFED00D, 0xCAFEFEED, 0xCCCCCCCC, 0xCDCDCDCD, 0x0D15EA5E, 0xDEAD10CC,
93  0xDEADBEEF, 0xDEADCAFE, 0xDEADC0DE, 0xDEADFA11, 0xDEADF00D, 0xDEFEC8ED,
94  0xDEADDEAD, 0xD00D2BAD, 0xEBEBEBEB, 0xFADEDEAD, 0xFDFDFDFD, 0xFEE1DEAD,
95  0xFEEDFACE, 0xFEEEFEEE};
96 
97 static const dif_keymgr_versioned_key_params_t kKeyVersionedParamsOTBNFI = {
99  .salt = // the salt doesn't really matter here.
100  {
101  0xb6521d8f,
102  0x13a0e876,
103  0x1ca1567b,
104  0xb4fb0fdf,
105  0x9f89bc56,
106  0x4bd127c7,
107  0x322288d8,
108  0xde919d54,
109  },
110  .version = 0x0, // specify a low enough version to work with the ROM EXT.
111 };
112 
113 /**
114  * Clears the OTBN DMEM and IMEM.
115  *
116  * @returns OK or error.
117  */
118 static status_t clear_otbn(void) {
119  // Clear OTBN memory.
120  TRY(otbn_dmem_sec_wipe());
121  TRY(otbn_imem_sec_wipe());
122 
123  return OK_STATUS();
124 }
125 
126 /**
127  * Read the error bits of the OTBN accelerator.
128  *
129  * @returns Error bits.
130  */
131 status_t read_otbn_err_bits(dif_otbn_err_bits_t *err_otbn) {
132  TRY(dif_otbn_get_err_bits(&otbn, err_otbn));
133  return OK_STATUS();
134 }
135 
136 /**
137  * Read the OTBN load checksum.
138  *
139  * @returns Load checksum.
140  */
141 status_t read_otbn_load_checksum(uint32_t *checksum) {
142  TRY(dif_otbn_get_load_checksum(&otbn, checksum));
143  return OK_STATUS();
144 }
145 
146 /**
147  * Clear the OTBN load checksum.
148  */
149 status_t clear_otbn_load_checksum(void) {
150  TRY(dif_otbn_clear_load_checksum(&otbn));
151  return OK_STATUS();
152 }
153 
154 status_t handle_otbn_fi_char_beq(ujson_t *uj) {
155  // Clear registered alerts in alert handler.
156  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
157  // Clear the AST recoverable alerts.
158  pentest_clear_sensor_recov_alerts();
159 
160  // Initialize OTBN app, load it, and get interface to OTBN data memory.
161  OTBN_DECLARE_APP_SYMBOLS(otbn_char_beq);
162  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_beq, res);
163  const otbn_app_t kOtbnAppCharBeq = OTBN_APP_T_INIT(otbn_char_beq);
164  static const otbn_addr_t kOtbnAppCharBeqRes =
165  OTBN_ADDR_T_INIT(otbn_char_beq, res);
166  otbn_load_app(kOtbnAppCharBeq);
167 
168  // FI code target.
169  pentest_set_trigger_high();
170  otbn_execute();
171  otbn_busy_wait_for_done();
172  pentest_set_trigger_low();
173  // Get registered alerts from alert handler.
174  reg_alerts = pentest_get_triggered_alerts();
175  // Get fatal and recoverable AST alerts from sensor controller.
176  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
177 
178  // Read counter (x1) from OTBN data memory.
179  otbn_fi_result_cnt_t uj_output;
180  uj_output.result = 0;
181  otbn_dmem_read(1, kOtbnAppCharBeqRes, &uj_output.result);
182 
183  // Read OTBN instruction counter.
184  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
185 
186  // Read ERR_STATUS register from OTBN.
187  dif_otbn_err_bits_t err_otbn;
188  read_otbn_err_bits(&err_otbn);
189 
190  // Read ERR_STATUS register from Ibex.
191  dif_rv_core_ibex_error_status_t err_ibx;
192  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
193 
194  // Clear OTBN memory.
195  TRY(clear_otbn());
196 
197  // Send back to host.
198  uj_output.err_otbn = err_otbn;
199  uj_output.err_ibx = err_ibx;
200  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
201  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
202  sizeof(sensor_alerts.alerts));
203  RESP_OK(ujson_serialize_otbn_fi_result_cnt_t, uj, &uj_output);
204  return OK_STATUS();
205 }
206 
207 status_t handle_otbn_fi_char_bn_rshi(ujson_t *uj) {
208  // Get big number (2x256 bit).
209  otbn_fi_big_num_t uj_data;
210  TRY(ujson_deserialize_otbn_fi_big_num_t(uj, &uj_data));
211 
212  // Clear registered alerts in alert handler.
213  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
214  // Clear the AST recoverable alerts.
215  pentest_clear_sensor_recov_alerts();
216 
217  // Initialize OTBN app, load it, and get interface to OTBN data memory.
218  OTBN_DECLARE_APP_SYMBOLS(otbn_char_bn_rshi);
219  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_bn_rshi, big_num);
220  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_bn_rshi, big_num_out);
221  const otbn_app_t kOtbnAppCharBnRshi = OTBN_APP_T_INIT(otbn_char_bn_rshi);
222  static const otbn_addr_t kOtbnAppCharBnRshiBigNum =
223  OTBN_ADDR_T_INIT(otbn_char_bn_rshi, big_num);
224  static const otbn_addr_t kOtbnAppCharBnRshiBigNumOut =
225  OTBN_ADDR_T_INIT(otbn_char_bn_rshi, big_num_out);
226 
227  // Load app and write received big_num into DMEM.
228  otbn_load_app(kOtbnAppCharBnRshi);
229  TRY(dif_otbn_dmem_write(&otbn, kOtbnAppCharBnRshiBigNum, uj_data.big_num,
230  sizeof(uj_data.big_num)));
231 
232  // FI code target.
233  pentest_set_trigger_high();
234  otbn_execute();
235  otbn_busy_wait_for_done();
236  pentest_set_trigger_low();
237  // Get registered alerts from alert handler.
238  reg_alerts = pentest_get_triggered_alerts();
239  // Get fatal and recoverable AST alerts from sensor controller.
240  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
241 
242  // Read big_num_out from OTBN data memory.
243  otbn_fi_big_num_out_t uj_output;
244  memset(uj_output.big_num, 0, sizeof(uj_output.big_num));
245  TRY(dif_otbn_dmem_read(&otbn, kOtbnAppCharBnRshiBigNumOut, uj_output.big_num,
246  sizeof(uj_output.big_num)));
247 
248  // Read OTBN instruction counter.
249  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
250 
251  // Read ERR_STATUS register from OTBN.
252  dif_otbn_err_bits_t err_otbn;
253  read_otbn_err_bits(&err_otbn);
254 
255  // Read ERR_STATUS register from Ibex.
256  dif_rv_core_ibex_error_status_t err_ibx;
257  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
258 
259  // Clear OTBN memory.
260  TRY(clear_otbn());
261 
262  // Send back to host.
263  uj_output.err_otbn = err_otbn;
264  uj_output.err_ibx = err_ibx;
265  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
266  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
267  sizeof(sensor_alerts.alerts));
268  RESP_OK(ujson_serialize_otbn_fi_big_num_out_t, uj, &uj_output);
269  return OK_STATUS();
270 }
271 
272 status_t handle_otbn_fi_char_bn_sel(ujson_t *uj) {
273  // Get big number (2x256 bit).
274  otbn_fi_big_num_t uj_data;
275  TRY(ujson_deserialize_otbn_fi_big_num_t(uj, &uj_data));
276 
277  // Clear registered alerts in alert handler.
278  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
279  // Clear the AST recoverable alerts.
280  pentest_clear_sensor_recov_alerts();
281 
282  // Initialize OTBN app, load it, and get interface to OTBN data memory.
283  OTBN_DECLARE_APP_SYMBOLS(otbn_char_bn_sel);
284  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_bn_sel, big_num);
285  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_bn_sel, big_num_out);
286  const otbn_app_t kOtbnAppCharBnSel = OTBN_APP_T_INIT(otbn_char_bn_sel);
287  static const otbn_addr_t kOtbnAppCharBnSelBigNum =
288  OTBN_ADDR_T_INIT(otbn_char_bn_sel, big_num);
289  static const otbn_addr_t kOtbnAppCharBnSelBigNumOut =
290  OTBN_ADDR_T_INIT(otbn_char_bn_sel, big_num_out);
291 
292  // Load app and write received big_num into DMEM.
293  otbn_load_app(kOtbnAppCharBnSel);
294  TRY(dif_otbn_dmem_write(&otbn, kOtbnAppCharBnSelBigNum, uj_data.big_num,
295  sizeof(uj_data.big_num)));
296 
297  // FI code target.
298  pentest_set_trigger_high();
299  otbn_execute();
300  otbn_busy_wait_for_done();
301  pentest_set_trigger_low();
302  // Get registered alerts from alert handler.
303  reg_alerts = pentest_get_triggered_alerts();
304  // Get fatal and recoverable AST alerts from sensor controller.
305  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
306 
307  // Read big_num_out from OTBN data memory.
308  otbn_fi_big_num_out_t uj_output;
309  memset(uj_output.big_num, 0, sizeof(uj_output.big_num));
310  TRY(dif_otbn_dmem_read(&otbn, kOtbnAppCharBnSelBigNumOut, uj_output.big_num,
311  sizeof(uj_output.big_num)));
312 
313  // Read OTBN instruction counter.
314  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
315 
316  // Read ERR_STATUS register from OTBN.
317  dif_otbn_err_bits_t err_otbn;
318  read_otbn_err_bits(&err_otbn);
319 
320  // Read ERR_STATUS register from Ibex.
321  dif_rv_core_ibex_error_status_t err_ibx;
322  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
323 
324  // Clear OTBN memory.
325  TRY(clear_otbn());
326 
327  // Send back to host.
328  uj_output.err_otbn = err_otbn;
329  uj_output.err_ibx = err_ibx;
330  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
331  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
332  sizeof(sensor_alerts.alerts));
333  RESP_OK(ujson_serialize_otbn_fi_big_num_out_t, uj, &uj_output);
334  return OK_STATUS();
335 }
336 
337 status_t handle_otbn_fi_char_bn_wsrr(ujson_t *uj) {
338  // Clear registered alerts in alert handler.
339  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
340  // Clear the AST recoverable alerts.
341  pentest_clear_sensor_recov_alerts();
342 
343  // Initialize OTBN app, load it, and get interface to OTBN data memory.
344  OTBN_DECLARE_APP_SYMBOLS(otbn_char_bn_wsrr);
345  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_bn_wsrr, otbn_res_values_wdr);
346  const otbn_app_t kOtbnAppCharBnWsrr = OTBN_APP_T_INIT(otbn_char_bn_wsrr);
347  static const otbn_addr_t kOtbnAppCharBnWsrrResValuesWDR =
348  OTBN_ADDR_T_INIT(otbn_char_bn_wsrr, otbn_res_values_wdr);
349 
350  // Load app and write received big_num into DMEM.
351  otbn_load_app(kOtbnAppCharBnWsrr);
352 
353  // FI code target.
354  pentest_set_trigger_high();
355  otbn_execute();
356  otbn_busy_wait_for_done();
357  pentest_set_trigger_low();
358 
359  // Get registered alerts from alert handler.
360  reg_alerts = pentest_get_triggered_alerts();
361  // Get fatal and recoverable AST alerts from sensor controller.
362  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
363 
364  // Read ERR_STATUS register from OTBN.
365  dif_otbn_err_bits_t err_otbn;
366  read_otbn_err_bits(&err_otbn);
367 
368  // Read ERR_STATUS register from Ibex.
369  dif_rv_core_ibex_error_status_t err_ibx;
370  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
371 
372  // Read DMEM
373  otbn_fi_data_t uj_output;
374  uj_output.res = 0;
375  memset(uj_output.data, 0, sizeof(uj_output.data));
376  TRY(dif_otbn_dmem_read(&otbn, kOtbnAppCharBnWsrrResValuesWDR, uj_output.data,
377  sizeof(uj_output.data)));
378  // Read OTBN instruction counter
379  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
380 
381  // Clear OTBN memory.
382  TRY(clear_otbn());
383 
384  // Send result & ERR_STATUS to host.
385  uj_output.err_otbn = err_otbn;
386  uj_output.err_ibx = err_ibx;
387  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
388  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
389  sizeof(sensor_alerts.alerts));
390  RESP_OK(ujson_serialize_otbn_fi_data_t, uj, &uj_output);
391 
392  return OK_STATUS();
393 }
394 
395 status_t handle_otbn_fi_char_bne(ujson_t *uj) {
396  // Clear registered alerts in alert handler.
397  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
398  // Clear the AST recoverable alerts.
399  pentest_clear_sensor_recov_alerts();
400 
401  // Initialize OTBN app, load it, and get interface to OTBN data memory.
402  OTBN_DECLARE_APP_SYMBOLS(otbn_char_bne);
403  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_bne, res);
404  const otbn_app_t kOtbnAppCharBne = OTBN_APP_T_INIT(otbn_char_bne);
405  static const otbn_addr_t kOtbnAppCharBneRes =
406  OTBN_ADDR_T_INIT(otbn_char_bne, res);
407  otbn_load_app(kOtbnAppCharBne);
408 
409  // FI code target.
410  pentest_set_trigger_high();
411  otbn_execute();
412  otbn_busy_wait_for_done();
413  pentest_set_trigger_low();
414 
415  // Get registered alerts from alert handler.
416  reg_alerts = pentest_get_triggered_alerts();
417  // Get fatal and recoverable AST alerts from sensor controller.
418  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
419  // Read counter (x1) from OTBN data memory.
420  otbn_fi_result_cnt_t uj_output;
421  uj_output.result = 0;
422  otbn_dmem_read(1, kOtbnAppCharBneRes, &uj_output.result);
423 
424  // Read OTBN instruction counter.
425  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
426 
427  // Read ERR_STATUS register from OTBN.
428  dif_otbn_err_bits_t err_otbn;
429  read_otbn_err_bits(&err_otbn);
430 
431  // Read ERR_STATUS register from Ibex.
432  dif_rv_core_ibex_error_status_t err_ibx;
433  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
434  // Clear OTBN memory.
435  TRY(clear_otbn());
436 
437  // Send back to host.
438  uj_output.err_otbn = err_otbn;
439  uj_output.err_ibx = err_ibx;
440  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
441  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
442  sizeof(sensor_alerts.alerts));
443  RESP_OK(ujson_serialize_otbn_fi_result_cnt_t, uj, &uj_output);
444  return OK_STATUS();
445 }
446 
447 status_t handle_otbn_fi_char_dmem_access(ujson_t *uj) {
448  // Clear registered alerts in alert handler.
449  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
450  // Clear the AST recoverable alerts.
451  pentest_clear_sensor_recov_alerts();
452 
453  // Config for the otbn.fi.char_dmem_access test.
454  OTBN_DECLARE_APP_SYMBOLS(otbn_char_dmem_access);
455  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_dmem_access, values);
456  static const otbn_app_t kOtbnAppCharDmemAccess =
457  OTBN_APP_T_INIT(otbn_char_dmem_access);
458  static const otbn_addr_t kOtbnVarCharDmemAccessValues =
459  OTBN_ADDR_T_INIT(otbn_char_dmem_access, values);
460 
461  otbn_load_app(kOtbnAppCharDmemAccess);
462 
463  // FI code target.
464  pentest_set_trigger_high();
465  otbn_execute();
466  otbn_busy_wait_for_done();
467  pentest_set_trigger_low();
468 
469  // Get registered alerts from alert handler.
470  reg_alerts = pentest_get_triggered_alerts();
471  // Get fatal and recoverable AST alerts from sensor controller.
472  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
473 
474  // Read ERR_STATUS register from OTBN.
475  dif_otbn_err_bits_t err_otbn;
476  read_otbn_err_bits(&err_otbn);
477 
478  // Read ERR_STATUS register from Ibex.
479  dif_rv_core_ibex_error_status_t err_ibx;
480  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
481 
482  // Read DMEM
483  otbn_fi_data_t uj_output;
484  uj_output.res = 0;
485  memset(uj_output.data, 0, sizeof(uj_output.data));
486  TRY(dif_otbn_dmem_read(&otbn, kOtbnVarCharDmemAccessValues, uj_output.data,
487  sizeof(uj_output.data)));
488  // Read OTBN instruction counter
489  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
490 
491  // Send result & ERR_STATUS to host.
492  uj_output.err_otbn = err_otbn;
493  uj_output.err_ibx = err_ibx;
494  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
495  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
496  sizeof(sensor_alerts.alerts));
497  RESP_OK(ujson_serialize_otbn_fi_data_t, uj, &uj_output);
498 
499  return OK_STATUS();
500 }
501 
502 status_t handle_otbn_fi_char_dmem_write(ujson_t *uj) {
503  // Clear registered alerts in alert handler.
504  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
505  // Clear the AST recoverable alerts.
506  pentest_clear_sensor_recov_alerts();
507 
508  // Config for the otbn.fi.char_rf test.
509  OTBN_DECLARE_APP_SYMBOLS(otbn_char_dmem_write);
510  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_dmem_write, mem);
511 
512  static const otbn_app_t kOtbnAppCharDmemWrite =
513  OTBN_APP_T_INIT(otbn_char_dmem_write);
514  static const otbn_addr_t kOtbnVarCharDmemWriteMem =
515  OTBN_ADDR_T_INIT(otbn_char_dmem_write, mem);
516 
517  // Init application and load reference values into DMEM.
518  otbn_load_app(kOtbnAppCharDmemWrite);
519  // FI code target.
520  pentest_set_trigger_high();
521  asm volatile(NOP30);
522  // Unrolled instruction sequence.
523  mmio_region_write32(
524  otbn.base_addr,
525  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem),
526  ref_values[0]);
527  mmio_region_write32(
528  otbn.base_addr,
529  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 4),
530  ref_values[1]);
531  mmio_region_write32(
532  otbn.base_addr,
533  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 8),
534  ref_values[2]);
535  mmio_region_write32(
536  otbn.base_addr,
537  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 12),
538  ref_values[3]);
539  mmio_region_write32(
540  otbn.base_addr,
541  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 16),
542  ref_values[4]);
543  mmio_region_write32(
544  otbn.base_addr,
545  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 20),
546  ref_values[5]);
547  mmio_region_write32(
548  otbn.base_addr,
549  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 24),
550  ref_values[6]);
551  mmio_region_write32(
552  otbn.base_addr,
553  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 28),
554  ref_values[7]);
555  mmio_region_write32(
556  otbn.base_addr,
557  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 32),
558  ref_values[8]);
559  mmio_region_write32(
560  otbn.base_addr,
561  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 36),
562  ref_values[9]);
563  mmio_region_write32(
564  otbn.base_addr,
565  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 40),
566  ref_values[10]);
567  mmio_region_write32(
568  otbn.base_addr,
569  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 44),
570  ref_values[11]);
571  mmio_region_write32(
572  otbn.base_addr,
573  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 48),
574  ref_values[12]);
575  mmio_region_write32(
576  otbn.base_addr,
577  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 52),
578  ref_values[13]);
579  mmio_region_write32(
580  otbn.base_addr,
581  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 56),
582  ref_values[14]);
583  mmio_region_write32(
584  otbn.base_addr,
585  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 60),
586  ref_values[15]);
587  mmio_region_write32(
588  otbn.base_addr,
589  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 64),
590  ref_values[16]);
591  mmio_region_write32(
592  otbn.base_addr,
593  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 68),
594  ref_values[17]);
595  mmio_region_write32(
596  otbn.base_addr,
597  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 72),
598  ref_values[18]);
599  mmio_region_write32(
600  otbn.base_addr,
601  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 76),
602  ref_values[19]);
603  mmio_region_write32(
604  otbn.base_addr,
605  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 80),
606  ref_values[20]);
607  mmio_region_write32(
608  otbn.base_addr,
609  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 84),
610  ref_values[21]);
611  mmio_region_write32(
612  otbn.base_addr,
613  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 88),
614  ref_values[22]);
615  mmio_region_write32(
616  otbn.base_addr,
617  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 92),
618  ref_values[23]);
619  mmio_region_write32(
620  otbn.base_addr,
621  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 96),
622  ref_values[24]);
623  mmio_region_write32(
624  otbn.base_addr,
625  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 100),
626  ref_values[25]);
627  mmio_region_write32(
628  otbn.base_addr,
629  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 104),
630  ref_values[26]);
631  mmio_region_write32(
632  otbn.base_addr,
633  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 108),
634  ref_values[27]);
635  mmio_region_write32(
636  otbn.base_addr,
637  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 112),
638  ref_values[28]);
639  mmio_region_write32(
640  otbn.base_addr,
641  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 116),
642  ref_values[29]);
643  mmio_region_write32(
644  otbn.base_addr,
645  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 120),
646  ref_values[30]);
647  mmio_region_write32(
648  otbn.base_addr,
649  (ptrdiff_t)(OTBN_DMEM_REG_OFFSET + kOtbnVarCharDmemWriteMem + 124),
650  ref_values[31]);
651  asm volatile(NOP10);
652  pentest_set_trigger_low();
653 
654  // Execute OTBN application.
655  otbn_execute();
656  otbn_busy_wait_for_done();
657 
658  // Get registered alerts from alert handler.
659  reg_alerts = pentest_get_triggered_alerts();
660  // Get fatal and recoverable AST alerts from sensor controller.
661  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
662 
663  // Read ERR_STATUS register from OTBN.
664  dif_otbn_err_bits_t err_otbn;
665  read_otbn_err_bits(&err_otbn);
666 
667  // Read ERR_STATUS register from Ibex.
668  dif_rv_core_ibex_error_status_t err_ibx;
669  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
670 
671  // Compare reference values.
672  otbn_fi_result_array_t uj_output;
673  uint32_t res_values[ARRAYSIZE(ref_values)];
674  memset(res_values, 0, sizeof(res_values));
675  TRY(dif_otbn_dmem_read(&otbn, kOtbnVarCharDmemWriteMem, res_values,
676  sizeof(res_values)));
677  for (size_t it = 0; it < ARRAYSIZE(ref_values); it++) {
678  uj_output.result[it] = res_values[it] ^ ref_values[it];
679  }
680 
681  // Read OTBN instruction counter.
682  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
683 
684  // Clear OTBN memory.
685  TRY(clear_otbn());
686 
687  // Send result & ERR_STATUS to host.
688  uj_output.err_otbn = err_otbn;
689  uj_output.err_ibx = err_ibx;
690  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
691  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
692  sizeof(sensor_alerts.alerts));
693  RESP_OK(ujson_serialize_otbn_fi_result_array_t, uj, &uj_output);
694 
695  return OK_STATUS();
696 }
697 
698 status_t handle_otbn_fi_char_hardware_dmem_op_loop(ujson_t *uj) {
699  // Clear registered alerts in alert handler.
700  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
701  // Clear the AST recoverable alerts.
702  pentest_clear_sensor_recov_alerts();
703 
704  // Initialize OTBN app, load it, and get interface to OTBN data memory.
705  OTBN_DECLARE_APP_SYMBOLS(otbn_char_hardware_dmem_op_loop);
706  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_hardware_dmem_op_loop, lc);
707  const otbn_app_t kOtbnAppCharHardwareDmemOpLoop =
708  OTBN_APP_T_INIT(otbn_char_hardware_dmem_op_loop);
709  static const otbn_addr_t kOtbnAppCharHardwareDmemOpLoopLC =
710  OTBN_ADDR_T_INIT(otbn_char_hardware_dmem_op_loop, lc);
711  otbn_load_app(kOtbnAppCharHardwareDmemOpLoop);
712 
713  uint32_t loop_counter;
714 
715  // FI code target.
716  pentest_set_trigger_high();
717  otbn_execute();
718  otbn_busy_wait_for_done();
719  pentest_set_trigger_low();
720  // Get registered alerts from alert handler.
721  reg_alerts = pentest_get_triggered_alerts();
722  // Get fatal and recoverable AST alerts from sensor controller.
723  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
724 
725  // Read loop counter from OTBN data memory.
726  otbn_dmem_read(1, kOtbnAppCharHardwareDmemOpLoopLC, &loop_counter);
727 
728  // Read ERR_STATUS register from OTBN.
729  dif_otbn_err_bits_t err_otbn;
730  read_otbn_err_bits(&err_otbn);
731 
732  // Read ERR_STATUS register from Ibex.
733  dif_rv_core_ibex_error_status_t err_ibx;
734  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
735 
736  // Clear OTBN memory.
737  TRY(clear_otbn());
738 
739  // Send loop counter & ERR_STATUS to host.
740  otbn_fi_loop_counter_t uj_output;
741  uj_output.loop_counter = loop_counter;
742  uj_output.err_otbn = err_otbn;
743  uj_output.err_ibx = err_ibx;
744  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
745  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
746  sizeof(sensor_alerts.alerts));
747  RESP_OK(ujson_serialize_otbn_fi_loop_counter_t, uj, &uj_output);
748  return OK_STATUS();
749 }
750 
751 status_t handle_otbn_fi_char_hardware_reg_op_loop(ujson_t *uj) {
752  // Clear registered alerts in alert handler.
753  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
754  // Clear the AST recoverable alerts.
755  pentest_clear_sensor_recov_alerts();
756 
757  // Initialize OTBN app, load it, and get interface to OTBN data memory.
758  OTBN_DECLARE_APP_SYMBOLS(otbn_char_hardware_reg_op_loop);
759  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_hardware_reg_op_loop, lc);
760  const otbn_app_t kOtbnAppCharHardwareRegOpLoop =
761  OTBN_APP_T_INIT(otbn_char_hardware_reg_op_loop);
762  static const otbn_addr_t kOtbnAppCharHardwareRegOpLoopLC =
763  OTBN_ADDR_T_INIT(otbn_char_hardware_reg_op_loop, lc);
764  otbn_load_app(kOtbnAppCharHardwareRegOpLoop);
765 
766  uint32_t loop_counter;
767 
768  // FI code target.
769  pentest_set_trigger_high();
770  otbn_execute();
771  otbn_busy_wait_for_done();
772  pentest_set_trigger_low();
773  // Get registered alerts from alert handler.
774  reg_alerts = pentest_get_triggered_alerts();
775  // Get fatal and recoverable AST alerts from sensor controller.
776  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
777 
778  // Read loop counter from OTBN data memory.
779  otbn_dmem_read(1, kOtbnAppCharHardwareRegOpLoopLC, &loop_counter);
780 
781  // Read ERR_STATUS register from OTBN.
782  dif_otbn_err_bits_t err_otbn;
783  read_otbn_err_bits(&err_otbn);
784 
785  // Read ERR_STATUS register from Ibex.
786  dif_rv_core_ibex_error_status_t err_ibx;
787  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
788 
789  // Clear OTBN memory.
790  TRY(clear_otbn());
791 
792  // Send loop counter & ERR_STATUS to host.
793  otbn_fi_loop_counter_t uj_output;
794  uj_output.loop_counter = loop_counter;
795  uj_output.err_otbn = err_otbn;
796  uj_output.err_ibx = err_ibx;
797  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
798  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
799  sizeof(sensor_alerts.alerts));
800  RESP_OK(ujson_serialize_otbn_fi_loop_counter_t, uj, &uj_output);
801  return OK_STATUS();
802 }
803 
804 status_t handle_otbn_fi_char_jal(ujson_t *uj) {
805  // Clear registered alerts in alert handler.
806  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
807  // Clear the AST recoverable alerts.
808  pentest_clear_sensor_recov_alerts();
809 
810  // Initialize OTBN app, load it, and get interface to OTBN data memory.
811  OTBN_DECLARE_APP_SYMBOLS(otbn_char_jal);
812  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_jal, res);
813  const otbn_app_t kOtbnAppCharJal = OTBN_APP_T_INIT(otbn_char_jal);
814  static const otbn_addr_t kOtbnAppCharJalRes =
815  OTBN_ADDR_T_INIT(otbn_char_jal, res);
816  otbn_load_app(kOtbnAppCharJal);
817 
818  // FI code target.
819  pentest_set_trigger_high();
820  otbn_execute();
821  otbn_busy_wait_for_done();
822  pentest_set_trigger_low();
823  // Get registered alerts from alert handler.
824  reg_alerts = pentest_get_triggered_alerts();
825  // Get fatal and recoverable AST alerts from sensor controller.
826  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
827 
828  // Read counter (x1) from OTBN data memory.
829  otbn_fi_result_cnt_t uj_output;
830  uj_output.result = 0;
831  otbn_dmem_read(1, kOtbnAppCharJalRes, &uj_output.result);
832 
833  // Read OTBN instruction counter.
834  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
835 
836  // Read ERR_STATUS register from OTBN.
837  dif_otbn_err_bits_t err_otbn;
838  read_otbn_err_bits(&err_otbn);
839 
840  // Read ERR_STATUS register from Ibex.
841  dif_rv_core_ibex_error_status_t err_ibx;
842  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
843 
844  // Clear OTBN memory.
845  TRY(clear_otbn());
846 
847  // Send back to host.
848  uj_output.err_otbn = err_otbn;
849  uj_output.err_ibx = err_ibx;
850  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
851  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
852  sizeof(sensor_alerts.alerts));
853  RESP_OK(ujson_serialize_otbn_fi_result_cnt_t, uj, &uj_output);
854  return OK_STATUS();
855 }
856 
857 status_t handle_otbn_fi_char_lw(ujson_t *uj) {
858  // Clear registered alerts in alert handler.
859  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
860  // Clear the AST recoverable alerts.
861  pentest_clear_sensor_recov_alerts();
862 
863  // Initialize OTBN app, load it, and get interface to OTBN data memory.
864  OTBN_DECLARE_APP_SYMBOLS(otbn_char_lw);
865  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_lw, mem_in);
866  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_lw, mem_out);
867  const otbn_app_t kOtbnAppCharLw = OTBN_APP_T_INIT(otbn_char_lw);
868  static const otbn_addr_t kOtbnMemIn = OTBN_ADDR_T_INIT(otbn_char_lw, mem_in);
869  static const otbn_addr_t kOtbnMemOut =
870  OTBN_ADDR_T_INIT(otbn_char_lw, mem_out);
871 
872  // Load app and write reference values into mem_in DMEM.
873  otbn_load_app(kOtbnAppCharLw);
874  TRY(dif_otbn_dmem_write(&otbn, kOtbnMemIn, ref_values, sizeof(ref_values)));
875 
876  // FI code target.
877  pentest_set_trigger_high();
878  otbn_execute();
879  otbn_busy_wait_for_done();
880  pentest_set_trigger_low();
881 
882  // Get registered alerts from alert handler.
883  reg_alerts = pentest_get_triggered_alerts();
884  // Get fatal and recoverable AST alerts from sensor controller.
885  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
886 
887  // Compare reference values. 29 values as we are loading into 29 registers.
888  otbn_fi_result_array_t uj_output;
889  uint32_t res_values[29];
890  memset(res_values, 0, sizeof(res_values));
891  memset(uj_output.result, 0, sizeof(uj_output.result));
892  TRY(dif_otbn_dmem_read(&otbn, kOtbnMemOut, res_values, sizeof(res_values)));
893  for (size_t it = 0; it < 29; it++) {
894  uj_output.result[it] = res_values[it] ^ ref_values[it];
895  }
896 
897  // Read OTBN instruction counter.
898  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
899 
900  // Read ERR_STATUS register from OTBN.
901  dif_otbn_err_bits_t err_otbn;
902  read_otbn_err_bits(&err_otbn);
903 
904  // Read ERR_STATUS register from Ibex.
905  dif_rv_core_ibex_error_status_t err_ibx;
906  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
907 
908  // Clear OTBN memory.
909  TRY(clear_otbn());
910 
911  // Send back to host.
912  uj_output.err_otbn = err_otbn;
913  uj_output.err_ibx = err_ibx;
914  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
915  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
916  sizeof(sensor_alerts.alerts));
917  RESP_OK(ujson_serialize_otbn_fi_result_array_t, uj, &uj_output);
918  return OK_STATUS();
919 }
920 
921 status_t handle_otbn_fi_char_mem(ujson_t *uj) {
922  // Get the test mode. The test mode only can be set at the beginning of a
923  // test.
924  if (!char_mem_test_cfg_valid) {
925  otbn_fi_mem_cfg_t uj_cfg;
926  TRY(ujson_deserialize_otbn_fi_mem_cfg_t(uj, &uj_cfg));
927  char_mem_imem = uj_cfg.imem;
928  char_mem_dmem = uj_cfg.dmem;
929  char_mem_byte_offset = uj_cfg.byte_offset;
930  char_mem_num_words = uj_cfg.num_words;
931  // Set config to valid.
932  char_mem_test_cfg_valid = true;
933  }
934 
935  // Clear registered alerts in alert handler.
936  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
937  // Clear the AST recoverable alerts.
938  pentest_clear_sensor_recov_alerts();
939 
940  // Reference values for DMEM and IMEM.
941  uint32_t dmem_array_ref[char_mem_num_words];
942  uint32_t imem_array_ref[char_mem_num_words];
943  if (char_mem_dmem) {
944  memset(dmem_array_ref, 0xab, sizeof(dmem_array_ref));
945  }
946  if (char_mem_imem) {
947  memset(imem_array_ref, 0xdf, sizeof(imem_array_ref));
948  }
949 
950  if (!char_mem_init) {
951  if (char_mem_dmem) {
952  TRY(dif_otbn_dmem_write(&otbn, char_mem_byte_offset, dmem_array_ref,
953  sizeof(dmem_array_ref)));
954  }
955  if (char_mem_imem) {
956  TRY(dif_otbn_imem_write(&otbn, char_mem_byte_offset, imem_array_ref,
957  sizeof(imem_array_ref)));
958  }
959  char_mem_init = true;
960  }
961 
962  // FI code target.
963  pentest_set_trigger_high();
964  asm volatile(NOP100);
965  pentest_set_trigger_low();
966 
967  // Get registered alerts from alert handler.
968  reg_alerts = pentest_get_triggered_alerts();
969  // Get fatal and recoverable AST alerts from sensor controller.
970  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
971 
972  // Read ERR_STATUS register from OTBN.
973  dif_otbn_err_bits_t err_otbn;
974  read_otbn_err_bits(&err_otbn);
975 
976  // Read ERR_STATUS register from Ibex.
977  dif_rv_core_ibex_error_status_t err_ibx;
978  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
979 
980  otbn_fi_mem_t uj_output;
981  // Init with all 0 for defaults.
982  memset(uj_output.dmem_data, 0, sizeof(uj_output.dmem_data));
983  memset(uj_output.dmem_addr, 0, sizeof(uj_output.dmem_addr));
984  memset(uj_output.imem_data, 0, sizeof(uj_output.imem_data));
985  memset(uj_output.imem_addr, 0, sizeof(uj_output.imem_addr));
986  uj_output.res = 0;
987 
988  // Check DMEM for data errors.
989  size_t fault_pos = 0;
990  if (char_mem_dmem) {
991  uint32_t dmem_array_res[char_mem_num_words];
992  TRY(dif_otbn_dmem_read(&otbn, char_mem_byte_offset, dmem_array_res,
993  sizeof(dmem_array_ref)));
994  for (size_t it = 0; it < char_mem_num_words; it++) {
995  if (dmem_array_res[it] != dmem_array_ref[it] &&
996  fault_pos < ARRAYSIZE(uj_output.dmem_data)) {
997  uj_output.dmem_data[fault_pos] = dmem_array_res[it];
998  uj_output.dmem_addr[fault_pos] = it;
999  fault_pos++;
1000  // Re-init memory.
1001  char_mem_init = false;
1002  uj_output.res = 1;
1003  }
1004  }
1005  }
1006 
1007  // Check IMEM for data errors.
1008  uint32_t imem_array_res[char_mem_num_words];
1009  if (char_mem_imem) {
1010  TRY(dif_otbn_imem_read(&otbn, char_mem_byte_offset, imem_array_res,
1011  sizeof(imem_array_ref)));
1012  fault_pos = 0;
1013  for (size_t it = 0; it < char_mem_num_words; it++) {
1014  if (imem_array_res[it] != imem_array_ref[it] &&
1015  fault_pos < ARRAYSIZE(uj_output.imem_data)) {
1016  uj_output.imem_data[fault_pos] = imem_array_res[it];
1017  uj_output.imem_addr[fault_pos] = it;
1018  fault_pos++;
1019  // Re-init memory.
1020  char_mem_init = false;
1021  uj_output.res = 1;
1022  }
1023  }
1024  }
1025 
1026  // Send result & ERR_STATUS to host.
1027  uj_output.err_otbn = err_otbn;
1028  uj_output.err_ibx = err_ibx;
1029  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1030  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1031  sizeof(sensor_alerts.alerts));
1032  RESP_OK(ujson_serialize_otbn_fi_mem_t, uj, &uj_output);
1033 
1034  return OK_STATUS();
1035 }
1036 
1037 status_t handle_otbn_fi_char_register_file(ujson_t *uj) {
1038  // Clear registered alerts in alert handler.
1039  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1040  // Clear the AST recoverable alerts.
1041  pentest_clear_sensor_recov_alerts();
1042 
1043  // Config for the otbn.fi.char_rf test.
1044  OTBN_DECLARE_APP_SYMBOLS(otbn_char_rf);
1045  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_rf, otbn_ref_values);
1046  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_rf, otbn_res_values_gpr);
1047  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_rf, otbn_res_values_wdr);
1048 
1049  static const otbn_app_t kOtbnAppCharRF = OTBN_APP_T_INIT(otbn_char_rf);
1050  static const otbn_addr_t kOtbnVarCharRFRefValues =
1051  OTBN_ADDR_T_INIT(otbn_char_rf, otbn_ref_values);
1052  static const otbn_addr_t kOtbnVarCharRFResValuesGPR =
1053  OTBN_ADDR_T_INIT(otbn_char_rf, otbn_res_values_gpr);
1054  static const otbn_addr_t kOtbnVarCharRFResValuesWDR =
1055  OTBN_ADDR_T_INIT(otbn_char_rf, otbn_res_values_wdr);
1056 
1057  // Init application and load reference values into DMEM.
1058  otbn_load_app(kOtbnAppCharRF);
1059  TRY(dif_otbn_dmem_write(&otbn, kOtbnVarCharRFRefValues, ref_values,
1060  sizeof(ref_values)));
1061 
1062  pentest_set_trigger_high();
1063  otbn_execute();
1064  otbn_busy_wait_for_done();
1065  pentest_set_trigger_low();
1066 
1067  // Get registered alerts from alert handler.
1068  reg_alerts = pentest_get_triggered_alerts();
1069  // Get fatal and recoverable AST alerts from sensor controller.
1070  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1071 
1072  // Read ERR_STATUS register from OTBN.
1073  dif_otbn_err_bits_t err_otbn;
1074  read_otbn_err_bits(&err_otbn);
1075 
1076  // Read ERR_STATUS register from Ibex.
1077  dif_rv_core_ibex_error_status_t err_ibx;
1078  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
1079 
1080  // Read GPR RF values from DMEM.
1081  uint32_t res_values_gpr[29];
1082  memset(res_values_gpr, 0, sizeof(res_values_gpr));
1083  TRY(dif_otbn_dmem_read(&otbn, kOtbnVarCharRFResValuesGPR, res_values_gpr,
1084  sizeof(res_values_gpr)));
1085 
1086  // Compare GPR RF values to reference values.
1087  otbn_fi_rf_char_t uj_output;
1088  memset(uj_output.faulty_gpr, 0, sizeof(uj_output.faulty_gpr));
1089  uj_output.res = 0;
1090  for (size_t it = 0; it < ARRAYSIZE(res_values_gpr); it++) {
1091  if (res_values_gpr[it] != ref_values[it]) {
1092  uj_output.res = 1;
1093  // Report reference value XOR faulty value back to also detect faulty
1094  // values that are 0.
1095  uj_output.faulty_gpr[it] = res_values_gpr[it] ^ ref_values[it];
1096  }
1097  }
1098 
1099  // Read WDR RF values from DMEM.
1100  uint32_t res_values_wdr[256];
1101  memset(res_values_wdr, 0, sizeof(res_values_wdr));
1102  TRY(dif_otbn_dmem_read(&otbn, kOtbnVarCharRFResValuesWDR, res_values_wdr,
1103  sizeof(res_values_wdr)));
1104 
1105  // Compare WDR RF values to reference values.
1106  memset(uj_output.faulty_wdr, 0, sizeof(uj_output.faulty_wdr));
1107  for (size_t it = 0; it < ARRAYSIZE(res_values_wdr); it++) {
1108  if (res_values_wdr[it] != ref_values[it % 32]) {
1109  uj_output.res = 1;
1110  // Report reference value XOR faulty value back to also detect faulty
1111  // values that are 0.
1112  uj_output.faulty_wdr[it] = res_values_wdr[it] ^ ref_values[it % 32];
1113  }
1114  }
1115 
1116  // Send result & ERR_STATUS to host.
1117  uj_output.err_otbn = err_otbn;
1118  uj_output.err_ibx = err_ibx;
1119  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1120  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1121  sizeof(sensor_alerts.alerts));
1122  RESP_OK(ujson_serialize_otbn_fi_rf_char_t, uj, &uj_output);
1123 
1124  return OK_STATUS();
1125 }
1126 
1127 status_t handle_otbn_fi_char_unrolled_dmem_op_loop(ujson_t *uj) {
1128  // Clear registered alerts in alert handler.
1129  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1130  // Clear the AST recoverable alerts.
1131  pentest_clear_sensor_recov_alerts();
1132 
1133  // Initialize OTBN app, load it, and get interface to OTBN data memory.
1134  OTBN_DECLARE_APP_SYMBOLS(otbn_char_unrolled_dmem_op_loop);
1135  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_unrolled_dmem_op_loop, lc);
1136  const otbn_app_t kOtbnAppCharUnrolledDmemOpLoop =
1137  OTBN_APP_T_INIT(otbn_char_unrolled_dmem_op_loop);
1138  static const otbn_addr_t kOtbnAppCharUnrolledDmemOpLoopLC =
1139  OTBN_ADDR_T_INIT(otbn_char_unrolled_dmem_op_loop, lc);
1140  otbn_load_app(kOtbnAppCharUnrolledDmemOpLoop);
1141 
1142  uint32_t loop_counter;
1143 
1144  // FI code target.
1145  pentest_set_trigger_high();
1146  otbn_execute();
1147  otbn_busy_wait_for_done();
1148  pentest_set_trigger_low();
1149  // Get registered alerts from alert handler.
1150  reg_alerts = pentest_get_triggered_alerts();
1151  // Get fatal and recoverable AST alerts from sensor controller.
1152  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1153 
1154  // Read loop counter from OTBN data memory.
1155  otbn_dmem_read(1, kOtbnAppCharUnrolledDmemOpLoopLC, &loop_counter);
1156 
1157  // Read ERR_STATUS register from OTBN.
1158  dif_otbn_err_bits_t err_otbn;
1159  read_otbn_err_bits(&err_otbn);
1160 
1161  // Read ERR_STATUS register from Ibex.
1162  dif_rv_core_ibex_error_status_t err_ibx;
1163  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
1164 
1165  // Clear OTBN memory.
1166  TRY(clear_otbn());
1167 
1168  // Send loop counter & ERR_STATUS to host.
1169  otbn_fi_loop_counter_t uj_output;
1170  uj_output.loop_counter = loop_counter;
1171  uj_output.err_otbn = err_otbn;
1172  uj_output.err_ibx = err_ibx;
1173  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1174  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1175  sizeof(sensor_alerts.alerts));
1176  RESP_OK(ujson_serialize_otbn_fi_loop_counter_t, uj, &uj_output);
1177  return OK_STATUS();
1178 }
1179 
1180 status_t handle_otbn_fi_char_unrolled_reg_op_loop(ujson_t *uj) {
1181  // Clear registered alerts in alert handler.
1182  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1183  // Clear the AST recoverable alerts.
1184  pentest_clear_sensor_recov_alerts();
1185 
1186  // Initialize OTBN app, load it, and get interface to OTBN data memory.
1187  OTBN_DECLARE_APP_SYMBOLS(otbn_char_unrolled_reg_op_loop);
1188  OTBN_DECLARE_SYMBOL_ADDR(otbn_char_unrolled_reg_op_loop, lc);
1189  const otbn_app_t kOtbnAppCharUnrolledRegOpLoop =
1190  OTBN_APP_T_INIT(otbn_char_unrolled_reg_op_loop);
1191  static const otbn_addr_t kOtbnAppCharUnrolledRegOpLoopLC =
1192  OTBN_ADDR_T_INIT(otbn_char_unrolled_reg_op_loop, lc);
1193  otbn_load_app(kOtbnAppCharUnrolledRegOpLoop);
1194 
1195  uint32_t loop_counter;
1196 
1197  // FI code target.
1198  pentest_set_trigger_high();
1199  otbn_execute();
1200  otbn_busy_wait_for_done();
1201  pentest_set_trigger_low();
1202  // Get registered alerts from alert handler.
1203  reg_alerts = pentest_get_triggered_alerts();
1204  // Get fatal and recoverable AST alerts from sensor controller.
1205  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1206 
1207  // Read loop counter from OTBN data memory.
1208  otbn_dmem_read(1, kOtbnAppCharUnrolledRegOpLoopLC, &loop_counter);
1209 
1210  // Read ERR_STATUS register from OTBN.
1211  dif_otbn_err_bits_t err_otbn;
1212  read_otbn_err_bits(&err_otbn);
1213 
1214  // Read ERR_STATUS register from Ibex.
1215  dif_rv_core_ibex_error_status_t err_ibx;
1216  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
1217 
1218  // Clear OTBN memory.
1219  TRY(clear_otbn());
1220 
1221  // Send loop counter & ERR_STATUS to host.
1222  otbn_fi_loop_counter_t uj_output;
1223  uj_output.loop_counter = loop_counter;
1224  uj_output.err_otbn = err_otbn;
1225  uj_output.err_ibx = err_ibx;
1226  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1227  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1228  sizeof(sensor_alerts.alerts));
1229  RESP_OK(ujson_serialize_otbn_fi_loop_counter_t, uj, &uj_output);
1230  return OK_STATUS();
1231 }
1232 
1233 status_t handle_otbn_fi_init(ujson_t *uj) {
1234  penetrationtest_cpuctrl_t uj_data;
1235  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
1236 
1237  // Configure the entropy complex for OTBN. Set the reseed interval to max
1238  // to avoid a non-constant trigger window.
1239  TRY(pentest_configure_entropy_source_max_reseed_interval());
1240 
1241  pentest_select_trigger_type(kPentestTriggerTypeSw);
1242  pentest_init(kPentestTriggerSourceOtbn,
1243  kPentestPeripheralIoDiv4 | kPentestPeripheralEdn |
1244  kPentestPeripheralCsrng | kPentestPeripheralEntropy |
1245  kPentestPeripheralAes | kPentestPeripheralHmac |
1246  kPentestPeripheralKmac | kPentestPeripheralOtbn);
1247 
1248  // Configure Ibex to allow reading ERR_STATUS register.
1249  TRY(dif_rv_core_ibex_init(
1251  &rv_core_ibex));
1252 
1253  // Init the OTBN core.
1254  TRY(dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn));
1255 
1256  // Configure the alert handler. Alerts triggered by IP blocks are captured
1257  // and reported to the test.
1258  pentest_configure_alert_handler();
1259 
1260  // Configure the CPU for the pentest.
1261  penetrationtest_device_info_t uj_output;
1262  TRY(pentest_configure_cpu(
1263  uj_data.icache_disable, uj_data.dummy_instr_disable,
1264  uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
1265  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
1266  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
1267  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
1268  ;
1269 
1270  // The load integrity, key sideloading, and char_mem tests get initialized at
1271  // the first run.
1272  load_integrity_init = false;
1273  key_sideloading_init = false;
1274  char_mem_init = false;
1275  char_mem_test_cfg_valid = false;
1276 
1277  // Read device ID and return to host.
1278  TRY(pentest_read_device_id(uj_output.device_id));
1279  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
1280 
1281  return OK_STATUS();
1282 }
1283 
1284 status_t handle_otbn_fi_init_keymgr(ujson_t *uj) {
1285  dif_kmac_t kmac;
1286  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
1288  &keymgr));
1289  TRY(keymgr_testutils_initialize(&keymgr, &kmac));
1290 
1291  dif_keymgr_versioned_key_params_t sideload_params = kKeyVersionedParamsOTBNFI;
1292  sideload_params.dest = kDifKeymgrVersionedKeyDestOtbn;
1293  TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params));
1294  return OK_STATUS();
1295 }
1296 
1297 status_t handle_otbn_fi_key_sideload(ujson_t *uj) {
1298  TRY(dif_otbn_set_ctrl_software_errs_fatal(&otbn, /*enable=*/false));
1299  // Clear registered alerts in alert handler.
1300  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1301  // Clear the AST recoverable alerts.
1302  pentest_clear_sensor_recov_alerts();
1303 
1304  if (!key_sideloading_init) {
1305  // Setup keymanager for sideloading key into OTBN.
1306  otbn_load_app(kOtbnAppKeySideload);
1307  // Get reference keys.
1308  otbn_execute();
1309  otbn_busy_wait_for_done();
1310 
1311  otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l_ref);
1312  otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h_ref);
1313  otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l_ref);
1314  otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h_ref);
1315 
1316  key_sideloading_init = true;
1317  }
1318 
1319  // FI code target.
1320  pentest_set_trigger_high();
1321  otbn_execute();
1322  otbn_busy_wait_for_done();
1323  pentest_set_trigger_low();
1324 
1325  // Get registered alerts from alert handler.
1326  reg_alerts = pentest_get_triggered_alerts();
1327  // Get fatal and recoverable AST alerts from sensor controller.
1328  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1329 
1330  // Read loop counter from OTBN data memory.
1331  uint32_t key_share_0_l, key_share_0_h;
1332  uint32_t key_share_1_l, key_share_1_h;
1333  otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l);
1334  otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h);
1335  otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l);
1336  otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h);
1337 
1338  // Read ERR_STATUS register from OTBN.
1339  dif_otbn_err_bits_t err_otbn;
1340  read_otbn_err_bits(&err_otbn);
1341 
1342  // Read ERR_STATUS register from Ibex.
1343  dif_rv_core_ibex_error_status_t err_ibx;
1344  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
1345 
1346  otbn_fi_keys_t uj_output;
1347  uj_output.keys[0] = key_share_0_l;
1348  uj_output.keys[1] = key_share_0_h;
1349  uj_output.keys[2] = key_share_1_l;
1350  uj_output.keys[3] = key_share_1_h;
1351 
1352  uj_output.res = 0;
1353  if ((key_share_0_l != key_share_0_l_ref) ||
1354  (key_share_0_h != key_share_0_h_ref) ||
1355  (key_share_1_l != key_share_1_l_ref) ||
1356  (key_share_1_h != key_share_1_h_ref)) {
1357  uj_output.res = 1;
1358  }
1359 
1360  // Send result & ERR_STATUS to host.
1361  uj_output.err_otbn = err_otbn;
1362  uj_output.err_ibx = err_ibx;
1363  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1364  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1365  sizeof(sensor_alerts.alerts));
1366  RESP_OK(ujson_serialize_otbn_fi_keys_t, uj, &uj_output);
1367  return OK_STATUS();
1368 }
1369 
1370 status_t handle_otbn_fi_load_integrity(ujson_t *uj) {
1371  // Clear registered alerts in alert handler.
1372  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1373  // Clear the AST recoverable alerts.
1374  pentest_clear_sensor_recov_alerts();
1375 
1376  if (!load_integrity_init) {
1377  // Load the OTBN app and read the load checksum without FI to retrieve
1378  // reference value.
1379  clear_otbn_load_checksum();
1380  otbn_load_app(kOtbnAppLoadIntegrity);
1381  read_otbn_load_checksum(&load_checksum_ref);
1382  clear_otbn_load_checksum();
1383 
1384  load_integrity_init = true;
1385  }
1386 
1387  // FI code target.
1388  pentest_set_trigger_high();
1389  otbn_load_app(kOtbnAppLoadIntegrity);
1390  pentest_set_trigger_low();
1391  // Get registered alerts from alert handler.
1392  reg_alerts = pentest_get_triggered_alerts();
1393  // Get fatal and recoverable AST alerts from sensor controller.
1394  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1395 
1396  // Read back checksum.
1397  uint32_t load_checksum;
1398  read_otbn_load_checksum(&load_checksum);
1399  clear_otbn_load_checksum();
1400 
1401  // Read loop counter from OTBN data memory.
1402  uint32_t ref_val1, ref_val2, ref_val3;
1403  otbn_dmem_read(1, kOtbnAppLoadIntegrityRefVal1, &ref_val1);
1404  otbn_dmem_read(1, kOtbnAppLoadIntegrityRefVal2, &ref_val2);
1405  otbn_dmem_read(1, kOtbnAppLoadIntegrityRefVal3, &ref_val3);
1406 
1407  // Check if DMEM is corrupted.
1408  bool dmem_corrupted = false;
1409  if ((ref_val1 != 0x1BADB002) || (ref_val2 != 0x8BADF00D) ||
1410  (ref_val3 != 0xA5A5A5A5)) {
1411  dmem_corrupted = true;
1412  }
1413 
1414  // If DMEM is corrupted and the checksum is still correct, we achieved the
1415  // attack goal.
1416  uint32_t res = 0;
1417  if ((load_checksum_ref == load_checksum) && dmem_corrupted) {
1418  res = 1;
1419  }
1420 
1421  // Read ERR_STATUS register from OTBN.
1422  dif_otbn_err_bits_t err_otbn;
1423  read_otbn_err_bits(&err_otbn);
1424 
1425  // Read ERR_STATUS register from Ibex.
1426  dif_rv_core_ibex_error_status_t err_ibx;
1427  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
1428 
1429  // Clear OTBN memory.
1430  TRY(clear_otbn());
1431 
1432  // Send result & ERR_STATUS to host.
1433  otbn_fi_result_t uj_output;
1434  uj_output.result = res;
1435  uj_output.err_otbn = err_otbn;
1436  uj_output.err_ibx = err_ibx;
1437  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1438  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1439  sizeof(sensor_alerts.alerts));
1440  RESP_OK(ujson_serialize_otbn_fi_result_t, uj, &uj_output);
1441  return OK_STATUS();
1442 }
1443 
1444 status_t handle_otbn_fi_pc(ujson_t *uj) {
1445  // Get OTBN program counter from host.
1446  otbn_fi_pc_t uj_data;
1447  TRY(ujson_deserialize_otbn_fi_pc_t(uj, &uj_data));
1448 
1449  // Clear registered alerts in alert handler.
1450  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1451  // Clear the AST recoverable alerts.
1452  pentest_clear_sensor_recov_alerts();
1453 
1454  // Initialize OTBN app, load it, and get interface to OTBN data memory.
1455  OTBN_DECLARE_APP_SYMBOLS(otbn_pc);
1456  OTBN_DECLARE_SYMBOL_ADDR(otbn_pc, pc);
1457  OTBN_DECLARE_SYMBOL_ADDR(otbn_pc, pc_out);
1458  const otbn_app_t kOtbnAppPc = OTBN_APP_T_INIT(otbn_pc);
1459  static const otbn_addr_t kOtbnPc = OTBN_ADDR_T_INIT(otbn_pc, pc);
1460  static const otbn_addr_t kOtbnPcOut = OTBN_ADDR_T_INIT(otbn_pc, pc_out);
1461  dif_otbn_status_t otbn_status;
1462 
1463  // Load app.
1464  otbn_load_app(kOtbnAppPc);
1465 
1466  // FI code target.
1467  pentest_set_trigger_high();
1468  TRY(dif_otbn_dmem_write(&otbn, kOtbnPc, &uj_data.pc, sizeof(uj_data.pc)));
1469  otbn_execute();
1470  // Wait until is started before deasserting the trigger.
1471  bool is_running = false;
1472  while (!is_running) {
1473  TRY(dif_otbn_get_status(&otbn, &otbn_status));
1474  if (otbn_status != kDifOtbnStatusIdle) {
1475  is_running = true;
1476  }
1477  }
1478  pentest_set_trigger_low();
1479  otbn_busy_wait_for_done();
1480  // Get registered alerts from alert handler.
1481  reg_alerts = pentest_get_triggered_alerts();
1482  // Get fatal and recoverable AST alerts from sensor controller.
1483  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1484 
1485  // Read pc_out from OTBN data memory.
1486  otbn_fi_pc_out_t uj_output;
1487  TRY(dif_otbn_dmem_read(&otbn, kOtbnPcOut, &uj_output.pc_otbn,
1488  sizeof(uj_output.pc_otbn)));
1489  TRY(dif_otbn_dmem_read(&otbn, kOtbnPc, &uj_output.pc_dmem,
1490  sizeof(uj_output.pc_dmem)));
1491 
1492  // Read OTBN instruction counter.
1493  TRY(dif_otbn_get_insn_cnt(&otbn, &uj_output.insn_cnt));
1494 
1495  // Read ERR_STATUS register from OTBN.
1496  dif_otbn_err_bits_t err_otbn;
1497  read_otbn_err_bits(&err_otbn);
1498 
1499  // Read ERR_STATUS register from Ibex.
1500  dif_rv_core_ibex_error_status_t err_ibx;
1501  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx));
1502 
1503  // Clear OTBN memory.
1504  TRY(clear_otbn());
1505 
1506  // Send back to host.
1507  uj_output.err_otbn = err_otbn;
1508  uj_output.err_ibx = err_ibx;
1509  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1510  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1511  sizeof(sensor_alerts.alerts));
1512  RESP_OK(ujson_serialize_otbn_fi_pc_out_t, uj, &uj_output);
1513  return OK_STATUS();
1514 }
1515 
1516 status_t handle_otbn_fi(ujson_t *uj) {
1517  otbn_fi_subcommand_t cmd;
1518  TRY(ujson_deserialize_otbn_fi_subcommand_t(uj, &cmd));
1519  switch (cmd) {
1520  case kOtbnFiSubcommandCharBeq:
1521  return handle_otbn_fi_char_beq(uj);
1522  case kOtbnFiSubcommandCharBnRshi:
1523  return handle_otbn_fi_char_bn_rshi(uj);
1524  case kOtbnFiSubcommandCharBnSel:
1525  return handle_otbn_fi_char_bn_sel(uj);
1526  case kOtbnFiSubcommandCharBnWsrr:
1527  return handle_otbn_fi_char_bn_wsrr(uj);
1528  case kOtbnFiSubcommandCharBne:
1529  return handle_otbn_fi_char_bne(uj);
1530  case kOtbnFiSubcommandCharDmemAccess:
1531  return handle_otbn_fi_char_dmem_access(uj);
1532  case kOtbnFiSubcommandCharDmemWrite:
1533  return handle_otbn_fi_char_dmem_write(uj);
1534  case kOtbnFiSubcommandCharHardwareDmemOpLoop:
1535  return handle_otbn_fi_char_hardware_dmem_op_loop(uj);
1536  case kOtbnFiSubcommandCharHardwareRegOpLoop:
1537  return handle_otbn_fi_char_hardware_reg_op_loop(uj);
1538  case kOtbnFiSubcommandCharJal:
1539  return handle_otbn_fi_char_jal(uj);
1540  case kOtbnFiSubcommandCharLw:
1541  return handle_otbn_fi_char_lw(uj);
1542  case kOtbnFiSubcommandCharMem:
1543  return handle_otbn_fi_char_mem(uj);
1544  case kOtbnFiSubcommandCharRF:
1545  return handle_otbn_fi_char_register_file(uj);
1546  case kOtbnFiSubcommandCharUnrolledDmemOpLoop:
1547  return handle_otbn_fi_char_unrolled_dmem_op_loop(uj);
1548  case kOtbnFiSubcommandCharUnrolledRegOpLoop:
1549  return handle_otbn_fi_char_unrolled_reg_op_loop(uj);
1550  case kOtbnFiSubcommandInit:
1551  return handle_otbn_fi_init(uj);
1552  case kOtbnFiSubcommandInitKeyMgr:
1553  return handle_otbn_fi_init_keymgr(uj);
1554  case kOtbnFiSubcommandKeySideload:
1555  return handle_otbn_fi_key_sideload(uj);
1556  case kOtbnFiSubcommandLoadIntegrity:
1557  return handle_otbn_fi_load_integrity(uj);
1558  case kOtbnFiSubcommandPC:
1559  return handle_otbn_fi_pc(uj);
1560  default:
1561  LOG_ERROR("Unrecognized OTBN FI subcommand: %d", cmd);
1562  return INVALID_ARGUMENT();
1563  }
1564  return OK_STATUS();
1565 }