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