Skip to content

Commit 875bce7

Browse files
siemen11nasahlpa
authored andcommitted
[crypto/gcm] Remove icache disable
The GCM was disabling icache during its operations due to GCM not being constant time with this feature enabled. However, the cryptolib can not write to such registers during API calls, hence the feature has to be removed. The otcrypto_init function at high security level now enables data independent timing to secure GCM for SCA (we leave icache as perference for the user). We create an interface to the ibex_disable_icache and ibex_restore_icache drivers functions for the user. Upon testing the aes_gcm_timing_functest, the timing issues come from the use of memshred, i.e., drawing randomness which stalls, and also from otcrypto_eval_exit which reads from the alert manager which crosses clock domains. The gcm is constant time when the icache is disabled and the reading of the alert registers is manually removed. We keep the test as broken (as we would need to mock out the reading of the alert registers). However, the test is slightly adapted to use the new ibex_disable_icache function. Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent 310a5c2 commit 875bce7

6 files changed

Lines changed: 44 additions & 63 deletions

File tree

sw/device/lib/crypto/impl/aes_gcm.c

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(otcrypto_blinded_key_t *key,
312312
// Check the tag length.
313313
HARDENED_TRY(aes_gcm_check_tag_length(auth_tag->len, tag_len));
314314

315-
// Store the iCache state (on or off) and disable it when it is on.
316-
hardened_bool_t icache_saved_state;
317-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
318-
319315
// Construct the AES key.
320316
aes_key_t aes_key;
321317
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
@@ -328,9 +324,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(otcrypto_blinded_key_t *key,
328324

329325
HARDENED_TRY(clear_key_if_sideloaded(aes_key));
330326

331-
// Enable the iCache if it was previously enabled.
332-
ibex_restore_icache(icache_saved_state);
333-
334327
// Verify the input buffers
335328
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(plaintext));
336329
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(iv));
@@ -360,10 +353,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt(
360353
return OTCRYPTO_BAD_ARGS;
361354
}
362355

363-
// Store the iCache state (on or off) and disable it when it is on.
364-
hardened_bool_t icache_saved_state;
365-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
366-
367356
// Construct the AES key.
368357
aes_key_t aes_key;
369358
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
@@ -385,9 +374,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt(
385374

386375
HARDENED_TRY(clear_key_if_sideloaded(aes_key));
387376

388-
// Enable the iCache if it was previously enabled.
389-
ibex_restore_icache(icache_saved_state);
390-
391377
// Verify the input buffers
392378
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(plaintext));
393379
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(iv));
@@ -405,10 +391,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_init(
405391
return OTCRYPTO_BAD_ARGS;
406392
}
407393

408-
// Store the iCache state (on or off) and disable it when it is on.
409-
hardened_bool_t icache_saved_state;
410-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
411-
412394
// Construct the AES key.
413395
aes_key_t aes_key;
414396
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
@@ -423,9 +405,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_init(
423405
HARDENED_TRY(gcm_context_save(&internal_ctx, ctx));
424406
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));
425407

426-
// Enable the iCache if it was previously enabled.
427-
ibex_restore_icache(icache_saved_state);
428-
429408
// Verify the input buffer
430409
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(iv));
431410

@@ -439,10 +418,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_init(
439418
return OTCRYPTO_BAD_ARGS;
440419
}
441420

442-
// Store the iCache state (on or off) and disable it when it is on.
443-
hardened_bool_t icache_saved_state;
444-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
445-
446421
// Construct the AES key.
447422
aes_key_t aes_key;
448423
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
@@ -457,9 +432,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_init(
457432
HARDENED_TRY(gcm_context_save(&internal_ctx, ctx));
458433
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));
459434

460-
// Enable the iCache if it was previously enabled.
461-
ibex_restore_icache(icache_saved_state);
462-
463435
// Verify the input buffer
464436
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(iv));
465437

@@ -477,10 +449,6 @@ otcrypto_status_t otcrypto_aes_gcm_update_aad(otcrypto_aes_gcm_context_t *ctx,
477449
return OTCRYPTO_OK;
478450
}
479451

