Software APIs
sha512.c
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 #include "sw/device/lib/crypto/impl/sha2/sha512.h"
6 
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"
14 
15 // Module ID for status codes.
16 #define MODULE_ID MAKE_MODULE_ID('s', '2', '5')
17 
18 enum {
19  /**
20  * Maximum number of message chunks that the OTBN app can accept.
21  *
22  * This number is based on the DMEM size limit and usage by the SHA-512 app
23  * itself; see `run_sha512.s` for the detailed calculation.
24  */
25  kSha512MaxMessageChunksPerOtbnRun = 16,
26 };
27 
28 /**
29  * A type to hold message blocks.
30  */
31 typedef struct sha512_message_block {
32  uint32_t data[kSha512MessageBlockWords];
34 
35 /**
36  * Context object for the OTBN message buffer.
37  */
38 typedef struct sha512_otbn_ctx {
39  /**
40  * Number of message blocks currently loaded.
41  */
42  size_t num_blocks;
44 
45 // Initial state for SHA-384 (see FIPS 180-4, section 5.3.4).
46 static const uint32_t kSha384InitialState[] = {
47  0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17,
48  0x152fecd8, 0xf70e5939, 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511,
49  0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,
50 };
51 
52 // Initial state for SHA-512 (see FIPS 180-4, section 5.3.5).
53 static const uint32_t kSha512InitialState[kSha512StateWords] = {
54  0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b,
55  0xa54ff53a, 0x5f1d36f1, 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f,
56  0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,
57 };
58 static_assert(sizeof(kSha512InitialState) == kSha512StateBytes,
59  "Initial state for SHA-512 has an unexpected size.");
60 
61 OTBN_DECLARE_APP_SYMBOLS(run_sha512); // The OTBN SHA-512 app.
62 OTBN_DECLARE_SYMBOL_ADDR(run_sha512, state); // Hash state.
63 OTBN_DECLARE_SYMBOL_ADDR(run_sha512, msg); // Input message.
64 OTBN_DECLARE_SYMBOL_ADDR(run_sha512, n_chunks); // Message length in blocks.
65 
66 static const otbn_app_t kOtbnAppSha512 = OTBN_APP_T_INIT(run_sha512);
67 static const otbn_addr_t kOtbnVarSha512State =
68  OTBN_ADDR_T_INIT(run_sha512, state);
69 static const otbn_addr_t kOtbnVarSha512Msg = OTBN_ADDR_T_INIT(run_sha512, msg);
70 static const otbn_addr_t kOtbnVarSha512NChunks =
71  OTBN_ADDR_T_INIT(run_sha512, n_chunks);
72 
73 void sha512_init(sha512_state_t *state) {
74  // Set the initial state.
75  hardened_memcpy(state->H, kSha512InitialState, kSha512StateWords);
76  // Set the partial block to 0 (the value is ignored).
77  memset(state->partial_block, 0, sizeof(state->partial_block));
78  // Set the message length so far to 0.
79  state->total_len.lower = 0;
80  state->total_len.upper = 0;
81 }
82 
83 void sha384_init(sha512_state_t *state) {
84  // Set the initial state.
85  hardened_memcpy(state->H, kSha384InitialState, kSha512StateWords);
86  // Set the partial block to 0 (the value is ignored).
87  memset(state->partial_block, 0, sizeof(state->partial_block));
88  // Set the message length so far to 0.
89  state->total_len.lower = 0;
90  state->total_len.upper = 0;
91 }
92 
93 /**
94  * Calculate an updated total message length and check that it is acceptable.
95  *
96  * Returns `OTCRYPTO_BAD_ARGS` if the current message length plus the new
97  * message length exceeds the SHA-512/SHA-384 maximum of 2^128 bits.
98  *
99  * This function is does not modify the state object; this is because in case
100  * of OTBN errors partway through the operation, the state could get out of
101  * sync.
102  *
103  * @param state Context object.
104  * @param msg_len Length of new data in bytes.
105  * @param[out] new_total_len New total received data length.
106  * @return Result of the operation.
107  */
108 static status_t get_new_total_len(const sha512_state_t *state, size_t msg_len,
109  sha512_message_length_t *new_total_len) {
110  // We need to shift `msg_len` here because `total_len` is in bits, not bytes.
111  new_total_len->lower = state->total_len.lower + (msg_len << 3);
112  new_total_len->upper = state->total_len.upper;
113  if (new_total_len->lower < state->total_len.lower) {
114  // If we got here, the addition for the first limb overflowed; add 1 to the
115  // next limb.
116  new_total_len->upper += 1;
117  }
118  if (new_total_len->upper < state->total_len.upper) {
119  // If the second subtraction overflowed, then the message is too long for
120  // SHA-512.
121  return OTCRYPTO_BAD_ARGS;
122  }
123  return OTCRYPTO_OK;
124 }
125 
126 /**
127  * Run OTBN to process the data currently in DMEM.
128  *
129  * @param ctx OTBN message buffer context information (updated in place).
130  * @return Result of the operation.
131  */
132 static status_t process_message_buffer(sha512_otbn_ctx_t *ctx) {
133  // Write the number of blocks to DMEM.
134  HARDENED_TRY(otbn_dmem_write(1, &ctx->num_blocks, kOtbnVarSha512NChunks));
135 
136  // Run the OTBN program.
137  HARDENED_TRY(otbn_execute());
138  HARDENED_TRY(otbn_busy_wait_for_done());
139 
140  // Reset the message buffer counter.
141  ctx->num_blocks = 0;
142  return OTCRYPTO_OK;
143 }
144 
145 /**
146  * Add a single message block to the processing buffer.
147  *
148  * Runs OTBN if the maximum number of message blocks has been reached.
149  *
150  * @param ctx OTBN message buffer context information (updated in place).
151  * @param block Block to write.
152  * @return Result of the operation.
153  */
154 static status_t process_block(sha512_otbn_ctx_t *ctx,
155  const sha512_message_block_t *block) {
156  // Calculate the offset within the message buffer.
157  size_t offset = ctx->num_blocks * kSha512MessageBlockBytes;
158  otbn_addr_t dst = kOtbnVarSha512Msg + offset;
159 
160  // Copy the message block into DMEM. The SHA-512 app expects 64-bit words
161  // within the message in big-endian form, so we copy 64 bits at a time and
162  // swap the order.
163  for (size_t i = 0; i + 1 < kSha512MessageBlockWords; i += 2) {
164  uint32_t bytes_7to4 = __builtin_bswap32(block->data[i + 1]);
165  uint32_t bytes_3to0 = __builtin_bswap32(block->data[i]);
166  HARDENED_TRY(otbn_dmem_write(1, &bytes_7to4, dst));
167  dst += sizeof(uint32_t);
168  HARDENED_TRY(otbn_dmem_write(1, &bytes_3to0, dst));
169  dst += sizeof(uint32_t);
170  }
171  ctx->num_blocks += 1;
172 
173  // If we've reached the maximum number of message chunks for a single run,
174  // then run the OTBN program to update the state in-place. Note that there
175  // is no need to read back and then re-write the state; it'll stay updated
176  // in DMEM for the next run.
177  if (ctx->num_blocks == kSha512MaxMessageChunksPerOtbnRun) {
178  HARDENED_TRY(process_message_buffer(ctx));
179  }
180  return OTCRYPTO_OK;
181 }
182 
183 /**
184  * Pad the block as described in FIPS 180-4, section 5.1.2.
185  *
186  * Padding fills the current block and may require one additional block. This
187  * function calls `process_block` to load the padded block(s) into OTBN.
188  *
189  * The length of real data in the partial block should be the byte-length of
190  * the message so far (total_len >> 3) modulo `kSha512MessageBlockBytes`.
191  *
192  * @param ctx OTBN message buffer context information (updated in place).
193  * @param total_len Total length of message so far.
194  * @param block Current (partial) block.
195  * @return Result of the operation.
196  */
197 static status_t process_padding(sha512_otbn_ctx_t *ctx,
198  const sha512_message_length_t total_len,
199  sha512_message_block_t *block) {
200  size_t partial_block_len = (total_len.lower >> 3) % kSha512MessageBlockBytes;
201 
202  // Get a byte-sized pointer to the end of the real data within the block.
203  unsigned char *data_end = (unsigned char *)block->data + partial_block_len;
204 
205  // Fill the remainder of the block with zeroes.
206  size_t padding_len = kSha512MessageBlockBytes - partial_block_len;
207  memset(data_end, 0, padding_len);
208 
209  // Set the last byte after the message to 0x80. There must be at least one
210  // unfilled byte in the partial block, since partial_block_len is always <
211  // kSha512MessageBlockBytes.
212  memset(data_end, 0x80, 1);
213 
214  if (partial_block_len + 1 + 2 * sizeof(uint64_t) > kSha512MessageBlockBytes) {
215  // We need to use the additional block. The first block is already
216  // complete, so process it and then zero out the block data again to
217  // prepare the next one.
218  HARDENED_TRY(process_block(ctx, block));
219  memset(block, 0, kSha512MessageBlockBytes);
220  }
221 
222  // Set the last 128 bits (=4 32b words) of the final block to the bit-length
223  // in big-endian form.
224  block->data[kSha512MessageBlockWords - 1] =
225  __builtin_bswap32(total_len.lower & UINT32_MAX);
226  block->data[kSha512MessageBlockWords - 2] =
227  __builtin_bswap32(total_len.lower >> 32);
228  block->data[kSha512MessageBlockWords - 3] =
229  __builtin_bswap32(total_len.upper & UINT32_MAX);
230  block->data[kSha512MessageBlockWords - 4] =
231  __builtin_bswap32(total_len.upper >> 32);
232 
233  // Process the last block.
234  return process_block(ctx, block);
235 }
236 
237 /**
238  * Update the hash state to include new data, optionally adding padding.
239  *
240  * @param state Context object.
241  * @param msg Input message.
242  * @param msg_len Input message length in bytes.
243  * @param padding_needed Whether to pad the message.
244  * @return Result of the operation.
245  */
246 static status_t process_message(sha512_state_t *state, const uint8_t *msg,
247  size_t msg_len,
248  hardened_bool_t padding_needed) {
249  // Load the SHA-512 app. Fails if OTBN is non-idle.
250  HARDENED_TRY(otbn_load_app(kOtbnAppSha512));
251 
252  // Calculate the new value of state->total_len. Do NOT update the state yet
253  // (because if we get an OTBN error, it would become out of sync).
254  sha512_state_t new_state;
255  HARDENED_TRY(get_new_total_len(state, msg_len, &new_state.total_len));
256 
257  // Set the initial state. The OTBN app expects the state in a pre-processed
258  // format, with the 64-bit state words aligned to wide-word boundaries.
259  otbn_addr_t state_write_addr = kOtbnVarSha512State;
260  for (size_t i = 0; i + 1 < kSha512StateWords; i += 2) {
261  HARDENED_TRY(otbn_dmem_write(1, &state->H[i + 1], state_write_addr));
262  HARDENED_TRY(
263  otbn_dmem_write(1, &state->H[i], state_write_addr + sizeof(uint32_t)));
264  state_write_addr += kOtbnWideWordNumBytes;
265  }
266 
267  // Start computing the first block for the hash computation by simply copying
268  // the partial block. We won't use the partial block directly to avoid
269  // contaminating the context object if this operation fails later.
271  size_t partial_block_len =
272  (state->total_len.lower >> 3) % kSha512MessageBlockBytes;
273  hardened_memcpy(block.data, state->partial_block, kSha512MessageBlockWords);
274 
275  // Initialize the context for the OTBN message buffer.
276  sha512_otbn_ctx_t ctx = {.num_blocks = 0};
277 
278  // Process the message one block at a time, including partial data if it is
279  // present (which is only possible on the first iteration).
280  while (msg_len >= kSha512MessageBlockBytes - partial_block_len) {
281  size_t available_len = kSha512MessageBlockBytes - partial_block_len;
282  memcpy((unsigned char *)block.data + partial_block_len, msg, available_len);
283  msg += available_len;
284  msg_len -= available_len;
285  HARDENED_TRY(process_block(&ctx, &block));
286  partial_block_len = 0;
287  }
288 
289  // Copy remaining mesage data into the working block (after partial data, if
290  // it is present). Because of the loop condition above, this must not be a
291  // full block.
292  memcpy((unsigned char *)block.data + partial_block_len, msg, msg_len);
293 
294  // Add padding if necessary.
295  if (padding_needed == kHardenedBoolTrue) {
296  HARDENED_TRY(process_padding(&ctx, new_state.total_len, &block));
297  }
298 
299  // If there are any unprocessed blocks currently in DMEM, run the program one
300  // final time.
301  if (ctx.num_blocks > 0) {
302  HARDENED_TRY(process_message_buffer(&ctx));
303  }
304 
305  // Read the final state from OTBN dmem. The state is still in the special
306  // form the OTBN app uses, with the 64-bit state words aligned to wide-word
307  // boundaries.
308  otbn_addr_t state_read_addr = kOtbnVarSha512State;
309  for (size_t i = 0; i + 1 < kSha512StateWords; i += 2) {
310  HARDENED_TRY(otbn_dmem_read(1, state_read_addr, &new_state.H[i + 1]));
311  HARDENED_TRY(
312  otbn_dmem_read(1, state_read_addr + sizeof(uint32_t), &new_state.H[i]));
313  state_read_addr += kOtbnWideWordNumBytes;
314  }
315 
316  // Clear OTBN's memory.
317  HARDENED_TRY(otbn_dmem_sec_wipe());
318 
319  // At this point, no more errors are possible; it is safe to update the
320  // context object.
321  hardened_memcpy(state->H, new_state.H, kSha512StateWords);
322  hardened_memcpy(state->partial_block, block.data, kSha512MessageBlockWords);
323  state->total_len.lower = new_state.total_len.lower;
324  state->total_len.upper = new_state.total_len.upper;
325  return OTCRYPTO_OK;
326 }
327 
328 status_t sha512_update(sha512_state_t *state, const uint8_t *msg,
329  const size_t msg_len) {
330  // Process new data with no padding.
331  return process_message(state, msg, msg_len, kHardenedBoolFalse);
332 }
333 
334 /**
335  * Replace sensitive data in a SHA-512 context with non-sensitive values.
336  *
337  * @param state The context object to shred.
338  */
339 static void state_shred(sha512_state_t *state) {
340  hardened_memshred(state->H, kSha512StateWords);
341  hardened_memshred(state->partial_block, kSha512MessageBlockWords);
342  state->total_len.lower = 0;
343  state->total_len.upper = 0;
344 }
345 
346 /**
347  * Copy the final SHA-512 digest as a byte-string.
348  *
349  * SHA-512 intermediate computations use words in little-endian format, but the
350  * FIPS 180-4 spec requires big-endian words (see section 3.1). Therefore, to
351  * get the right final byte-order, we need to reverse each word in the state.
352  *
353  * @param state Context object.
354  * @param[out] digest Destination buffer for digest.
355  */
356 static void sha512_digest_get(sha512_state_t *state, uint32_t *digest) {
357  // Reverse the bytes in each word to match FIPS 180-4.
358  for (size_t i = 0; i < kSha512StateWords; i++) {
359  state->H[i] = __builtin_bswap32(state->H[i]);
360  }
361  hardened_memcpy(digest, state->H, kSha512DigestWords);
362 }
363 
364 /**
365  * Copy the final SHA-384 digest as a byte-string.
366  *
367  * The SHA-384 digest is formed the same was as SHA-512, but truncated to 384
368  * bits.
369  *
370  * @param state Context object.
371  * @param[out] digest Destination buffer for digest.
372  */
373 static void sha384_digest_get(sha512_state_t *state, uint32_t *digest) {
374  // Reverse the bytes in each word to match FIPS 180-4.
375  for (size_t i = 0; i < kSha512StateWords; i++) {
376  state->H[i] = __builtin_bswap32(state->H[i]);
377  }
378  hardened_memcpy(digest, state->H, kSha384DigestWords);
379 }
380 
381 status_t sha512_final(sha512_state_t *state, uint32_t *digest) {
382  // Entropy complex needs to be initialized for `state_shred`.
383  HARDENED_TRY(entropy_complex_check());
384 
385  // Construct padding.
386  HARDENED_TRY(process_message(state, NULL, 0, kHardenedBoolTrue));
387 
388  // Copy the digest and then destroy the state.
389  sha512_digest_get(state, digest);
390  state_shred(state);
391  return OTCRYPTO_OK;
392 }
393 
394 status_t sha512(const uint8_t *msg, const size_t msg_len, uint32_t *digest) {
395  // Entropy complex needs to be initialized for `state_shred`.
396  HARDENED_TRY(entropy_complex_check());
397 
398  sha512_state_t state;
399  sha512_init(&state);
400 
401  // Process data with padding enabled.
402  HARDENED_TRY(process_message(&state, msg, msg_len, kHardenedBoolTrue));
403  sha512_digest_get(&state, digest);
404  state_shred(&state);
405  return OTCRYPTO_OK;
406 }
407 
408 status_t sha384_update(sha384_state_t *state, const uint8_t *msg,
409  const size_t msg_len) {
410  // An update for SHA-384 is exactly the same as for SHA-512.
411  return sha512_update(state, msg, msg_len);
412 }
413 
414 status_t sha384_final(sha384_state_t *state, uint32_t *digest) {
415  // Entropy complex needs to be initialized for `state_shred`.
416  HARDENED_TRY(entropy_complex_check());
417 
418  // Construct padding.
419  HARDENED_TRY(process_message(state, NULL, 0, kHardenedBoolTrue));
420 
421  // Copy the digest and then destroy the state.
422  sha384_digest_get(state, digest);
423  state_shred(state);
424  return OTCRYPTO_OK;
425 }
426 
427 status_t sha384(const uint8_t *msg, const size_t msg_len, uint32_t *digest) {
428  // Entropy complex needs to be initialized for `state_shred`.
429  HARDENED_TRY(entropy_complex_check());
430 
431  sha384_state_t state;
432  sha384_init(&state);
433 
434  // Process data with padding enabled.
435  HARDENED_TRY(process_message(&state, msg, msg_len, kHardenedBoolTrue));
436  sha384_digest_get(&state, digest);
437  state_shred(&state);
438  return OTCRYPTO_OK;
439 }