5 #include "sw/device/lib/crypto/impl/aes_gcm/aes_gcm.h"
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"
19 #define MODULE_ID MAKE_MODULE_ID('g', 'c', 'm')
25 kAesBlockLog2NumBytes = 4,
27 static_assert(kAesBlockNumBytes == (1 << kAesBlockLog2NumBytes),
28 "kAesBlockLog2NumBytes does not match kAesBlockNumBytes");
41 static inline uint32_t word_inc32(
const uint32_t word) {
43 return __builtin_bswap32(__builtin_bswap32(word) + 1);
54 static inline void block_inc32(
aes_block_t *block) {
56 block->data[kAesBlockNumWords - 1] =
57 word_inc32(block->data[kAesBlockNumWords - 1]);
67 HARDENED_TRY(aes_encrypt_begin(key, iv));
68 HARDENED_TRY(aes_update(NULL, input));
69 HARDENED_TRY(aes_update(output, NULL));
86 HARDENED_TRY(aes_encrypt_block(key, iv, input, output));
123 size_t input_len,
const uint8_t *input,
124 size_t *output_len, uint8_t *output) {
126 if (key.
mode != kAesCipherModeCtr) {
127 return OTCRYPTO_BAD_ARGS;
130 if (input_len < kAesBlockNumBytes - partial_len) {
132 unsigned char *partial_bytes = (
unsigned char *)partial->data;
133 memcpy(partial_bytes + partial_len, input, input_len);
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;
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;
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;
160 memcpy(partial->data, input, input_len);
182 memset(zero.data, 0, kAesBlockNumBytes);
184 HARDENED_TRY(aes_encrypt_block(key, &zero, &zero, &hash_subkey));
187 ghash_init_subkey(hash_subkey.data, ctx);
205 static status_t aes_gcm_counter(
const size_t iv_len,
const uint32_t *iv,
211 j0->data[kAesBlockNumWords - 1] = __builtin_bswap32(1);
212 }
else if (iv_len == 4) {
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);
224 return OTCRYPTO_BAD_ARGS;
242 static status_t aes_gcm_get_tag(aes_gcm_context_t *ctx,
size_t tag_len,
246 uint64_t last_block[2] = {
247 __builtin_bswap64(((uint64_t)ctx->aad_len) * 8),
248 __builtin_bswap64(((uint64_t)ctx->input_len) * 8),
252 ghash_update(&ctx->ghash_ctx, kAesBlockNumBytes, (
unsigned char *)last_block);
254 ghash_final(&ctx->ghash_ctx, s.data);
257 uint32_t full_tag[kAesBlockNumWords];
260 HARDENED_TRY(aes_gcm_gctr(ctx->key, &ctx->initial_counter_block,
261 0, &empty, kAesBlockNumBytes,
262 (
unsigned char *)s.data, &full_tag_len,
263 (
unsigned char *)full_tag));
266 if (full_tag_len != kAesBlockNumBytes) {
267 return OTCRYPTO_FATAL_ERR;
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,
305 const uint32_t *iv, aes_gcm_context_t *ctx) {
308 if (ctx == NULL || iv == NULL || (iv_len != 3 && iv_len != 4)) {
309 return OTCRYPTO_BAD_ARGS;
313 HARDENED_TRY(aes_gcm_hash_subkey(key, &ctx->ghash_ctx));
316 HARDENED_TRY(aes_gcm_counter(iv_len, iv, &ctx->ghash_ctx,
317 &ctx->initial_counter_block));
321 memcpy(ctx->gctr_iv.data, ctx->initial_counter_block.data, kAesBlockNumBytes);
322 block_inc32(&ctx->gctr_iv);
334 ghash_init(&ctx->ghash_ctx);
343 ctx->partial_aes_block = (
aes_block_t){.data = {0}};
349 const uint32_t *iv, aes_gcm_context_t *ctx) {
351 return aes_gcm_init(key, iv_len, iv, ctx);
354 status_t aes_gcm_update_aad(aes_gcm_context_t *ctx,
const size_t aad_len,
355 const uint8_t *aad) {
364 if (aad_len > UINT32_MAX - ctx->aad_len) {
365 return OTCRYPTO_BAD_ARGS;
371 if (ctx == NULL || aad == NULL || ctx->input_len > 0) {
372 return OTCRYPTO_BAD_ARGS;
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;
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,
388 if (input_len == 0) {
395 if (input_len > UINT32_MAX - ctx->input_len) {
396 return OTCRYPTO_BAD_ARGS;
400 if (ctx == NULL || input == NULL || output == NULL) {
401 return OTCRYPTO_BAD_ARGS;
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);
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));
423 if (*output_len % kGhashBlockNumBytes != 0) {
424 return OTCRYPTO_RECOV_ERR;
426 ghash_process_full_blocks(&ctx->ghash_ctx, 0,
427 &ctx->partial_ghash_block, *output_len, output);
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);
433 return OTCRYPTO_BAD_ARGS;
436 ctx->input_len += input_len;
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) {
455 if (ctx == NULL || output_len == NULL || tag == NULL) {
456 return OTCRYPTO_BAD_ARGS;
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);
471 size_t partial_aes_block_len = ctx->input_len % kAesBlockNumBytes;
472 if (partial_aes_block_len == 0) {
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);
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;
489 if (*output_len > 0) {
490 ghash_update(&ctx->ghash_ctx, *output_len, (
unsigned char *)output);
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);
499 return OTCRYPTO_BAD_ARGS;
502 return aes_gcm_get_tag(ctx, tag_len, tag);
505 status_t aes_gcm_encrypt_final(aes_gcm_context_t *ctx,
size_t tag_len,
506 uint32_t *tag,
size_t *output_len,
508 return aes_gcm_final(ctx, tag_len, tag, output_len, output);
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,
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,
529 const uint32_t *iv, aes_gcm_context_t *ctx) {
531 return aes_gcm_init(key, iv_len, iv, ctx);
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,
538 uint32_t expected_tag[tag_len];
539 size_t bytes_written;
541 aes_gcm_final(ctx, tag_len, expected_tag, &bytes_written, output));
550 memset(output, 0, bytes_written);