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_LIB_CRYPTO_DRIVERS_OTBN_H_
6 #define OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_OTBN_H_
7 
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 
12 #include "sw/device/lib/crypto/impl/status.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  kOtbnWideWordNumBits = 256,
24  /* Length of an OTBN wide word in bytes */
25  kOtbnWideWordNumBytes = kOtbnWideWordNumBits / 8,
26  /* Length of an OTBN wide word in words */
27  kOtbnWideWordNumWords = kOtbnWideWordNumBytes / sizeof(uint32_t),
28 };
29 
30 /**
31  * The address of an OTBN symbol as seen by OTBN.
32  *
33  * Use `OTBN_DECLARE_SYMBOL_ADDR()` together with `OTBN_ADDR_T_INIT()` to
34  * initialize this type.
35  */
36 typedef uint32_t otbn_addr_t;
37 
38 /**
39  * Information about an embedded OTBN application image.
40  *
41  * All pointers reference data in the normal CPU address space.
42  * uint32_t values are addresses in the OTBN address space.
43  *
44  * Use `OTBN_DECLARE_APP_SYMBOLS()` together with `OTBN_APP_T_INIT()` to
45  * initialize this structure.
46  */
47 typedef struct otbn_app {
48  /**
49  * Start of OTBN instruction memory in the embedded program.
50  *
51  * This pointer references Ibex's memory.
52  */
53  const uint32_t *imem_start;
54  /**
55  * The first word after OTBN instruction memory in the embedded program.
56  *
57  * This pointer references Ibex's memory.
58  *
59  * This address satifies `imem_start < imem_end`.
60  */
61  const uint32_t *imem_end;
62  /**
63  * Start of initialized OTBN data in the embedded program.
64  *
65  * This pointer references Ibex's memory.
66  *
67  * Data in between `dmem_data_start` and `dmem_data_end` will be copied to
68  * OTBN at app load time.
69  */
70  const uint32_t *dmem_data_start;
71  /**
72  * The first word after initialized OTBN data in the embedded program.
73  *
74  * This pointer references Ibex's memory.
75  *
76  * Should satisfy `dmem_data_start <= dmem_data_end`.
77  */
78  const uint32_t *dmem_data_end;
79  /**
80  * Start of initialized data section in OTBN's DMEM.
81  *
82  * This pointer references OTBN's memory and is used to copy data at app load
83  * time.
84  */
85  const otbn_addr_t dmem_data_start_addr;
86  /**
87  * Application checksum.
88  *
89  * This value represents a CRC32 checksum over IMEM and the `.data` portion
90  * of DMEM.
91  */
92  const uint32_t checksum;
93 } otbn_app_t;
94 
95 /**
96  * Generate the prefix to add to an OTBN symbol name used on the Ibex side
97  *
98  * The result is a pointer to Ibex's rodata that should be used to initialise
99  * memory for that symbol.
100  *
101  * This is needed by the OTBN driver to support DMEM/IMEM ranges but
102  * application code shouldn't need to use this. Use the `otbn_addr_t` type and
103  * supporting macros instead.
104  */
105 #define OTBN_SYMBOL_PTR(app_name, sym) _otbn_local_app_##app_name##_##sym
106 
107 /**
108  * Generate the prefix to add to an OTBN symbol name used on the OTBN side
109  *
110  * The result is a pointer whose integer value is the address by which the
111  * symbol should be accessed in OTBN memory.
112  *
113  * This is an internal macro used in `OTBN_DECLARE_SYMBOL_ADDR` and
114  * `OTBN_ADDR_T_INIT` but application code shouldn't need to use it directly.
115  */
116 #define OTBN_SYMBOL_ADDR(app_name, sym) _otbn_remote_app_##app_name##_##sym
117 
118 /**
119  * Makes a symbol in the OTBN application image available.
120  *
121  * This is needed by the OTBN driver to support DMEM/IMEM ranges but
122  * application code shouldn't need to use this. To get access to OTBN
123  * addresses, use `OTBN_DECLARE_SYMBOL_ADDR` instead.
124  */
125 #define OTBN_DECLARE_SYMBOL_PTR(app_name, symbol_name) \
126  extern const uint32_t OTBN_SYMBOL_PTR(app_name, symbol_name)[]
127 
128 /**
129  * Makes the OTBN address of a symbol in the OTBN application available.
130  *
131  * Symbols are typically function or data pointers, i.e. labels in assembly
132  * code. Unlike OTBN_DECLARE_SYMBOL_PTR, this will work for symbols in the .bss
133  * section (which exist on the OTBN side, even though they don't have backing
134  * data on Ibex).
135  *
136  * Use this macro instead of manually declaring the symbols as symbol names
137  * might change.
138  *
139  * @param app_name Name of the application the function is contained in.
140  * @param symbol_name Name of the symbol (function, label).
141  */
142 #define OTBN_DECLARE_SYMBOL_ADDR(app_name, symbol_name) \
143  extern const uint32_t OTBN_SYMBOL_ADDR(app_name, symbol_name)[]
144 
145 /**
146  * Makes an embedded OTBN application image available for use.
147  *
148  * Make symbols available that indicate the start and the end of instruction
149  * and data memory regions, as they are stored in the device memory.
150  *
151  * Use this macro instead of manually declaring the symbols as symbol names
152  * might change.
153  *
154  * @param app_name Name of the application to load, which is typically the
155  * name of the main (assembly) source file.
156  */
157 #define OTBN_DECLARE_APP_SYMBOLS(app_name) \
158  OTBN_DECLARE_SYMBOL_PTR(app_name, _imem_start); \
159  OTBN_DECLARE_SYMBOL_PTR(app_name, _imem_end); \
160  OTBN_DECLARE_SYMBOL_PTR(app_name, _dmem_data_start); \
161  OTBN_DECLARE_SYMBOL_PTR(app_name, _dmem_data_end); \
162  OTBN_DECLARE_SYMBOL_ADDR(app_name, _dmem_data_start); \
163  OTBN_DECLARE_SYMBOL_ADDR(app_name, _checksum)
164 
165 /**
166  * Initializes the OTBN application information structure.
167  *
168  * After making all required symbols from the application image available
169  * through `OTBN_DECLARE_APP_SYMBOLS()`, use this macro to initialize an
170  * `otbn_app_t` struct with those symbols.
171  *
172  * @param app_name Name of the application to load.
173  * @see OTBN_DECLARE_APP_SYMBOLS()
174  */
175 #define OTBN_APP_T_INIT(app_name) \
176  ((otbn_app_t){ \
177  .imem_start = OTBN_SYMBOL_PTR(app_name, _imem_start), \
178  .imem_end = OTBN_SYMBOL_PTR(app_name, _imem_end), \
179  .dmem_data_start = OTBN_SYMBOL_PTR(app_name, _dmem_data_start), \
180  .dmem_data_end = OTBN_SYMBOL_PTR(app_name, _dmem_data_end), \
181  .dmem_data_start_addr = OTBN_ADDR_T_INIT(app_name, _dmem_data_start), \
182  .checksum = OTBN_ADDR_T_INIT(app_name, _checksum), \
183  })
184 
185 /**
186  * Initializes an `otbn_addr_t`.
187  */
188 #define OTBN_ADDR_T_INIT(app_name, symbol_name) \
189  ((uint32_t)OTBN_SYMBOL_ADDR(app_name, symbol_name))
190 
191 /**
192  * Write to OTBN's data memory (DMEM)
193  *
194  * Only 32b-aligned 32b word accesses are allowed. If `dest` is not
195  * word-aligned or if the length and offset exceed the DMEM size, this function
196  * will return an error.
197  *
198  * The caller must ensure OTBN is idle before calling this function.
199  *
200  * @param num_words Length of the data in 32-bit words.
201  * @param src The main memory location to copy from.
202  * @param dest The DMEM location to copy to.
203  * @return Result of the operation.
204  */
205 status_t otbn_dmem_write(size_t num_words, const uint32_t *src,
206  otbn_addr_t dest);
207 
208 /**
209  * Set a range of OTBN's data memory (DMEM) to a particular value.
210  *
211  * Only 32b-aligned 32b word accesses are allowed. If `dest` is not
212  * word-aligned or if the length and offset exceed the DMEM size, this function
213  * will return an error.
214  *
215  * The caller must ensure OTBN is idle before calling this function.
216  *
217  * @param num_words Length of the range to set in 32-bit words.
218  * @param src The value to set each word in DMEM to.
219  * @param dest The DMEM location to set.
220  * @return Result of the operation.
221  */
222 status_t otbn_dmem_set(size_t num_words, const uint32_t src, otbn_addr_t dest);
223 
224 /**
225  * Read from OTBN's data memory (DMEM)
226  *
227  * Only 32b-aligned 32b word accesses are allowed. If `src` is not word-aligned
228  * or if the length and offset exceed the DMEM size, this function will return
229  * an error.
230  *
231  * The caller must ensure OTBN is idle before calling this function.
232  *
233  * @param num_words Length of the data in 32-bit words.
234  * @param src The DMEM location to copy from.
235  * @param[out] dest The main memory location to copy to.
236  * @return Result of the operation.
237  */
238 status_t otbn_dmem_read(size_t num_words, otbn_addr_t src, uint32_t *dest);
239 
240 /**
241  * Start the execution of the application loaded into OTBN.
242  *
243  * This function returns an error if called when OTBN is not idle.
244  *
245  * @return Result of the operation.
246  */
247 status_t otbn_execute(void);
248 
249 /**
250  * Blocks until OTBN is idle.
251  *
252  * If OTBN is or becomes locked, an error will occur.
253  *
254  * @return Result of the operation.
255  */
256 status_t otbn_busy_wait_for_done(void);
257 
258 /**
259  * Get the error bits set by the device if the operation failed.
260  *
261  * @return The contents of OTBN's ERR_BITS register.
262  */
263 uint32_t otbn_err_bits_get(void);
264 
265 /**
266  * Read OTBN's instruction count register.
267  *
268  * OTBN automatically calculates how many instructions are executed in a given
269  * program and writes the result to this register. Software can read it to
270  * verify that instructions were not unexpectedly skipped or added (for
271  * instance, due to fault injection attacks).
272  *
273  * Note that the OTBN hardware resets the instruction count register to 0 when
274  * the EXECUTE command is issued, so there is no need for software to reset the
275  * counter between programs.
276  *
277  * @return count the value from the instruction count register
278  */
279 uint32_t otbn_instruction_count_get(void);
280 
281 /**
282  * Wipe IMEM securely.
283  *
284  * This function returns an error if called when OTBN is not idle, and blocks
285  * until the secure wipe is complete.
286  *
287  * @return Result of the operation.
288  */
289 status_t otbn_imem_sec_wipe(void);
290 
291 /**
292  * Wipe DMEM securely.
293  *
294  * This function returns an error if called when OTBN is not idle, and blocks
295  * until the secure wipe is complete.
296  *
297  * @return Result of the operation.
298  */
299 status_t otbn_dmem_sec_wipe(void);
300 
301 /**
302  * Sets the software errors are fatal bit in the control register.
303  *
304  * When set any software error becomes a fatal error. The bit can only be
305  * changed when the OTBN status is IDLE.
306  *
307  * This function returns an error if called when OTBN is not idle.
308  *
309  * @param enable Enable or disable whether software errors are fatal.
310  * @return Result of the operation.
311  */
312 status_t otbn_set_ctrl_software_errs_fatal(bool enable);
313 
314 /**
315  * (Re-)loads the provided application into OTBN.
316  *
317  * Load the application image with both instruction and data segments into
318  * OTBN.
319  *
320  * This function will return an error if called when OTBN is not idle.
321  *
322  * @param ctx The context object.
323  * @param app The application to load into OTBN.
324  * @return The result of the operation.
325  */
326 status_t otbn_load_app(const otbn_app_t app);
327 
328 #ifdef __cplusplus
329 }
330 #endif
331 
332 #endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_OTBN_H_