Software APIs
otbn.h
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 #ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_OTBN_H_
6 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_OTBN_H_
7 
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 
12 #include "sw/device/silicon_creator/lib/error.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * Constants related to OTBN wide words
20  */
21 enum {
22  /* Length of an OTBN wide word in bits */
23  kScOtbnWideWordNumBits = 256,
24  /* Length of an OTBN wide word in words */
25  kScOtbnWideWordNumWords = kScOtbnWideWordNumBits / (sizeof(uint32_t) * 8),
26 };
27 
28 /**
29  * The following constants represent the expected number of sec_mmio register
30  * writes performed by functions in provided in this module. See
31  * `SEC_MMIO_WRITE_INCREMENT()` for more details.
32  *
33  * Example:
34  * ```
35  * sc_otbn_execute();
36  * SEC_MMIO_WRITE_INCREMENT(kScOtbnSecMmioExecute);
37  * ```
38  */
39 enum {
40  kScOtbnSecMmioExecute = 1,
41 };
42 
43 /**
44  * OTBN commands
45  *
46  * TODO(#16754): replace these with constants from otbn_regs.h
47  */
48 typedef enum sc_otbn_cmd {
49  kScOtbnCmdExecute = 0xd8,
50  kScOtbnCmdSecWipeDmem = 0xc3,
51  kScOtbnCmdSecWipeImem = 0x1e,
52 } sc_otbn_cmd_t;
53 
54 /**
55  * OTBN status
56  *
57  * TODO(#16754): replace these with constants from otbn_regs.h
58  */
59 typedef enum sc_otbn_status {
60  kScOtbnStatusIdle = 0x00,
61  kScOtbnStatusBusyExecute = 0x01,
62  kScOtbnStatusBusySecWipeDmem = 0x02,
63  kScOtbnStatusBusySecWipeImem = 0x03,
64  kScOtbnStatusBusySecWipeInt = 0x04,
65  kScOtbnStatusLocked = 0xFF,
66 } sc_otbn_status_t;
67 
68 /**
69  * The address of an OTBN symbol as seen by OTBN
70  *
71  * Use `OTBN_DECLARE_SYMBOL_ADDR()` together with `OTBN_ADDR_T_INIT()` to
72  * initialize this type.
73  */
74 typedef uint32_t sc_otbn_addr_t;
75 
76 /**
77  * Information about an embedded OTBN application image.
78  *
79  * All pointers reference data in the normal CPU address space.
80  * uint32_t values are addresses in the OTBN address space.
81  *
82  * Use `OTBN_DECLARE_APP_SYMBOLS()` together with `OTBN_APP_T_INIT()` to
83  * initialize this structure.
84  */
85 typedef struct sc_otbn_app {
86  /**
87  * Start of OTBN instruction memory.
88  */
89  const uint32_t *imem_start;
90  /**
91  * The first word after OTBN instruction memory.
92  *
93  * This address satifies `imem_len = imem_end - imem_start`.
94  */
95  const uint32_t *imem_end;
96  /**
97  * Start of initialized OTBN data.
98  *
99  * Data in between dmem_data_start and dmem_data_end will be copied to OTBN
100  * at app load time.
101  */
102  const uint32_t *dmem_data_start;
103  /**
104  * The first word after initialized OTBN data.
105  *
106  * Should satisfy `dmem_data_start <= dmem_data_end`.
107  */
108  const uint32_t *dmem_data_end;
109  /**
110  * Start of initialized data section in OTBN's DMEM.
111  *
112  * This pointer references OTBN's memory and is used to copy data at app load
113  * time.
114  */
115  const sc_otbn_addr_t dmem_data_start_addr;
116 } sc_otbn_app_t;
117 
118 /**
119  * Generate the prefix to add to an OTBN symbol name used on the Ibex side
120  *
121  * The result is a pointer to Ibex's rodata that should be used to initialise
122  * memory for that symbol.
123  *
124  * This is needed by the OTBN driver to support DMEM/IMEM ranges but
125  * application code shouldn't need to use this. Use the `sc_otbn_addr_t` type
126  * and supporting macros instead.
127  */
128 #define OTBN_SYMBOL_PTR(app_name, sym) _otbn_local_app_##app_name##_##sym
129 
130 /**
131  * Generate the prefix to add to an OTBN symbol name used on the OTBN side
132  *
133  * The result is a pointer whose integer value is the address by which the
134  * symbol should be accessed in OTBN memory.
135  *
136  * This is an internal macro used in `OTBN_DECLARE_SYMBOL_ADDR` and
137  * `OTBN_ADDR_T_INIT` but application code shouldn't need to use it directly.
138  */
139 #define OTBN_SYMBOL_ADDR(app_name, sym) _otbn_remote_app_##app_name##_##sym
140 
141 /**
142  * Makes a symbol in the OTBN application image available.
143  *
144  * This is needed by the OTBN driver to support DMEM/IMEM ranges but
145  * application code shouldn't need to use this. To get access to OTBN
146  * addresses, use `OTBN_DECLARE_SYMBOL_ADDR` instead.
147  */
148 #define OTBN_DECLARE_SYMBOL_PTR(app_name, symbol_name) \
149  extern const uint32_t OTBN_SYMBOL_PTR(app_name, symbol_name)[]
150 
151 /**
152  * Makes the OTBN address of a symbol in the OTBN application available.
153  *
154  * Symbols are typically function or data pointers, i.e. labels in assembly
155  * code. Unlike OTBN_DECLARE_SYMBOL_PTR, this will work for symbols in the .bss
156  * section (which exist on the OTBN side, even though they don't have backing
157  * data on Ibex).
158  *
159  * Use this macro instead of manually declaring the symbols as symbol names
160  * might change.
161  *
162  * @param app_name Name of the application the function is contained in.
163  * @param symbol_name Name of the symbol (function, label).
164  */
165 #define OTBN_DECLARE_SYMBOL_ADDR(app_name, symbol_name) \
166  extern const uint32_t OTBN_SYMBOL_ADDR(app_name, symbol_name)[]
167 
168 /**
169  * Makes an embedded OTBN application image available for use.
170  *
171  * Make symbols available that indicate the start and the end of instruction
172  * and data memory regions, as they are stored in the device memory.
173  *
174  * Use this macro instead of manually declaring the symbols as symbol names
175  * might change.
176  *
177  * @param app_name Name of the application to load, which is typically the
178  * name of the main (assembly) source file.
179  */
180 #define OTBN_DECLARE_APP_SYMBOLS(app_name) \
181  OTBN_DECLARE_SYMBOL_PTR(app_name, _imem_start); \
182  OTBN_DECLARE_SYMBOL_PTR(app_name, _imem_end); \
183  OTBN_DECLARE_SYMBOL_PTR(app_name, _dmem_data_start); \
184  OTBN_DECLARE_SYMBOL_PTR(app_name, _dmem_data_end); \
185  OTBN_DECLARE_SYMBOL_ADDR(app_name, _dmem_data_start);
186 
187 /**
188  * Initializes the OTBN application information structure.
189  *
190  * After making all required symbols from the application image available
191  * through `OTBN_DECLARE_APP_SYMBOLS()`, use this macro to initialize an
192  * `sc_otbn_app_t` struct with those symbols.
193  *
194  * @param app_name Name of the application to load.
195  * @see OTBN_DECLARE_APP_SYMBOLS()
196  */
197 #define OTBN_APP_T_INIT(app_name) \
198  ((sc_otbn_app_t){ \
199  .imem_start = OTBN_SYMBOL_PTR(app_name, _imem_start), \
200  .imem_end = OTBN_SYMBOL_PTR(app_name, _imem_end), \
201  .dmem_data_start = OTBN_SYMBOL_PTR(app_name, _dmem_data_start), \
202  .dmem_data_end = OTBN_SYMBOL_PTR(app_name, _dmem_data_end), \
203  .dmem_data_start_addr = OTBN_ADDR_T_INIT(app_name, _dmem_data_start), \
204  })
205 
206 /**
207  * Initializes an `sc_otbn_addr_t`.
208  */
209 #define OTBN_ADDR_T_INIT(app_name, symbol_name) \
210  ((uint32_t)OTBN_SYMBOL_ADDR(app_name, symbol_name))
211 
212 /**
213  * (Re-)loads an application into OTBN.
214  *
215  * Load the application image with both instruction and data segments into
216  * OTBN.
217  *
218  * @param app The application to load into OTBN.
219  * @return The result of the operation.
220  */
222 rom_error_t sc_otbn_load_app(const sc_otbn_app_t app);
223 
224 /**
225  * Copies data from the CPU memory to OTBN data memory.
226  *
227  * @param num_words Number of 32b words to copy.
228  * @param dest Address of the destination in OTBN's data memory.
229  * @param src Source of the data to copy.
230  * @return The result of the operation.
231  */
233 rom_error_t sc_otbn_dmem_write(size_t num_words, const uint32_t *src,
234  sc_otbn_addr_t dest);
235 
236 /**
237  * Copies data from OTBN's data memory to CPU memory.
238  *
239  * @param num_words The number of 32b words to copy.
240  * @param src The address in OTBN data memory to copy from.
241  * @param[out] dest The destination of the copied data in main memory
242  * (preallocated).
243  * @return The result of the operation.
244  */
246 rom_error_t sc_otbn_dmem_read(size_t num_words, const sc_otbn_addr_t src,
247  uint32_t *dest);
248 
249 /**
250  * Start the execution of the application loaded into OTBN.
251  *
252  * This function blocks until OTBN is idle.
253  *
254  * @return Result of the operation.
255  */
257 rom_error_t sc_otbn_execute(void);
258 
259 /**
260  * Blocks until OTBN is idle.
261  *
262  * If OTBN is or becomes locked, an error will occur.
263  *
264  * @return Result of the operation.
265  */
267 rom_error_t sc_otbn_busy_wait_for_done(void);
268 
269 /**
270  * Read OTBN's instruction count register.
271  *
272  * OTBN automatically calculates how many instructions are executed in a given
273  * program and writes the result to this register. Software can read it to
274  * verify that instructions were not unexpectedly skipped or added (for
275  * instance, due to fault injection attacks).
276  *
277  * Note that the OTBN hardware resets the instruction count register to 0 when
278  * the EXECUTE command is issued, so there is no need for software to reset the
279  * counter between programs.
280  *
281  * @return count the value from the instruction count register
282  */
284 uint32_t sc_otbn_instruction_count_get(void);
285 
286 /**
287  * Wipe IMEM securely.
288  *
289  * This function blocks until OTBN is idle.
290  *
291  * @return Result of the operation.
292  */
294 rom_error_t sc_otbn_imem_sec_wipe(void);
295 
296 /**
297  * Wipe DMEM securely.
298  *
299  * This function blocks until OTBN is idle.
300  *
301  * @return Result of the operation.
302  */
304 rom_error_t sc_otbn_dmem_sec_wipe(void);
305 
306 #ifdef __cplusplus
307 }
308 #endif
309 
310 #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_OTBN_H_