@@ -42,6 +42,20 @@ enum {
4242 kAesGcmContextNumWords = sizeof (aes_gcm_context_t ) / sizeof (uint32_t ),
4343};
4444
45+ /**
46+ * AES cleanup guard.
47+ */
48+ static void aes_wipe_guard (uint32_t * dummy ) { (void )aes_clear (); }
49+
50+ /**
51+ * Sideload cleanup guard.
52+ */
53+ static void sideload_wipe_guard (hardened_bool_t * is_sideloaded ) {
54+ if (* is_sideloaded == kHardenedBoolTrue ) {
55+ (void )keymgr_sideload_clear_aes ();
56+ }
57+ }
58+
4559/**
4660 * Save an AES-GCM context.
4761 *
@@ -252,30 +266,6 @@ static status_t load_key_if_sideloaded(const aes_key_t key) {
252266 return keymgr_generate_key_aes (diversification );
253267}
254268
255- /**
256- * Clear the sideload slot if the AES key was sideloaded.
257- *
258- * It is important to clear the sideload slot before returning to the caller so
259- * that other applications can't access the key in between operations.
260- *
261- * If the key is not a sideloaded key, this function does nothing.
262- *
263- * @param key Key that was possibly loaded.
264- * @return OK or errror.
265- */
266- static status_t clear_key_if_sideloaded (const aes_key_t key ) {
267- if (launder32 (key .sideload ) == kHardenedBoolFalse ) {
268- HARDENED_CHECK_EQ (key .sideload , launder32 (kHardenedBoolFalse ));
269- return OTCRYPTO_OK ;
270- } else if (launder32 (key .sideload ) != kHardenedBoolTrue ) {
271- // COVERAGE (SW ERR) This is an internal function, the aes key's sideload is
272- // set internal by good parameters.
273- return OTCRYPTO_BAD_ARGS ;
274- }
275- HARDENED_CHECK_EQ (key .sideload , launder32 (kHardenedBoolTrue ));
276- return keymgr_sideload_clear_aes ();
277- }
278-
279269otcrypto_status_t otcrypto_aes_gcm_encrypt (
280270 otcrypto_blinded_key_t * key , const otcrypto_const_byte_buf_t * plaintext ,
281271 const otcrypto_const_word32_buf_t * iv , const otcrypto_const_byte_buf_t * aad ,
@@ -300,6 +290,11 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(
300290 }
301291#endif
302292
293+ // LIFO Cleanup: aes_clear() executes before sideload_clear().
294+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
295+ kHardenedBoolFalse ;
296+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
297+
303298 // Ensure the plaintext and ciphertext lengths match.
304299 if (launder32 (ciphertext -> len ) != plaintext -> len ) {
305300 return OTCRYPTO_BAD_ARGS ;
@@ -315,6 +310,9 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(
315310 // Construct the AES key.
316311 aes_key_t aes_key ;
317312 HARDENED_TRY (aes_gcm_key_construct (key , & aes_key ));
313+ if (launder32 (aes_key .sideload ) == kHardenedBoolTrue ) {
314+ is_sideloaded = kHardenedBoolTrue ;
315+ }
318316 HARDENED_TRY (load_key_if_sideloaded (aes_key ));
319317
320318 // Call the core encryption operation.
@@ -323,8 +321,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(
323321 auth_tag -> len , key -> config .security_level ,
324322 auth_tag -> data , ciphertext -> data ));
325323
326- HARDENED_TRY (clear_key_if_sideloaded (aes_key ));
327-
328324 // Verify the input buffers
329325 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (plaintext ));
330326 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (iv ));
@@ -359,9 +355,16 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt(
359355 }
360356#endif
361357
358+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
359+ kHardenedBoolFalse ;
360+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
361+
362362 // Construct the AES key.
363363 aes_key_t aes_key ;
364364 HARDENED_TRY (aes_gcm_key_construct (key , & aes_key ));
365+ if (launder32 (aes_key .sideload ) == kHardenedBoolTrue ) {
366+ is_sideloaded = kHardenedBoolTrue ;
367+ }
365368 HARDENED_TRY (load_key_if_sideloaded (aes_key ));
366369
367370 // Ensure the plaintext and ciphertext lengths match.
@@ -379,8 +382,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt(
379382 auth_tag -> len , auth_tag -> data , plaintext -> data ,
380383 key -> config .security_level , success ));
381384
382- HARDENED_TRY (clear_key_if_sideloaded (aes_key ));
383-
384385 // Verify the input buffers
385386 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (plaintext ));
386387 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (iv ));
@@ -401,19 +402,25 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_init(
401402 }
402403#endif
403404
405+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
406+ kHardenedBoolFalse ;
407+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
408+
404409 // Construct the AES key.
405410 aes_key_t aes_key ;
406411 HARDENED_TRY (aes_gcm_key_construct (key , & aes_key ));
412+ if (launder32 (aes_key .sideload ) == kHardenedBoolTrue ) {
413+ is_sideloaded = kHardenedBoolTrue ;
414+ }
407415 HARDENED_TRY (load_key_if_sideloaded (aes_key ));
408416
409417 // Call the internal init operation.
410418 aes_gcm_context_t internal_ctx ;
411419 internal_ctx .security_level = key -> config .security_level ;
412420 HARDENED_TRY (aes_gcm_encrypt_init (aes_key , iv -> len , iv -> data , & internal_ctx ));
413421
414- // Save the context and clear the key if needed .
422+ // Save the context.
415423 HARDENED_TRY (gcm_context_save (& internal_ctx , ctx ));
416- HARDENED_TRY (clear_key_if_sideloaded (internal_ctx .key ));
417424
418425 // Verify the input buffer
419426 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (iv ));
@@ -431,19 +438,25 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_init(
431438 }
432439#endif
433440
441+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
442+ kHardenedBoolFalse ;
443+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
444+
434445 // Construct the AES key.
435446 aes_key_t aes_key ;
436447 HARDENED_TRY (aes_gcm_key_construct (key , & aes_key ));
448+ if (launder32 (aes_key .sideload ) == kHardenedBoolTrue ) {
449+ is_sideloaded = kHardenedBoolTrue ;
450+ }
437451 HARDENED_TRY (load_key_if_sideloaded (aes_key ));
438452
439453 // Call the internal init operation.
440454 aes_gcm_context_t internal_ctx ;
441455 internal_ctx .security_level = key -> config .security_level ;
442456 HARDENED_TRY (aes_gcm_decrypt_init (aes_key , iv -> len , iv -> data , & internal_ctx ));
443457
444- // Save the context and clear the key if needed .
458+ // Save the context.
445459 HARDENED_TRY (gcm_context_save (& internal_ctx , ctx ));
446- HARDENED_TRY (clear_key_if_sideloaded (internal_ctx .key ));
447460
448461 // Verify the input buffer
449462 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (iv ));
@@ -465,17 +478,23 @@ otcrypto_status_t otcrypto_aes_gcm_update_aad(
465478 return OTCRYPTO_OK ;
466479 }
467480
481+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
482+ kHardenedBoolFalse ;
483+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
484+
468485 // Restore the AES-GCM context object and load the key if needed.
469486 aes_gcm_context_t internal_ctx ;
470487 HARDENED_TRY (gcm_context_restore (ctx , & internal_ctx ));
488+ if (launder32 (internal_ctx .key .sideload ) == kHardenedBoolTrue ) {
489+ is_sideloaded = kHardenedBoolTrue ;
490+ }
471491 HARDENED_TRY (load_key_if_sideloaded (internal_ctx .key ));
472492
473493 // Call the internal update operation.
474494 HARDENED_TRY (aes_gcm_update_aad (& internal_ctx , aad -> len , aad -> data ));
475495
476- // Save the context and clear the key if needed .
496+ // Save the context.
477497 HARDENED_TRY (gcm_context_save (& internal_ctx , ctx ));
478- HARDENED_TRY (clear_key_if_sideloaded (internal_ctx .key ));
479498
480499 // Verify the input buffer
481500 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (aad ));
@@ -500,9 +519,16 @@ otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data(
500519 return OTCRYPTO_OK ;
501520 }
502521
522+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
523+ kHardenedBoolFalse ;
524+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
525+
503526 // Restore the AES-GCM context object and load the key if needed.
504527 aes_gcm_context_t internal_ctx ;
505528 HARDENED_TRY (gcm_context_restore (ctx , & internal_ctx ));
529+ if (launder32 (internal_ctx .key .sideload ) == kHardenedBoolTrue ) {
530+ is_sideloaded = kHardenedBoolTrue ;
531+ }
506532 HARDENED_TRY (load_key_if_sideloaded (internal_ctx .key ));
507533 // Remask the key if it is not sideloaded.
508534 HARDENED_TRY (gcm_remask_key (& internal_ctx ));
@@ -526,9 +552,8 @@ otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data(
526552 input -> data , output_bytes_written ,
527553 output -> data ));
528554
529- // Save the context and clear the key if needed .
555+ // Save the context.
530556 HARDENED_TRY (gcm_context_save (& internal_ctx , ctx ));
531- HARDENED_TRY (clear_key_if_sideloaded (internal_ctx .key ));
532557
533558 // Verify the input buffers
534559 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (input ));
@@ -559,9 +584,16 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final(
559584 // Randomize the tag before the operation.
560585 HARDENED_TRY (hardened_memshred (auth_tag -> data , auth_tag -> len ));
561586
587+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
588+ kHardenedBoolFalse ;
589+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
590+
562591 // Restore the AES-GCM context object and load the key if needed.
563592 aes_gcm_context_t internal_ctx ;
564593 HARDENED_TRY (gcm_context_restore (ctx , & internal_ctx ));
594+ if (launder32 (internal_ctx .key .sideload ) == kHardenedBoolTrue ) {
595+ is_sideloaded = kHardenedBoolTrue ;
596+ }
565597 HARDENED_TRY (load_key_if_sideloaded (internal_ctx .key ));
566598 // Remask the key if it is not sideloaded.
567599 HARDENED_TRY (gcm_remask_key (& internal_ctx ));
@@ -578,9 +610,8 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final(
578610 auth_tag -> data , ciphertext_bytes_written ,
579611 ciphertext -> data ));
580612
581- // Clear the context and the key if needed .
613+ // Clear the context.
582614 HARDENED_TRY (hardened_memshred (ctx -> data , ARRAYSIZE (ctx -> data )));
583- HARDENED_TRY (clear_key_if_sideloaded (internal_ctx .key ));
584615
585616 // Verify the input buffers
586617 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (ciphertext ));
@@ -609,9 +640,16 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final(
609640 // Check the tag length.
610641 HARDENED_TRY (aes_gcm_check_tag_length (auth_tag -> len , tag_len ));
611642
643+ hardened_bool_t is_sideloaded __attribute__((cleanup (sideload_wipe_guard ))) =
644+ kHardenedBoolFalse ;
645+ uint32_t hw_cleanup_guard __attribute__((cleanup (aes_wipe_guard ))) = 1 ;
646+
612647 // Restore the AES-GCM context object and load the key if needed.
613648 aes_gcm_context_t internal_ctx ;
614649 HARDENED_TRY (gcm_context_restore (ctx , & internal_ctx ));
650+ if (launder32 (internal_ctx .key .sideload ) == kHardenedBoolTrue ) {
651+ is_sideloaded = kHardenedBoolTrue ;
652+ }
615653 HARDENED_TRY (load_key_if_sideloaded (internal_ctx .key ));
616654 // Remask the key if it is not sideloaded.
617655 HARDENED_TRY (gcm_remask_key (& internal_ctx ));
@@ -628,9 +666,8 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final(
628666 auth_tag -> data , plaintext_bytes_written ,
629667 plaintext -> data , success ));
630668
631- // Clear the context and the key if needed .
669+ // Clear the context.
632670 HARDENED_TRY (hardened_memshred (ctx -> data , ARRAYSIZE (ctx -> data )));
633- HARDENED_TRY (clear_key_if_sideloaded (internal_ctx .key ));
634671
635672 // Verify the input buffers
636673 HARDENED_CHECK_EQ (kHardenedBoolTrue , OTCRYPTO_CHECK_BUF (auth_tag ));
0 commit comments