aboutsummaryrefslogtreecommitdiff
path: root/lib/fih
diff options
context:
space:
mode:
authorDavid Hu <david.hu@arm.com>2021-02-16 12:26:03 +0800
committerDavid Hu <david.hu@arm.com>2021-03-19 15:08:49 +0800
commit616eaa3733c181f22c081210d3c38c2c2984fca6 (patch)
tree4c5bb3dbcaa178233282b5fc4b63a0310154a323 /lib/fih
parent2e868cb2015128fccd46e7896131146f088f3d8f (diff)
downloadtrusted-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.h62
-rw-r--r--lib/fih/src/fih.c6
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);