5 #include "sw/device/lib/crypto/drivers/otbn.h"
11 #include "sw/device/lib/base/status.h"
12 #include "sw/device/lib/crypto/drivers/entropy.h"
13 #include "sw/device/lib/crypto/impl/status.h"
16 #include "otbn_regs.h"
19 #define MODULE_ID MAKE_MODULE_ID('d', 'b', 'n')
29 kOtbnDMemSizeBytes = OTBN_DMEM_SIZE_BYTES,
33 kOtbnIMemSizeBytes = OTBN_IMEM_SIZE_BYTES,
42 kOtbnErrBitsNoError = 0,
48 typedef enum otbn_cmd {
49 kOtbnCmdExecute = 0xd8,
50 kOtbnCmdSecWipeDmem = 0xc3,
51 kOtbnCmdSecWipeImem = 0x1e,
57 typedef enum otbn_status {
58 kOtbnStatusIdle = 0x00,
59 kOtbnStatusBusyExecute = 0x01,
60 kOtbnStatusBusySecWipeDmem = 0x02,
61 kOtbnStatusBusySecWipeImem = 0x03,
62 kOtbnStatusBusySecWipeInt = 0x04,
63 kOtbnStatusLocked = 0xFF,
74 static status_t check_offset_len(uint32_t offset_bytes,
size_t num_words,
76 if (num_words > UINT32_MAX /
sizeof(uint32_t)) {
77 return OTCRYPTO_BAD_ARGS;
79 uint32_t num_bytes = num_words *
sizeof(uint32_t);
81 if (offset_bytes > UINT32_MAX - num_bytes) {
82 return OTCRYPTO_BAD_ARGS;
84 uint32_t adjusted_offset_bytes = offset_bytes + num_bytes;
86 if (adjusted_offset_bytes > mem_size) {
87 return OTCRYPTO_BAD_ARGS;
101 static status_t otbn_assert_idle(
void) {
102 uint32_t
status = launder32(~(uint32_t)kOtbnStatusIdle);
104 .value = (int32_t)launder32((uint32_t)OTCRYPTO_OK.value ^
status)};
105 status = abs_mmio_read32(kBase + OTBN_STATUS_REG_OFFSET);
113 return OTCRYPTO_ASYNC_INCOMPLETE;
123 static void otbn_write(uint32_t dest_addr,
const uint32_t *src,
127 size_t i = ((uint64_t)0 * (uint64_t)num_words) >> 32;
130 for (; launder32(iter_cnt) < num_words; ++iter_cnt) {
131 abs_mmio_write32(dest_addr + i *
sizeof(uint32_t), src[i]);
133 if (launder32(i) >= num_words) {
136 HARDENED_CHECK_LT(i, num_words);
141 status_t otbn_dmem_write(
size_t num_words,
const uint32_t *src,
143 HARDENED_TRY(check_offset_len(dest, num_words, kOtbnDMemSizeBytes));
144 otbn_write(kBase + OTBN_DMEM_REG_OFFSET + dest, src, num_words);
148 status_t otbn_dmem_set(
size_t num_words,
const uint32_t src, otbn_addr_t dest) {
149 HARDENED_TRY(check_offset_len(dest, num_words, kOtbnDMemSizeBytes));
153 for (; launder32(i) < num_words; ++i) {
154 abs_mmio_write32(kBase + OTBN_DMEM_REG_OFFSET + dest + i *
sizeof(uint32_t),
156 HARDENED_CHECK_LT(i, num_words);
162 status_t otbn_dmem_read(
size_t num_words, otbn_addr_t src, uint32_t *dest) {
163 HARDENED_TRY(check_offset_len(src, num_words, kOtbnDMemSizeBytes));
166 for (; launder32(i) < num_words; ++i) {
167 dest[i] = abs_mmio_read32(kBase + OTBN_DMEM_REG_OFFSET + src +
168 i *
sizeof(uint32_t));
178 HARDENED_TRY(entropy_complex_check());
181 HARDENED_TRY(otbn_assert_idle());
183 abs_mmio_write32(kBase + OTBN_CMD_REG_OFFSET, kOtbnCmdExecute);
187 status_t otbn_busy_wait_for_done(
void) {
188 uint32_t
status = launder32(UINT32_MAX);
192 status = abs_mmio_read32(kBase + OTBN_STATUS_REG_OFFSET);
193 }
while (launder32(
status) != kOtbnStatusIdle &&
194 launder32(
status) != kOtbnStatusLocked);
197 uint32_t err_bits = otbn_err_bits_get();
200 launder32(err_bits) == kOtbnErrBitsNoError) {
202 err_bits = otbn_err_bits_get();
210 if (launder32(
status) == kOtbnStatusIdle) {
212 return OTCRYPTO_RECOV_ERR;
217 return OTCRYPTO_FATAL_ERR;
220 uint32_t otbn_err_bits_get(
void) {
221 return abs_mmio_read32(kBase + OTBN_ERR_BITS_REG_OFFSET);
224 uint32_t otbn_instruction_count_get(
void) {
225 return abs_mmio_read32(kBase + OTBN_INSN_CNT_REG_OFFSET);
229 HARDENED_TRY(entropy_complex_check());
230 HARDENED_TRY(otbn_assert_idle());
231 abs_mmio_write32(kBase + OTBN_CMD_REG_OFFSET, kOtbnCmdSecWipeImem);
232 HARDENED_TRY(otbn_busy_wait_for_done());
237 HARDENED_TRY(entropy_complex_check());
238 HARDENED_TRY(otbn_assert_idle());
239 abs_mmio_write32(kBase + OTBN_CMD_REG_OFFSET, kOtbnCmdSecWipeDmem);
240 HARDENED_TRY(otbn_busy_wait_for_done());
244 status_t otbn_set_ctrl_software_errs_fatal(
bool enable) {
246 HARDENED_TRY(otbn_assert_idle());
257 abs_mmio_write32(kBase + OTBN_CTRL_REG_OFFSET, new_ctrl);
276 return OTCRYPTO_BAD_ARGS;
282 return OTCRYPTO_BAD_ARGS;
290 HARDENED_TRY(check_app_address_ranges(&app));
293 HARDENED_TRY(otbn_assert_idle());
296 const size_t data_num_words =
299 HARDENED_TRY(otbn_imem_sec_wipe());
300 HARDENED_TRY(otbn_dmem_sec_wipe());
303 abs_mmio_write32(kBase + OTBN_LOAD_CHECKSUM_REG_OFFSET, 0);
308 kOtbnDMemSizeBytes));
311 otbn_addr_t imem_offset = 0;
313 check_offset_len(imem_offset, imem_num_words, kOtbnIMemSizeBytes));
314 uint32_t imem_start_addr = kBase + OTBN_IMEM_REG_OFFSET + imem_offset;
316 for (; launder32(i) < imem_num_words; i++) {
317 HARDENED_CHECK_LT(i, imem_num_words);
318 abs_mmio_write32(imem_start_addr + i *
sizeof(uint32_t), app.
imem_start[i]);
325 check_offset_len(data_offset, data_num_words, kOtbnDMemSizeBytes));
326 uint32_t data_start_addr = kBase + OTBN_DMEM_REG_OFFSET + data_offset;
328 for (; launder32(i) < data_num_words; i++) {
329 HARDENED_CHECK_LT(i, data_num_words);
330 abs_mmio_write32(data_start_addr + i *
sizeof(uint32_t),
336 uint32_t checksum = abs_mmio_read32(kBase + OTBN_LOAD_CHECKSUM_REG_OFFSET);
337 if (launder32(checksum) != app.
checksum) {
338 return OTCRYPTO_FATAL_ERR;