diff options
author | David Hu <david.hu@arm.com> | 2021-02-16 12:26:03 +0800 |
---|---|---|
committer | David Hu <david.hu@arm.com> | 2021-03-19 15:08:49 +0800 |
commit | 616eaa3733c181f22c081210d3c38c2c2984fca6 (patch) | |
tree | 4c5bb3dbcaa178233282b5fc4b63a0310154a323 /lib/fih | |
parent | 2e868cb2015128fccd46e7896131146f088f3d8f (diff) | |
download | trusted-firmware-m-616eaa3733c181f22c081210d3c38c2c2984fca6.tar.gz |
FIH: Extend control flow integrity protection
Current CFI implementation ensures that functions called by FIH_CALL
macro cannot be skipped unnoticeable. But still sections within a
function could be skipped and these skips are not caught by CFI.
This patch extends the CFI functionality to make possible to apply more
granular checks within a function. Add a set of macros to track the
internal critical steps inside a function. Functions can call these
macros to protect critical steps from physical attacks.
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
Co-authorized-by: David Hu <david.hu@arm.com>
Change-Id: I3b3a3d3ade69063ed29bda067ea2f5a270df1def
Diffstat (limited to 'lib/fih')
-rw-r--r-- | lib/fih/inc/fih.h | 62 | ||||
-rw-r--r-- | lib/fih/src/fih.c | 6 |
2 files changed, 58 insertions, 10 deletions
diff --git a/lib/fih/inc/fih.h b/lib/fih/inc/fih.h index 5fd7b70a42..0f0684a033 100644 --- a/lib/fih/inc/fih.h +++ b/lib/fih/inc/fih.h @@ -334,13 +334,18 @@ fih_int fih_int_encode_zero_equality(int32_t x) } } +#ifdef FIH_ENABLE_CFI +/* Global Control Flow Integrity counter */ +extern fih_int _fih_cfi_ctr; + /* - * Increment the CFI counter by one, and return the value before the increment. + * Increment the CFI counter by input counter and return the value before the + * increment. * * NOTE * This function shall not be called directly. */ -fih_int fih_cfi_get_and_increment(void); +fih_int fih_cfi_get_and_increment(uint8_t cnt); /* * Validate that the saved precall value is the same as the value of the global @@ -361,10 +366,6 @@ void fih_cfi_validate(fih_int saved); */ void fih_cfi_decrement(void); -#ifdef FIH_ENABLE_CFI -/* Global Control Flow Integrity counter */ -extern fih_int _fih_cfi_ctr; - /* * Macro wrappers for functions - Even when the functions have zero body this * saves a few bytes on noop functions as it doesn't generate the call/ret @@ -376,17 +377,60 @@ extern fih_int _fih_cfi_ctr; * called. */ #define FIH_CFI_PRECALL_BLOCK \ - fih_int _fih_cfi_precall_saved_value = fih_cfi_get_and_increment() + fih_int _fih_cfi_precall_saved_value = fih_cfi_get_and_increment(1) #define FIH_CFI_POSTCALL_BLOCK \ fih_cfi_validate(_fih_cfi_precall_saved_value) #define FIH_CFI_PRERET \ fih_cfi_decrement() + +/* + * Marcos to support protect the control flow integrity inside a function. + * + * The FIH_CFI_PRECALL_BLOCK/FIH_CFI_POSTCALL_BLOCK pair mainly protect function + * calls from fault injection. Fault injection may attack a function to skip its + * critical steps which are not function calls. It is difficult for the caller + * to dectect the injection as long as the function successfully returns. + * + * The following macros can be called in a function to track the critical steps, + * especially those which are not function calls. + */ +/* + * FIH_CFI_STEP_INIT() saves the CFI counter and increase the CFI counter by the + * number of the critical steps. It should be called before execution starts. + */ +#define FIH_CFI_STEP_INIT(x) \ + fih_int _fih_cfi_step_saved_value = fih_cfi_get_and_increment(x) + +/* + * FIH_CFI_STEP_DECREMENT() decrease the CFI counter by one. It can be called + * after each critical step execution completes. + */ +#define FIH_CFI_STEP_DECREMENT() \ + fih_cfi_decrement() + +/* + * FIH_CFI_STEP_ERR_RESET() resets the CFI counter to the previous value saved + * by FIH_CFI_STEP_INIT(). It shall be called only when a functionality error + * occurs and forces the function to exit. It can enable the caller to capture + * the functionality error other than being trapped in fault injection error + * handling. + */ +#define FIH_CFI_STEP_ERR_RESET() \ + do { \ + _fih_cfi_ctr = _fih_cfi_step_saved_value; \ + fih_int_validate(_fih_cfi_ctr); \ + } while(0) + #else /* FIH_ENABLE_CFI */ #define FIH_CFI_PRECALL_BLOCK #define FIH_CFI_POSTCALL_BLOCK #define FIH_CFI_PRERET + +#define FIH_CFI_STEP_INIT(x) +#define FIH_CFI_STEP_DECREMENT() +#define FIH_CFI_STEP_ERR_RESET() #endif /* FIH_ENABLE_CFI */ /* @@ -465,6 +509,10 @@ typedef int32_t fih_int; return ret; \ } while (0) +#define FIH_CFI_STEP_INIT(x) +#define FIH_CFI_STEP_DECREMENT() +#define FIH_CFI_STEP_ERR_RESET() + #endif /* TFM_FIH_PROFILE_ON */ #ifdef __cplusplus diff --git a/lib/fih/src/fih.c b/lib/fih/src/fih.c index 780715efe4..915bc53ed6 100644 --- a/lib/fih/src/fih.c +++ b/lib/fih/src/fih.c @@ -17,7 +17,7 @@ fih_int FIH_FAILURE = FIH_INT_INIT(FIH_NEGATIVE_VALUE); #ifdef FIH_ENABLE_CFI fih_int _fih_cfi_ctr = FIH_INT_INIT(0); -fih_int fih_cfi_get_and_increment(void) +fih_int fih_cfi_get_and_increment(uint8_t cnt) { fih_int saved_ctr = _fih_cfi_ctr; @@ -26,11 +26,11 @@ fih_int fih_cfi_get_and_increment(void) } /* Overflow */ - if (fih_int_decode(_fih_cfi_ctr) > (fih_int_decode(_fih_cfi_ctr) + 1)) { + if (fih_int_decode(_fih_cfi_ctr) > (fih_int_decode(_fih_cfi_ctr) + cnt)) { FIH_PANIC; } - _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) + 1); + _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) + cnt); fih_int_validate(_fih_cfi_ctr); fih_int_validate(saved_ctr); |