Software APIs
aes_gcm.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/aes_gcm/aes_gcm.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
14 #include "sw/device/lib/crypto/drivers/aes.h"
15 #include "sw/device/lib/crypto/impl/aes_gcm/ghash.h"
16 #include "sw/device/lib/crypto/impl/status.h"
17 
18 // Module ID for status codes.
19 #define MODULE_ID MAKE_MODULE_ID('g', 'c', 'm')
20 
21 enum {
22  /**
23  * Log2 of the number of bytes in an AES block.
24  */
25  kAesBlockLog2NumBytes = 4,
26 };
27 static_assert(kAesBlockNumBytes == (1 << kAesBlockLog2NumBytes),
28  "kAesBlockLog2NumBytes does not match kAesBlockNumBytes");
29 
30 /**
31  * Increment a 32-bit big-endian word.
32  *
33  * This operation theoretically increments the "rightmost" (last) 32 bits of
34  * the input modulo 2^32. However, NIST treats all bitvectors as big-endian and
35  * the processor is little-endian. In order to increment we first need to
36  * reverse the bytes of the 32-bit word, then increment, then reverse it back.
37  *
38  * @param word Input word in big-endian form.
39  * @returns (word + 1) mod 2^32 in big-endian form.
40  */
41 static inline uint32_t word_inc32(const uint32_t word) {
42  // Reverse the bytes, increment, and reverse back.
43  return __builtin_bswap32(__builtin_bswap32(word) + 1);
44 }
45 
46 /**
47  * Implements the inc32() function on blocks from NIST SP800-38D.
48  *
49  * Interprets the last (rightmost) 32 bits of the block as a big-endian integer
50  * and increments this value modulo 2^32 in-place.
51  *
52  * @param block AES block, modified in place.
53  */
54 static inline void block_inc32(aes_block_t *block) {
55  // Set the last word to the incremented value.
56  block->data[kAesBlockNumWords - 1] =
57  word_inc32(block->data[kAesBlockNumWords - 1]);
58 }
59 
60 /**
61  * One-shot version of the AES encryption API for a single block.
62  */
64 static status_t aes_encrypt_block(const aes_key_t key, const aes_block_t *iv,
65  const aes_block_t *input,
66  aes_block_t *output) {
67  HARDENED_TRY(aes_encrypt_begin(key, iv));
68  HARDENED_TRY(aes_update(/*dest=*/NULL, input));
69  HARDENED_TRY(aes_update(output, /*src=*/NULL));
70  return aes_end(NULL);
71 }
72 
73 /**
74  * Run GCTR on exactly one block of input.
75  *
76  * Updates the IV in-place.
77  *
78  * @param key The AES key
79  * @param iv Initialization vector, 128 bits
80  * @param input Input block
81  * @param[out] output Output block
82  */
84 static status_t gctr_process_block(const aes_key_t key, aes_block_t *iv,
85  aes_block_t *input, aes_block_t *output) {
86  HARDENED_TRY(aes_encrypt_block(key, iv, input, output));
87  block_inc32(iv);
88  return OTCRYPTO_OK;
89 }
90 
91 /**
92  * Implements the GCTR function as specified in SP800-38D, section 6.5.
93  *
94  * The block cipher is fixed to AES. Note that the GCTR function is a modified
95  * version of the AES-CTR mode of encryption.
96  *
97  * Appends the new data to the partial data and then processes any resulting
98  * full blocks. Finally, updates the partial data to hold any data that was
99  * left over. The partial block may be empty, but should never be full;
100  * `partial_len` should always be less than `kAesBlockNumBytes`.
101  *
102  * The output buffer should have enough space to hold all full blocks of
103  * partial data + input data. The partial data length after this function will
104  * always be `(partial_len + input_len) % kAesBlockNumBytes`.
105  *
106  * Updates the IV and partial block in-place; it is possible to call this
107  * function again with the updated IV and partial data on additional data to
108  * generate more output, and the result should be the same as if all the data
109  * was passed in one call.
110  *
111  * @param key The AES key
112  * @param iv Initialization vector, 128 bits
113  * @param partial_len Length of partial block data in bytes.
114  * @param partial Partial AES block.
115  * @param input_len Number of bytes for input and output
116  * @param input Pointer to input buffer (may be NULL if `len` is 0)
117  * @param[out] output_len Number of output bytes written
118  * @param[out] output Pointer to output buffer
119  */
121 static status_t aes_gcm_gctr(const aes_key_t key, aes_block_t *iv,
122  size_t partial_len, aes_block_t *partial,
123  size_t input_len, const uint8_t *input,
124  size_t *output_len, uint8_t *output) {
125  // Key must be intended for CTR mode.
126  if (key.mode != kAesCipherModeCtr) {
127  return OTCRYPTO_BAD_ARGS;
128  }
129 
130  if (input_len < kAesBlockNumBytes - partial_len) {
131  // Not enough data for a full block; copy into the partial block.
132  unsigned char *partial_bytes = (unsigned char *)partial->data;
133  memcpy(partial_bytes + partial_len, input, input_len);
134  } else {
135  // Construct a block from the partial data and the start of the new data.
136  unsigned char *partial_bytes = (unsigned char *)partial->data;
137  memcpy(partial_bytes + partial_len, input, kAesBlockNumBytes - partial_len);
138  input += kAesBlockNumBytes - partial_len;
139  input_len -= kAesBlockNumBytes - partial_len;
140 
141  // Process the block.
142  aes_block_t block_out;
143  HARDENED_TRY(gctr_process_block(key, iv, partial, &block_out));
144  memcpy(output, block_out.data, kAesBlockNumBytes);
145  output += kAesBlockNumBytes;
146  *output_len = kAesBlockNumBytes;
147 
148  // Process any remaining full blocks of input.
149  while (input_len >= kAesBlockNumBytes) {
150  memcpy(partial->data, input, kAesBlockNumBytes);
151  HARDENED_TRY(gctr_process_block(key, iv, partial, &block_out));
152  memcpy(output, block_out.data, kAesBlockNumBytes);
153  output += kAesBlockNumBytes;
154  *output_len += kAesBlockNumBytes;
155  input += kAesBlockNumBytes;
156  input_len -= kAesBlockNumBytes;
157  }
158 
159  // Copy any remaining input into the partial block.
160  memcpy(partial->data, input, input_len);
161  }
162 
163  return OTCRYPTO_OK;
164 }
165 
166 /**
167  * Compute and set the hash subkey for AES-GCM.
168  *
169  * If any step in this process fails, the function returns an error and the
170  * output should not be used.
171  *
172  * @param key AES key
173  * @param[out] ctx Destination GHASH context object
174  * @return OK or error
175  */
177 static status_t aes_gcm_hash_subkey(const aes_key_t key, ghash_context_t *ctx) {
178  // Compute the initial hash subkey H = AES_K(0). Note that to get this
179  // result from AES_CTR, we set both the IV and plaintext to zero; this way,
180  // AES-CTR's final XOR with the plaintext does nothing.
181  aes_block_t zero;
182  memset(zero.data, 0, kAesBlockNumBytes);
183  aes_block_t hash_subkey;
184  HARDENED_TRY(aes_encrypt_block(key, &zero, &zero, &hash_subkey));
185 
186  // Set the key for the GHASH context.
187  ghash_init_subkey(hash_subkey.data, ctx);
188 
189  return OTCRYPTO_OK;
190 }
191 
192 /**
193  * Compute the counter block based on the given IV and hash subkey.
194  *
195  * This block is called J0 in the NIST documentation, and is the same for both
196  * encryption and decryption.
197  *
198  * @param iv_len IV length in 32-bit words
199  * @param iv IV value
200  * @param ctx GHASH context with product table for hash subkey H
201  * @param[out] j0 Destination for the output counter block
202  * @return OK or error
203  */
205 static status_t aes_gcm_counter(const size_t iv_len, const uint32_t *iv,
206  ghash_context_t *ctx, aes_block_t *j0) {
207  if (iv_len == 3) {
208  // If the IV is 96 bits, then J0 = (IV || {0}^31 || 1).
209  hardened_memcpy(j0->data, iv, iv_len);
210  // Set the last word to 1 (as a big-endian integer).
211  j0->data[kAesBlockNumWords - 1] = __builtin_bswap32(1);
212  } else if (iv_len == 4) {
213  // If the IV is 128 bits, then J0 = GHASH(H, IV || {0}^120 || 0x80), where
214  // {0}^120 means 120 zero bits (15 0x00 bytes).
215  ghash_init(ctx);
216  ghash_update(ctx, iv_len * sizeof(uint32_t), (unsigned char *)iv);
217  uint8_t buffer[kAesBlockNumBytes];
218  memset(buffer, 0, kAesBlockNumBytes);
219  buffer[kAesBlockNumBytes - 1] = 0x80;
220  ghash_update(ctx, kAesBlockNumBytes, buffer);
221  ghash_final(ctx, j0->data);
222  } else {
223  // Should not happen; invalid IV length.
224  return OTCRYPTO_BAD_ARGS;
225  }
226 
227  return OTCRYPTO_OK;
228 }
229 
230 /**
231  * Compute the AES-GCM authentication tag.
232  *
233  * Expects the GHASH context parameter of `ctx` to represent GHASH(H, expand(A)
234  * || expand(C)), where A is the aad, C is the ciphertext, and expand(x) pads x
235  * to a multiple of 128 bits by adding zeroes to the right-hand side.
236  *
237  * @param ctx AES-GCM context
238  * @param tag_len Tag length in 32-bit words
239  * @param[out] tag Buffer for output tag.
240  */
242 static status_t aes_gcm_get_tag(aes_gcm_context_t *ctx, size_t tag_len,
243  uint32_t *tag) {
244  // Compute len64(A) and len64(C) by computing the length in *bits* (shift by
245  // 3) and then converting to big-endian.
246  uint64_t last_block[2] = {
247  __builtin_bswap64(((uint64_t)ctx->aad_len) * 8),
248  __builtin_bswap64(((uint64_t)ctx->input_len) * 8),
249  };
250 
251  // Finish computing S by appending (len64(A) || len64(C)).
252  ghash_update(&ctx->ghash_ctx, kAesBlockNumBytes, (unsigned char *)last_block);
253  aes_block_t s;
254  ghash_final(&ctx->ghash_ctx, s.data);
255 
256  // Compute the tag T = GCTR(K, J0, S).
257  uint32_t full_tag[kAesBlockNumWords];
258  size_t full_tag_len;
259  aes_block_t empty = {.data = {0}};
260  HARDENED_TRY(aes_gcm_gctr(ctx->key, &ctx->initial_counter_block,
261  /*partial_len=*/0, &empty, kAesBlockNumBytes,
262  (unsigned char *)s.data, &full_tag_len,
263  (unsigned char *)full_tag));
264 
265  // Sanity check.
266  if (full_tag_len != kAesBlockNumBytes) {
267  return OTCRYPTO_FATAL_ERR;
268  }
269 
270  // Truncate the tag if needed. NIST requires we take the most significant
271  // bits in big-endian representation, which corresponds to the least
272  // significant bits in Ibex's little-endian representation.
273  hardened_memcpy(tag, full_tag, tag_len);
274  return OTCRYPTO_OK;
275 }
276 
277 status_t aes_gcm_encrypt(const aes_key_t key, const size_t iv_len,
278  const uint32_t *iv, const size_t plaintext_len,
279  const uint8_t *plaintext, const size_t aad_len,
280  const uint8_t *aad, const size_t tag_len,
281  uint32_t *tag, uint8_t *ciphertext) {
282  aes_gcm_context_t ctx;
283  HARDENED_TRY(aes_gcm_encrypt_init(key, iv_len, iv, &ctx));
284  HARDENED_TRY(aes_gcm_update_aad(&ctx, aad_len, aad));
285  size_t ciphertext_bytes_written;
286  HARDENED_TRY(aes_gcm_update_encrypted_data(
287  &ctx, plaintext_len, plaintext, &ciphertext_bytes_written, ciphertext));
288  ciphertext += ciphertext_bytes_written;
289  return aes_gcm_encrypt_final(&ctx, tag_len, tag, &ciphertext_bytes_written,
290  ciphertext);
291 }
292 
293 /**
294  * Starts an AES-GCM operation.
295  *
296  * This process is actually the same for both encryption and decryption.
297  *
298  * @param key Underlying AES-CTR key.
299  * @param iv_len Length of the initialization vector in 32-bit words.
300  * @param iv Initialization vector (nonce).
301  * @param[out] ctx Initialized context object.
302  * @return Error status; OK if no errors.
303  */
304 static status_t aes_gcm_init(const aes_key_t key, const size_t iv_len,
305  const uint32_t *iv, aes_gcm_context_t *ctx) {
306  // Check for null pointers and IV length (must be 96 or 128 bits = 3 or 4
307  // words).
308  if (ctx == NULL || iv == NULL || (iv_len != 3 && iv_len != 4)) {
309  return OTCRYPTO_BAD_ARGS;
310  }
311 
312  // Initialize the hash subkey H.
313  HARDENED_TRY(aes_gcm_hash_subkey(key, &ctx->ghash_ctx));
314 
315  // Compute the counter block (called J0 in the NIST specification).
316  HARDENED_TRY(aes_gcm_counter(iv_len, iv, &ctx->ghash_ctx,
317  &ctx->initial_counter_block));
318 
319  // Set the initial IV for GCTR to inc32(J0).
320  // The eventual ciphertext is C = GCTR(K, inc32(J0), plaintext).
321  memcpy(ctx->gctr_iv.data, ctx->initial_counter_block.data, kAesBlockNumBytes);
322  block_inc32(&ctx->gctr_iv);
323 
324  // Initialize the GHASH context. We will eventually compute
325  // S = GHASH(H, expand(A) || expand(C) || len64(A) || len64(C))
326  // where:
327  // * A is the aad, C is the ciphertext
328  // * expand(x) pads x to a multiple of 128 bits by adding zeroes to the
329  // right-hand side
330  // * len64(x) is the length of x in bits expressed as a
331  // big-endian 64-bit integer.
332  //
333  // The tag will eventually be T = GCTR(K, J0, S).
334  ghash_init(&ctx->ghash_ctx);
335 
336  // Initialize the key and lengths.
337  memcpy(&ctx->key, &key, sizeof(aes_key_t));
338  ctx->aad_len = 0;
339  ctx->input_len = 0;
340 
341  // Zeroize the partial blocks.
342  ctx->partial_ghash_block = (ghash_block_t){.data = {0}};
343  ctx->partial_aes_block = (aes_block_t){.data = {0}};
344 
345  return OTCRYPTO_OK;
346 }
347 
348 status_t aes_gcm_encrypt_init(const aes_key_t key, const size_t iv_len,
349  const uint32_t *iv, aes_gcm_context_t *ctx) {
350  ctx->is_encrypt = kHardenedBoolTrue;
351  return aes_gcm_init(key, iv_len, iv, ctx);
352 }
353 
354 status_t aes_gcm_update_aad(aes_gcm_context_t *ctx, const size_t aad_len,
355  const uint8_t *aad) {
356  // If the length is 0, we have nothing to do.
357  if (aad_len == 0) {
358  return OTCRYPTO_OK;
359  }
360 
361  // Check that the total AAD length is < 2^32 bytes. This is stricter than
362  // NIST requires, but SP800-38D also allows implementations to stipulate
363  // lower length limits.
364  if (aad_len > UINT32_MAX - ctx->aad_len) {
365  return OTCRYPTO_BAD_ARGS;
366  }
367 
368  // Check for null pointers and ensure we are in the expected state. Once
369  // we've started accumulating encrypted data, we can't add more associated
370  // data because of the structure of the tag's GHASH operation.
371  if (ctx == NULL || aad == NULL || ctx->input_len > 0) {
372  return OTCRYPTO_BAD_ARGS;
373  }
374 
375  // Accumulate any full blocks of AAD into the tag's GHASH computation.
376  size_t partial_ghash_block_len = ctx->aad_len % kGhashBlockNumBytes;
377  ghash_process_full_blocks(&ctx->ghash_ctx, partial_ghash_block_len,
378  &ctx->partial_ghash_block, aad_len, aad);
379  ctx->aad_len += aad_len;
380 
381  return OTCRYPTO_OK;
382 }
383 
384 status_t aes_gcm_update_encrypted_data(aes_gcm_context_t *ctx, size_t input_len,
385  const uint8_t *input, size_t *output_len,
386  uint8_t *output) {
387  // If the length is 0, we have nothing to do.
388  if (input_len == 0) {
389  return OTCRYPTO_OK;
390  }
391 
392  // Check that the total input length is < 2^32 bytes. This is stricter
393  // than NIST requires, but SP800-38D also allows implementations to stipulate
394  // lower length limits.
395  if (input_len > UINT32_MAX - ctx->input_len) {
396  return OTCRYPTO_BAD_ARGS;
397  }
398 
399  // Check for null pointers.
400  if (ctx == NULL || input == NULL || output == NULL) {
401  return OTCRYPTO_BAD_ARGS;
402  }
403 
404  // If this is the first part of the plaintext and we haven't finished the AAD
405  // yet, process the remaining partial AAD and update the state.
406  size_t partial_ghash_block_len = ctx->aad_len % kGhashBlockNumBytes;
407  if (ctx->input_len == 0 && partial_ghash_block_len != 0) {
408  ghash_update(&ctx->ghash_ctx, partial_ghash_block_len,
409  (unsigned char *)ctx->partial_ghash_block.data);
410  }
411 
412  // Process any full blocks of input with GCTR to generate more ciphertext.
413  size_t partial_aes_block_len = ctx->input_len % kAesBlockNumBytes;
414  HARDENED_TRY(aes_gcm_gctr(ctx->key, &ctx->gctr_iv, partial_aes_block_len,
415  &ctx->partial_aes_block, input_len, input,
416  output_len, output));
417 
418  // Accumulate any new ciphertext to the GHASH context. The ciphertext is the
419  // output for encryption, and the input for decryption.
420  if (ctx->is_encrypt == kHardenedBoolTrue) {
421  // Since we only generate ciphertext in full-block increments, no partial
422  // blocks are possible in this case.
423  if (*output_len % kGhashBlockNumBytes != 0) {
424  return OTCRYPTO_RECOV_ERR;
425  }
426  ghash_process_full_blocks(&ctx->ghash_ctx, /*partial_len=*/0,
427  &ctx->partial_ghash_block, *output_len, output);
428  } else if (ctx->is_encrypt == kHardenedBoolFalse) {
429  size_t partial_ghash_block_len = ctx->input_len % kGhashBlockNumBytes;
430  ghash_process_full_blocks(&ctx->ghash_ctx, partial_ghash_block_len,
431  &ctx->partial_ghash_block, input_len, input);
432  } else {
433  return OTCRYPTO_BAD_ARGS;
434  }
435 
436  ctx->input_len += input_len;
437  return OTCRYPTO_OK;
438 }
439 
440 /**
441  * Finalize an AES-GCM operation: process remaining data and get the tag.
442  *
443  * This procedure is the same for encryption and decryption, although
444  * decryption must compare the tag afterwards.
445  *
446  * @param ctx AES-GCM context.
447  * @param tag_len Tag length in 32-bit words.
448  * @param[out] tag Buffer for the tag.
449  * @param[out] output_len Number of bytes written to `output`.
450  * @param[out] output Buffer for output data.
451  */
452 status_t aes_gcm_final(aes_gcm_context_t *ctx, size_t tag_len, uint32_t *tag,
453  size_t *output_len, uint8_t *output) {
454  // Check for null pointers.
455  if (ctx == NULL || output_len == NULL || tag == NULL) {
456  return OTCRYPTO_BAD_ARGS;
457  }
458 
459  // If there was no input (we never entered the "update encrypted data"
460  // stage), process the remaining partial AAD and update the state.
461  size_t partial_ghash_block_len = ctx->aad_len % kGhashBlockNumBytes;
462  if (ctx->input_len == 0 && partial_ghash_block_len != 0) {
463  size_t partial_ghash_block_len = ctx->aad_len % kGhashBlockNumBytes;
464  ghash_update(&ctx->ghash_ctx, partial_ghash_block_len,
465  (unsigned char *)ctx->partial_ghash_block.data);
466  }
467 
468  // If a partial block of input data remains, pad it with zeroes and generate
469  // one last block of output, which is then truncated to match the input
470  // length.
471  size_t partial_aes_block_len = ctx->input_len % kAesBlockNumBytes;
472  if (partial_aes_block_len == 0) {
473  *output_len = 0;
474  } else {
475  unsigned char *partial_aes_block_bytes =
476  (unsigned char *)ctx->partial_aes_block.data;
477  memset(partial_aes_block_bytes + partial_aes_block_len, 0,
478  kAesBlockNumBytes - partial_aes_block_len);
479  aes_block_t block_out;
480  HARDENED_TRY(gctr_process_block(ctx->key, &ctx->gctr_iv,
481  &ctx->partial_aes_block, &block_out));
482  memcpy(output, block_out.data, partial_aes_block_len);
483  *output_len = partial_aes_block_len;
484  }
485 
486  if (ctx->is_encrypt == kHardenedBoolTrue) {
487  // If a partial block of ciphertext (output for encryption) was generated,
488  // accumulate in GHASH.
489  if (*output_len > 0) {
490  ghash_update(&ctx->ghash_ctx, *output_len, (unsigned char *)output);
491  }
492  } else if (ctx->is_encrypt == kHardenedBoolFalse) {
493  // If a partial block of ciphertext (input for decryption) remains,
494  // accumulate it in GHASH.
495  size_t partial_ghash_block_len = ctx->input_len % kGhashBlockNumBytes;
496  ghash_update(&ctx->ghash_ctx, partial_ghash_block_len,
497  (unsigned char *)ctx->partial_ghash_block.data);
498  } else {
499  return OTCRYPTO_BAD_ARGS;
500  }
501 
502  return aes_gcm_get_tag(ctx, tag_len, tag);
503 }
504 
505 status_t aes_gcm_encrypt_final(aes_gcm_context_t *ctx, size_t tag_len,
506  uint32_t *tag, size_t *output_len,
507  uint8_t *output) {
508  return aes_gcm_final(ctx, tag_len, tag, output_len, output);
509 }
510 
511 status_t aes_gcm_decrypt(const aes_key_t key, const size_t iv_len,
512  const uint32_t *iv, const size_t ciphertext_len,
513  const uint8_t *ciphertext, const size_t aad_len,
514  const uint8_t *aad, const size_t tag_len,
515  const uint32_t *tag, uint8_t *plaintext,
516  hardened_bool_t *success) {
517  aes_gcm_context_t ctx;
518  HARDENED_TRY(aes_gcm_decrypt_init(key, iv_len, iv, &ctx));
519  HARDENED_TRY(aes_gcm_update_aad(&ctx, aad_len, aad));
520  size_t plaintext_bytes_written;
521  HARDENED_TRY(aes_gcm_update_encrypted_data(
522  &ctx, ciphertext_len, ciphertext, &plaintext_bytes_written, plaintext));
523  plaintext += plaintext_bytes_written;
524  return aes_gcm_decrypt_final(&ctx, tag_len, tag, &plaintext_bytes_written,
525  plaintext, success);
526 }
527 
528 status_t aes_gcm_decrypt_init(const aes_key_t key, const size_t iv_len,
529  const uint32_t *iv, aes_gcm_context_t *ctx) {
530  ctx->is_encrypt = kHardenedBoolFalse;
531  return aes_gcm_init(key, iv_len, iv, ctx);
532 }
533 
534 status_t aes_gcm_decrypt_final(aes_gcm_context_t *ctx, size_t tag_len,
535  const uint32_t *tag, size_t *output_len,
536  uint8_t *output, hardened_bool_t *success) {
537  // Get the expected authentication tag.
538  uint32_t expected_tag[tag_len];
539  size_t bytes_written;
540  HARDENED_TRY(
541  aes_gcm_final(ctx, tag_len, expected_tag, &bytes_written, output));
542 
543  // Compare the expected tag to the actual tag (in constant time).
544  *success = hardened_memeq(expected_tag, tag, tag_len);
545  if (*success != kHardenedBoolTrue) {
546  // If authentication fails, zero the plaintext so that the caller does not
547  // use the unauthenticated decrypted data. We still use `OTCRYPTO_OK`
548  // because there was no internal error during the authentication check.
549  *success = kHardenedBoolFalse;
550  memset(output, 0, bytes_written);
551  }
552 
553  return OTCRYPTO_OK;
554 }