Skip to content

[crypto] Disable the iCache when entering CL #27678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions sw/device/lib/crypto/drivers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ dual_cc_library(
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//hw/top:rv_core_ibex_c_regs",
"//sw/device/lib/base:abs_mmio",
"//sw/device/lib/base:csr",
],
shared = [
"//sw/device/lib/base:hardened",
"//sw/device/lib/crypto/impl:status",
],
),
)
Expand Down
34 changes: 34 additions & 0 deletions sw/device/lib/crypto/drivers/rv_core_ibex.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@

#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/csr.h"
#include "sw/device/lib/base/hardened.h"
#include "sw/device/lib/crypto/impl/status.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "rv_core_ibex_regs.h"

enum {
kBaseAddr = TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR,
/**
* CSR_REG_CPUCTRL[0] is the iCache configuration field.
*/
kCpuctrlICacheMask = 1,
};

/**
Expand All @@ -27,6 +34,33 @@ static void wait_rnd_valid(void) {
}
}

hardened_bool_t ibex_disable_icache(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense. Requires the caller to create a var and handle the state in each function but avoids global var and state

// Check if the instruction cache is already disabled.
uint32_t csr;
CSR_READ(CSR_REG_CPUCTRL, &csr);
hardened_bool_t icache_enabled = kHardenedBoolFalse;
if ((csr & kCpuctrlICacheMask) == 1) {
icache_enabled = kHardenedBoolTrue;
}

// If the instruction cache is enabled, disable it.
if (launder32(icache_enabled) == kHardenedBoolTrue) {
CSR_CLEAR_BITS(CSR_REG_CPUCTRL, kCpuctrlICacheMask);
} else {
HARDENED_CHECK_EQ(icache_enabled, kHardenedBoolFalse);
}

return icache_enabled;
}

void ibex_restore_icache(hardened_bool_t icache_enabled) {
// If the instruction cache was enabled before the CL disabled it, enable it
// again.
if (icache_enabled == kHardenedBoolTrue) {
CSR_SET_BITS(CSR_REG_CPUCTRL, kCpuctrlICacheMask);
}
}

uint32_t ibex_rnd32_read(void) {
wait_rnd_valid();
return abs_mmio_read32(kBaseAddr + RV_CORE_IBEX_RND_DATA_REG_OFFSET);
Expand Down
20 changes: 20 additions & 0 deletions sw/device/lib/crypto/drivers/rv_core_ibex.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@
#include <stddef.h>
#include <stdint.h>

#include "sw/device/lib/base/hardened.h"

/**
* Disable the Ibex Instruction Cache if it is enabled.
*
* Reads out the current state of the instruction cache. If it is enabled,
* disable it for the crypto lib.
*
* @return kHardenedBoolTrue if the iCache was enabled before we disabled it.
*/
hardened_bool_t ibex_disable_icache(void);

/**
* Enables the Ibex Instruction Cache if icache_enabled is set.
*
* If icache_enabled == kHardenedBoolTrue, this function enables the iCache by
* writing to CPUCTRL.
*/
void ibex_restore_icache(hardened_bool_t icache_enabled);

/**
* Get random data from the EDN0 interface.
*
Expand Down
56 changes: 56 additions & 0 deletions sw/device/lib/crypto/impl/aes_gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(otcrypto_blinded_key_t *key,
// Check the tag length.
HARDENED_TRY(aes_gcm_check_tag_length(auth_tag.len, tag_len));

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Construct the AES key.
aes_key_t aes_key;
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
Expand All @@ -280,6 +283,10 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt(otcrypto_blinded_key_t *key,
auth_tag.data, ciphertext.data));

HARDENED_TRY(clear_key_if_sideloaded(aes_key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -305,6 +312,9 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt(
// Ensure entropy complex is initialized.
HARDENED_TRY(entropy_complex_check());

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Construct the AES key.
aes_key_t aes_key;
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
Expand All @@ -325,6 +335,10 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt(
auth_tag.data, plaintext.data, success));

HARDENED_TRY(clear_key_if_sideloaded(aes_key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -338,6 +352,9 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_init(
// Ensure entropy complex is initialized.
HARDENED_TRY(entropy_complex_check());

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Construct the AES key.
aes_key_t aes_key;
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
Expand All @@ -350,6 +367,10 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_init(
// Save the context and clear the key if needed.
gcm_context_save(&internal_ctx, ctx);
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -363,6 +384,9 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_init(
// Ensure entropy complex is initialized.
HARDENED_TRY(entropy_complex_check());

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Construct the AES key.
aes_key_t aes_key;
HARDENED_TRY(aes_gcm_key_construct(key, &aes_key));
Expand All @@ -375,6 +399,10 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_init(
// Save the context and clear the key if needed.
gcm_context_save(&internal_ctx, ctx);
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -392,6 +420,9 @@ otcrypto_status_t otcrypto_aes_gcm_update_aad(otcrypto_aes_gcm_context_t *ctx,
return OTCRYPTO_OK;
}

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Restore the AES-GCM context object and load the key if needed.
aes_gcm_context_t internal_ctx;
gcm_context_restore(ctx, &internal_ctx);
Expand All @@ -403,6 +434,10 @@ otcrypto_status_t otcrypto_aes_gcm_update_aad(otcrypto_aes_gcm_context_t *ctx,
// Save the context and clear the key if needed.
gcm_context_save(&internal_ctx, ctx);
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -423,6 +458,9 @@ otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data(
return OTCRYPTO_OK;
}

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Restore the AES-GCM context object and load the key if needed.
aes_gcm_context_t internal_ctx;
gcm_context_restore(ctx, &internal_ctx);
Expand All @@ -448,6 +486,10 @@ otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data(
// Save the context and clear the key if needed.
gcm_context_save(&internal_ctx, ctx);
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -467,6 +509,9 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final(
// Ensure entropy complex is initialized.
HARDENED_TRY(entropy_complex_check());

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Check the tag length.
HARDENED_TRY(aes_gcm_check_tag_length(auth_tag.len, tag_len));

Expand All @@ -490,6 +535,10 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final(
// Clear the context and the key if needed.
hardened_memshred(ctx->data, ARRAYSIZE(ctx->data));
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}

Expand All @@ -510,6 +559,9 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final(
// Entropy complex needs to be initialized for `memshred`.
HARDENED_TRY(entropy_complex_check());

// Store the iCache state (on or off) and disable it when it is on.
hardened_bool_t icache_saved_state = ibex_disable_icache();

// Check the tag length.
HARDENED_TRY(aes_gcm_check_tag_length(auth_tag.len, tag_len));

Expand All @@ -533,5 +585,9 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final(
// Clear the context and the key if needed.
hardened_memshred(ctx->data, ARRAYSIZE(ctx->data));
HARDENED_TRY(clear_key_if_sideloaded(internal_ctx.key));

// Enable the iCache if it was previously enabled.
ibex_restore_icache(icache_saved_state);

return OTCRYPTO_OK;
}
Loading