5 #include "sw/device/silicon_creator/lib/drivers/otbn.h"
14 #include "sw/device/silicon_creator/lib/drivers/rnd.h"
15 #include "sw/device/silicon_creator/lib/error.h"
18 #include "otbn_regs.h"
28 kOtbnErrBitsLast = OTBN_ERR_BITS_FATAL_SOFTWARE_BIT,
35 static rom_error_t check_offset_len(uint32_t offset_bytes,
size_t num_words,
37 if (num_words > UINT32_MAX /
sizeof(uint32_t)) {
38 return kErrorOtbnBadOffsetLen;
40 uint32_t num_bytes = num_words *
sizeof(uint32_t);
42 if (offset_bytes > UINT32_MAX - num_bytes) {
43 return kErrorOtbnBadOffsetLen;
45 uint32_t adjusted_offset_bytes = offset_bytes + num_bytes;
47 if (adjusted_offset_bytes > mem_size) {
48 return kErrorOtbnBadOffsetLen;
54 rom_error_t sc_otbn_busy_wait_for_done(
void) {
55 uint32_t
status = launder32(UINT32_MAX);
56 rom_error_t res = launder32(kErrorOk ^
status);
58 status = abs_mmio_read32(kBase + OTBN_STATUS_REG_OFFSET);
59 }
while (launder32(
status) != kScOtbnStatusIdle &&
60 launder32(
status) != kScOtbnStatusLocked);
62 if (launder32(res) == kErrorOk) {
68 return kErrorOtbnUnavailable;
78 static void sc_otbn_write(uint32_t dest_addr,
const uint32_t *src,
81 uint32_t i = ((uint64_t)rnd_uint32() * (uint64_t)num_words) >> 32;
83 uint32_t iter_cnt = 0, r_iter_cnt = num_words - 1;
84 for (; launder32(iter_cnt) < num_words && launder32(r_iter_cnt) < num_words;
85 ++iter_cnt, --r_iter_cnt) {
86 abs_mmio_write32(dest_addr + i *
sizeof(uint32_t), src[i]);
88 if (launder32(i) >= num_words) {
91 HARDENED_CHECK_LT(i, num_words);
98 static rom_error_t sc_otbn_imem_write(
size_t num_words,
const uint32_t *src,
99 sc_otbn_addr_t dest) {
100 HARDENED_RETURN_IF_ERROR(
101 check_offset_len(dest, num_words, OTBN_IMEM_SIZE_BYTES));
102 sc_otbn_write(kBase + OTBN_IMEM_REG_OFFSET + dest, src, num_words);
106 rom_error_t sc_otbn_dmem_write(
size_t num_words,
const uint32_t *src,
107 sc_otbn_addr_t dest) {
108 HARDENED_RETURN_IF_ERROR(
109 check_offset_len(dest, num_words, OTBN_DMEM_SIZE_BYTES));
110 sc_otbn_write(kBase + OTBN_DMEM_REG_OFFSET + dest, src, num_words);
114 rom_error_t sc_otbn_dmem_read(
size_t num_words, sc_otbn_addr_t src,
116 HARDENED_RETURN_IF_ERROR(
117 check_offset_len(src, num_words, OTBN_DMEM_SIZE_BYTES));
118 uint32_t i = 0, r = num_words - 1;
119 for (; launder32(i) < num_words && launder32(r) < num_words; ++i, --r) {
120 dest[i] = abs_mmio_read32(kBase + OTBN_DMEM_REG_OFFSET + src +
121 i *
sizeof(uint32_t));
138 static rom_error_t sc_otbn_cmd_run(sc_otbn_cmd_t cmd, rom_error_t error) {
140 kIntrStateDone = (1 << OTBN_INTR_COMMON_DONE_BIT),
144 static_assert((UINT32_C(1) << kResDoneBit) > kOtbnErrBitsLast,
145 "kResDoneBit must not overlap with OTBN error bits");
147 abs_mmio_write32(kBase + OTBN_INTR_STATE_REG_OFFSET, kIntrStateDone);
148 abs_mmio_write32(kBase + OTBN_CMD_REG_OFFSET, cmd);
150 rom_error_t res = kErrorOk ^ (UINT32_C(1) << kResDoneBit);
153 reg = abs_mmio_read32(kBase + OTBN_INTR_STATE_REG_OFFSET);
156 }
while (launder32(reg) != kIntrStateDone);
158 abs_mmio_write32(kBase + OTBN_INTR_STATE_REG_OFFSET, kIntrStateDone);
161 uint32_t err_bits = abs_mmio_read32(kBase + OTBN_ERR_BITS_REG_OFFSET);
167 uint32_t
status = abs_mmio_read32(kBase + OTBN_STATUS_REG_OFFSET);
169 if (launder32(res) == kErrorOk && launder32(err_bits) == 0 &&
170 launder32(
status) == kScOtbnStatusIdle) {
180 rom_error_t sc_otbn_execute(
void) {
182 HARDENED_RETURN_IF_ERROR(sc_otbn_busy_wait_for_done());
188 1 << OTBN_CTRL_SOFTWARE_ERRS_FATAL_BIT);
190 return sc_otbn_cmd_run(kScOtbnCmdExecute, kErrorOtbnExecutionFailed);
193 uint32_t sc_otbn_instruction_count_get(
void) {
194 return abs_mmio_read32(kBase + OTBN_INSN_CNT_REG_OFFSET);
197 rom_error_t sc_otbn_imem_sec_wipe(
void) {
198 return sc_otbn_cmd_run(kScOtbnCmdSecWipeImem, kErrorOtbnSecWipeImemFailed);
201 rom_error_t sc_otbn_dmem_sec_wipe(
void) {
202 return sc_otbn_cmd_run(kScOtbnCmdSecWipeDmem, kErrorOtbnSecWipeDmemFailed);
216 static rom_error_t check_app_address_ranges(
const sc_otbn_app_t app) {
223 return kErrorOtbnInvalidArgument;
227 HARDENED_RETURN_IF_ERROR(check_app_address_ranges(app));
230 HARDENED_RETURN_IF_ERROR(sc_otbn_busy_wait_for_done());
233 HARDENED_RETURN_IF_ERROR(sc_otbn_dmem_sec_wipe());
234 HARDENED_RETURN_IF_ERROR(sc_otbn_imem_sec_wipe());
237 const size_t data_num_words =
241 sc_otbn_addr_t imem_start_addr = 0;
242 HARDENED_RETURN_IF_ERROR(
243 sc_otbn_imem_write(imem_num_words, app.
imem_start, imem_start_addr));
245 if (data_num_words > 0) {
246 HARDENED_RETURN_IF_ERROR(sc_otbn_dmem_write(