480-
// Store the iCache state (on or off) and disable it when it is on.
481-
hardened_bool_t icache_saved_state;
482-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
483-
484452
// Restore the AES-GCM context object and load the key if needed.
485453
aes_gcm_context_t internal_ctx;
486454
HARDENED_TRY(gcm_context_restore(ctx, &internal_ctx));
@@ -493,9 +461,6 @@ otcrypto_status_t otcrypto_aes_gcm_update_aad(otcrypto_aes_gcm_context_t *ctx,
493461
HARDENED_TRY(gcm_context_save(&internal_ctx, ctx));
494462
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));
495463

496-
// Enable the iCache if it was previously enabled.
497-
ibex_restore_icache(icache_saved_state);
498-
499464
// Verify the input buffer
500465
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(aad));
501466

@@ -516,10 +481,6 @@ otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data(
516481
return OTCRYPTO_OK;
517482
}
518483

519-
// Store the iCache state (on or off) and disable it when it is on.
520-
hardened_bool_t icache_saved_state;
521-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
522-
523484
// Restore the AES-GCM context object and load the key if needed.
524485
aes_gcm_context_t internal_ctx;
525486
HARDENED_TRY(gcm_context_restore(ctx, &internal_ctx));
@@ -549,9 +510,6 @@ otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data(
549510
HARDENED_TRY(gcm_context_save(&internal_ctx, ctx));
550511
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));
551512

552-
// Enable the iCache if it was previously enabled.
553-
ibex_restore_icache(icache_saved_state);
554-
555513
// Verify the input buffers
556514
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(input));
557515
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(output));
@@ -575,10 +533,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final(
575533
// Randomize the tag before the operation.
576534
HARDENED_TRY(hardened_memshred(auth_tag->data, auth_tag->len));
577535

578-
// Store the iCache state (on or off) and disable it when it is on.
579-
hardened_bool_t icache_saved_state;
580-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
581-
582536
// Check the tag length.
583537
HARDENED_TRY(aes_gcm_check_tag_length(auth_tag->len, tag_len));
584538

@@ -605,9 +559,6 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final(
605559
HARDENED_TRY(hardened_memshred(ctx->data, ARRAYSIZE(ctx->data)));
606560
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));
607561

608-
// Enable the iCache if it was previously enabled.
609-
ibex_restore_icache(icache_saved_state);
610-
611562
// Verify the input buffers
612563
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(ciphertext));
613564
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(auth_tag));
@@ -629,10 +580,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final(
629580
*plaintext_bytes_written = 0;
630581
*success = kHardenedBoolFalse;
631582

632-
// Store the iCache state (on or off) and disable it when it is on.
633-
hardened_bool_t icache_saved_state;
634-
HARDENED_TRY(ibex_disable_icache(&icache_saved_state));
635-
636583
// Check the tag length.
637584
HARDENED_TRY(aes_gcm_check_tag_length(auth_tag->len, tag_len));
638585

@@ -659,9 +606,6 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final(
659606
HARDENED_TRY(hardened_memshred(ctx->data, ARRAYSIZE(ctx->data)));
660607
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));
661608

662-
// Enable the iCache if it was previously enabled.
663-
ibex_restore_icache(icache_saved_state);
664-
665609
// Verify the input buffers
666610
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(auth_tag));
667611
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(plaintext));

sw/device/lib/crypto/impl/config.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ otcrypto_status_t otcrypto_set_security_config(
5858
return OTCRYPTO_OK;
5959
}
6060

