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