5 #include "sw/device/lib/crypto/impl/sha2/sha256.h"
11 #include "sw/device/lib/crypto/drivers/otbn.h"
12 #include "sw/device/lib/crypto/drivers/rv_core_ibex.h"
13 #include "sw/device/lib/crypto/impl/status.h"
16 #define MODULE_ID MAKE_MODULE_ID('s', '2', '2')
25 kSha256MaxMessageChunksPerOtbnRun = 41,
32 uint32_t data[kSha256MessageBlockWords];
48 static const uint32_t kSha256InitialState[kSha256StateWords] = {
49 0x5be0cd19, 0x1f83d9ab, 0x9b05688c, 0x510e527f,
50 0xa54ff53a, 0x3c6ef372, 0xbb67ae85, 0x6a09e667,
52 static_assert(
sizeof(kSha256InitialState) == kSha256StateBytes,
53 "Initial state for SHA-256 has an unexpected size.");
62 static const otbn_addr_t kOtbnVarSha256State =
64 static const otbn_addr_t kOtbnVarSha256Msg =
OTBN_ADDR_T_INIT(run_sha256, msg);
65 static const otbn_addr_t kOtbnVarSha256NumMsgChunks =
86 otbn_dmem_write(1, &ctx->
num_blocks, kOtbnVarSha256NumMsgChunks));
89 HARDENED_TRY(otbn_execute());
90 HARDENED_TRY(otbn_busy_wait_for_done());
109 size_t offset = ctx->
num_blocks * kSha256MessageBlockBytes;
110 otbn_addr_t dst = kOtbnVarSha256Msg + offset;
113 otbn_dmem_write(kSha256MessageBlockWords, block->data, dst);
120 if (ctx->
num_blocks == kSha256MaxMessageChunksPerOtbnRun) {
121 HARDENED_TRY(process_message_buffer(ctx));
141 const uint64_t total_len,
143 size_t partial_block_len = (total_len >> 3) % kSha256MessageBlockBytes;
146 unsigned char *data_end = (
unsigned char *)block->data + partial_block_len;
149 size_t padding_len = kSha256MessageBlockBytes - partial_block_len;
150 memset(data_end, 0, padding_len);
155 memset(data_end, 0x80, 1);
157 if (partial_block_len + 1 +
sizeof(total_len) > kSha256MessageBlockBytes) {
161 HARDENED_TRY(process_block(ctx, block));
162 memset(block, 0, kSha256MessageBlockBytes);
167 block->data[kSha256MessageBlockWords - 1] =
168 __builtin_bswap32(total_len & UINT32_MAX);
169 block->data[kSha256MessageBlockWords - 2] =
170 __builtin_bswap32(total_len >> 32);
173 return process_block(ctx, block);
189 HARDENED_TRY(otbn_load_app(kOtbnAppSha256));
193 uint64_t msg_bits = ((uint64_t)msg_len) << 3;
194 uint64_t max_msg_bits = UINT64_MAX - state->
total_len;
195 if (msg_bits > max_msg_bits) {
196 return OTCRYPTO_BAD_ARGS;
205 if (state->
total_len >= kSha256MessageBlockBytes) {
207 otbn_dmem_write(kSha256StateWords, state->
H, kOtbnVarSha256State));
214 size_t partial_block_len = (state->
total_len >> 3) % kSha256MessageBlockBytes;
222 while (msg_len >= kSha256MessageBlockBytes - partial_block_len) {
223 size_t available_len = kSha256MessageBlockBytes - partial_block_len;
224 memcpy((
unsigned char *)block.data + partial_block_len, msg, available_len);
225 msg += available_len;
226 msg_len -= available_len;
227 HARDENED_TRY(process_block(&ctx, &block));
228 partial_block_len = 0;
234 memcpy((
unsigned char *)block.data + partial_block_len, msg, msg_len);
238 HARDENED_TRY(process_padding(&ctx, new_state.
total_len, &block));
244 HARDENED_TRY(process_message_buffer(&ctx));
249 otbn_dmem_read(kSha256StateWords, kOtbnVarSha256State, new_state.
H));
252 HARDENED_TRY(otbn_dmem_sec_wipe());
263 const size_t msg_len) {
295 for (
size_t i = 0; i < kSha256StateWords / 2; i++) {
296 uint32_t tmp = __builtin_bswap32(state->
H[i]);
297 state->
H[i] = __builtin_bswap32(state->
H[kSha256StateWords - 1 - i]);
298 state->
H[kSha256StateWords - 1 - i] = tmp;
305 HARDENED_TRY(entropy_complex_check());
311 digest_get(state, digest);
316 status_t sha256(
const uint8_t *msg,
const size_t msg_len, uint32_t *digest) {
318 HARDENED_TRY(entropy_complex_check());
327 digest_get(&state, digest);