61+
otcrypto_status_t otcrypto_disable_icache(hardened_bool_t *icache_enabled) {
62+
HARDENED_TRY(ibex_disable_icache(icache_enabled));
63+
return OTCRYPTO_OK;
64+
}
65+
66+
otcrypto_status_t otcrypto_restore_icache(hardened_bool_t icache_enabled) {
67+
ibex_restore_icache(icache_enabled);
68+
return OTCRYPTO_OK;
69+
}
70+
6171
otcrypto_status_t otcrypto_init(otcrypto_key_security_level_t security_level) {
6272
HARDENED_TRY(otcrypto_set_security_config(security_level));
6373

sw/device/lib/crypto/include/config.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ otcrypto_status_t otcrypto_security_config_check(
3434
* and the data independent timing. On low security level, leaves the chip as it
3535
* is.
3636
*
37-
* This function writes to Ibex registers.
37+
* This function writes to Ibex registers. Hence, it is only usable in M mode.
3838
*
3939
* @param security_level Security level of the used key.
4040
* @returns OK when the configuration is correctly set.
@@ -43,6 +43,33 @@ OT_WARN_UNUSED_RESULT
4343
otcrypto_status_t otcrypto_set_security_config(
4444
otcrypto_key_security_level_t security_level);
4545

46+
/**
47+
* Disable the Ibex Instruction Cache if it is enabled.
48+
*
49+
* Reads out the current state of the instruction cache. If it is enabled,
50+
* disable it for the crypto lib.
51+
* It is only usable in M mode.
52+
*
53+
* @param[out] icache_enabled kHardenedBoolTrue if the iCache was enabled before
54+
* we disabled it.
55+
* @return Error status.
56+
*/
57+
OT_WARN_UNUSED_RESULT
58+
otcrypto_status_t otcrypto_disable_icache(hardened_bool_t *icache_enabled);
59+
60+
/**
61+
* Enables the Ibex Instruction Cache if icache_enabled is set.
62+
*
63+
* If icache_enabled == kHardenedBoolTrue, this function enables the iCache by
64+
* writing to CPUCTRL.
65+
* It is only usable in M mode.
66+
*
67+
* @param icache_enabled kHardenedBoolTrue to enable the iCache.
68+
* @return Error status.
69+
*/
70+
OT_WARN_UNUSED_RESULT
71+
otcrypto_status_t otcrypto_restore_icache(hardened_bool_t icache_enabled);
72+
4673
/**
4774
* Initializes the crypto library for use.
4875
*
@@ -52,6 +79,7 @@ otcrypto_status_t otcrypto_set_security_config(
5279
* Set up the entropy source
5380
*
5481
* This function writes to alert manager and Ibex registers.
82+
* It is only usable in M mode.
5583
*
5684
* @param security_level Security level of the used key.
5785
* @returns OK when the security check passed.

sw/device/tests/crypto/BUILD

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,11 @@ opentitan_test(
219219
exec_env = CRYPTOTEST_EXEC_ENVS,
220220
fpga = fpga_params(
221221
timeout = "long",
222-
tags = ["broken"], # https://github.com/lowRISC/opentitan/issues/15788
223-
# [test-triage] test not constant time with icache enabled
222+
tags = ["broken"],
224223
),
225224
verilator = verilator_params(
226225
timeout = "long",
227-
tags = ["broken"], # https://github.com/lowRISC/opentitan/issues/15788
228-
# [test-triage] test not constant time with icache enabled
226+
tags = ["broken"],
229227
),
230228
deps = [
231229
":aes_gcm_testutils",

sw/device/tests/crypto/aes_gcm_testutils.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,11 @@ status_t aes_gcm_testutils_decrypt(const aes_gcm_test_t *test,
278278
*cycles = profile_end(t_start);
279279
} else {
280280
// Call decrypt() with a cycle count timing profile.
281-
icache_invalidate();
282281
uint64_t t_start = profile_start();
283282
otcrypto_status_t err =
284283
otcrypto_aes_gcm_decrypt(&key, &ciphertext, &iv, &aad, tag_len, &tag,
285284
&actual_plaintext, tag_valid);
286285
*cycles = profile_end(t_start);
287-
icache_invalidate();
288286

289287
// Check for errors.
290288
TRY(err);

sw/device/tests/crypto/aes_gcm_timing_functest.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// SPDX-License-Identifier: Apache-2.0
44

55
#include "sw/device/lib/base/macros.h"
6+
#include "sw/device/lib/crypto/drivers/rv_core_ibex.h"
67
#include "sw/device/lib/crypto/impl/aes_gcm/aes_gcm.h"
78
#include "sw/device/lib/crypto/include/config.h"
89
#include "sw/device/lib/crypto/include/entropy_src.h"
@@ -77,6 +78,8 @@ OTTF_DEFINE_TEST_CONFIG();
7778
bool test_main(void) {
7879
status_t result;
7980
CHECK_STATUS_OK(otcrypto_init(kOtcryptoKeySecurityLevelHigh));
81+
hardened_bool_t icache_enabled;
82+
CHECK_STATUS_OK(otcrypto_disable_icache(&icache_enabled));
8083
for (size_t i = 0; i < ARRAYSIZE(kAesGcmTestvectors); i++) {
8184
current_test = &kAesGcmTestvectors[i];
8285
LOG_INFO("Key length = %d", current_test->key_len * sizeof(uint32_t));

0 commit comments

Comments
 (0)