/*--------------------------------------------------------------------------*/ /* Copyright 2020-2021 NXP */ /* */ /* NXP Confidential. This software is owned or controlled by NXP and may */ /* only be used strictly in accordance with the applicable license terms. */ /* By expressly accepting such terms or by downloading, installing, */ /* activating and/or otherwise using the software, you are agreeing that */ /* you have read, and that you agree to comply with and are bound by, such */ /* license terms. If you do not agree to be bound by the applicable license */ /* terms, then you may not retain, install, activate or otherwise use the */ /* software. */ /*--------------------------------------------------------------------------*/ /** * @file mcuxCsslFlowProtection.h * @brief Provides the API for the CSSL flow protection mechanism. */ #ifndef MCUX_CSSL_FLOW_PROTECTION_H_ #define MCUX_CSSL_FLOW_PROTECTION_H_ /* Include the actual implementation of the flow protection mechanism. */ #include /** * @addtogroup mcuxCsslAPI MCUX CSSL -- API * * @defgroup mcuxCsslFlowProtection Flow Protection API * @brief Flow protection mechanism. * @ingroup mcuxCsslAPI */ /** * @defgroup csslFpCore Flow protection core functionality * @brief Flow protection handling core functionality. * @ingroup mcuxCsslFlowProtection * * @todo Extend this description of the core functionality which relies * basically on the function calling flow protection. * * @declaration{MCUX_CSSL_FP_FUNCTION_DECL} * @event{MCUX_CSSL_FP_FUNCTION_CALL} * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED} */ /** * @defgroup csslFpFunction Function calling flow protection * @brief Support for flow protected functions. * @ingroup mcuxCsslFlowProtection * * @declaration{MCUX_CSSL_FP_FUNCTION_DECL} * @event{MCUX_CSSL_FP_FUNCTION_CALL} * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED} */ /** * @def MCUX_CSSL_FP_PROTECTED_TYPE * @brief Based on a given base type, builds a return type with flow * protection. * @ingroup csslFpFunction * * This macro must be used to wrap the function return type. For example: * @code * MCUX_CSSL_FP_FUNCTION_DECL(someFunction) * MCUX_CSSL_FP_PROTECTED_TYPE(uint32_t) someFunction(void); * @endcode * * Note that depending on the selected flow protection mechanism, the width of * the result type may be limited to 32 bits or less to allow encoding a * protection token in the other half of a 64-bit return value. * * @see MCUX_CSSL_FP_FUNCTION_DEF * * @param resultType The type to be converted into a protected type. */ #define MCUX_CSSL_FP_PROTECTED_TYPE(resultType) \ MCUX_CSSL_FP_PROTECTED_TYPE_IMPL(resultType) /** * @def MCUX_CSSL_FP_COUNTER_STMT * @brief A statement which is only evaluated if a secure counter is used. * @api * @ingroup csslFpFunction * * This macro can be used to create counting variables that are only present if * the active configuration uses a secure counter, to avoid warnings about * unused variables. * * @param statement The statement to be conditionally included. */ #define MCUX_CSSL_FP_COUNTER_STMT(statement) \ MCUX_CSSL_FP_COUNTER_STMT_IMPL(statement) /** * @def MCUX_CSSL_FP_FUNCTION_DECL * @brief Declaration of a flow protected function. * @api * @ingroup csslFpFunction * * This declaration must be placed just in front of the actual function * declaration. For example: * @code * MCUX_CSSL_FP_FUNCTION_DECL(someFunction) // Note: no semicolon here * uint32_t someFunction(void); * @endcode * * @event{MCUX_CSSL_FP_FUNCTION_CALL} * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED} * * @see MCUX_CSSL_FP_FUNCTION_DEF * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * * @param id Identifier for the function that is flow protected. */ #define MCUX_CSSL_FP_FUNCTION_DECL(id) \ MCUX_CSSL_FP_FUNCTION_DECL_IMPL(id) /** * @def MCUX_CSSL_FP_FUNCTION_DEF * @brief Definition of a flow protected function. * @api * @ingroup csslFpFunction * * This definition macro must be placed just in front of the actual function * definition, that has been previously declared as flow protected using * #MCUX_CSSL_FP_FUNCTION_DECL. For example: * @code * // someHeader.h * MCUX_CSSL_FP_FUNCTION_DECL(someFunction) // Note: no semicolon here * uint32_t someFunction(void); * * // someFile.c * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * // some function body * } * @endcode * * @see MCUX_CSSL_FP_FUNCTION_DECL * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * * @param id Identifier for the function that is flow protected. */ #define MCUX_CSSL_FP_FUNCTION_DEF(id) \ MCUX_CSSL_FP_FUNCTION_DEF_IMPL(id) /** * @def MCUX_CSSL_FP_FUNCTION_ENTRY * @brief Flow protection handler for the function entry point. * @api * @ingroup csslFpFunction * * This entry macro should be placed at the start of the function body that * needs to be protected. The function must have been declared before as flow * protected using #MCUX_CSSL_FP_FUNCTION_DECL. For example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // remainder of the function body * } * @endcode * * The only statements that should be placed before this one, are declarations * for flow protected operations that are already used as expectations in this * macro. For example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(uint32_t count) * { * MCUX_CSSL_FP_LOOP_DECL(someLoop); * MCUX_CSSL_FP_LOOP_DECL(otherLoop); * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction, * MCUX_CSSL_FP_LOOP_ITERATIONS(someLoop, count), * MCUX_CSSL_FP_LOOP_ITERATIONS(otherLoop, 2u * count) * ); * // Remainder of the function body, where someLoop makes count iterations, * // and otherLoop 2*count iterations. * } * @endcode * * @see MCUX_CSSL_FP_FUNCTION_DECL * @see MCUX_CSSL_FP_FUNCTION_DEF * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the function that has just been entered.
* - expect: Zero or more (comma separated) declarations of expected code * flow behavior. */ #define MCUX_CSSL_FP_FUNCTION_ENTRY(...) \ MCUX_CSSL_FP_FUNCTION_ENTRY_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_EXIT * @brief Flow protection handler for the function exit point. * @api * @ingroup csslFpFunction * * This exit macro must replace the regular \c return statements of a protected * function. Given the following unprotected example: * @code * uint32_t someFunction(void) * { * // some function body * return 0; * } * @endcode * The protected version would become: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // remainder of the function body * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0); * } * @endcode * * @see MCUX_CSSL_FP_FUNCTION_DECL * @see MCUX_CSSL_FP_FUNCTION_DEF * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the function from which we will exit. * - result: Result that should be encoded in the return value. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior. * @return A value in which both \p result and a flow protection token * are encoded. */ #define MCUX_CSSL_FP_FUNCTION_EXIT(...) \ MCUX_CSSL_FP_FUNCTION_EXIT_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @brief Flow protection handler for the function exit point which includes * an actual check of the code flow. * @api * @ingroup csslFpFunction * * This exit macro must replace the regular \c return statements of a protected * function. In addition to #MCUX_CSSL_FP_FUNCTION_EXIT it also checks the flow * protection, and selects the return value accordingly. For example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // remainder of the function body * MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK(someFunction, 0, 0xFAu); * } * @endcode * * @see MCUX_CSSL_FP_FUNCTION_DECL * @see MCUX_CSSL_FP_FUNCTION_DEF * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the function from which we will exit. * - pass: Result that should be encoded in the return value if the flow * protection check passed. * - fail: Result that should be encoded in the return value if the flow * protection check failed. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior. * @return A value in which both the result (either \p pass or \p fail) * and a flow protection token are encoded. */ #define MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK(...) \ MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_EXIT_VOID * @brief Flow protection handler for the exit point of functions with the * return type \c void. * @api * @ingroup csslFpFunction * * This exit macro must replace the regular \c return statements of a protected * void function. Given the following unprotected example: * @code * void someFunction(void) * { * // some function body * return 0; * } * @endcode * The protected version would become: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * void someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // remainder of the function body * MCUX_CSSL_FP_FUNCTION_EXIT_VOID(someFunction); * } * @endcode * * @see MCUX_CSSL_FP_FUNCTION_DECL * @see MCUX_CSSL_FP_FUNCTION_DEF * @see MCUX_CSSL_FP_FUNCTION_ENTRY * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the function from which we will exit. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior. * @return A protected return value of type void. */ #define MCUX_CSSL_FP_FUNCTION_EXIT_VOID(...) \ MCUX_CSSL_FP_FUNCTION_EXIT_VOID_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_RESULT * @brief Extract the result value from a protected \p return value. * @ingroup csslFpFunction * * @param return The protected return value which contains the result. */ #define MCUX_CSSL_FP_RESULT(return) \ MCUX_CSSL_FP_RESULT_IMPL(return) /** * @def MCUX_CSSL_FP_PROTECTION_TOKEN * @brief Extract the protection token value from a protected \p return value. * @ingroup csslFpFunction * * Note that this macro is only used with a local security counter, * e.g. for configuration CSSL_SC_USE_SW_LOCAL * * @param return The protected return value which contains the protection token. */ #define MCUX_CSSL_FP_PROTECTION_TOKEN(return) \ MCUX_CSSL_FP_PROTECTION_TOKEN_IMPL(return) /** * @def MCUX_CSSL_FP_FUNCTION_CALL * @brief Call a flow protected function. * @api * @ingroup csslFpFunction * * This function call macro encapsulates the flow protection handling needed * for calling a function. In particular it takes care of extracting the flow * protection token from the return value (which has been inserted by * #MCUX_CSSL_FP_FUNCTION_EXIT or #MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK) and * incorporating that in the flow protection of the current function. For * example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // ... * MCUX_CSSL_FP_FUNCTION_CALL(result, otherFunction()); * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) * ); * } * @endcode * * For functions returning void, the macro #MCUX_CSSL_FP_FUNCTION_CALL_VOID * exists. * * @declaration{MCUX_CSSL_FP_FUNCTION_DECL} * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED} * * @param ... The following parameters need to be passed (comma separated): * - result: Fresh variable name to store the result of \p call. * - call: The (protected) function call that must be performed. */ #define MCUX_CSSL_FP_FUNCTION_CALL(...) \ MCUX_CSSL_FP_FUNCTION_CALL_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_CALL_VOID * @brief Call a flow protected void function. * @api * @ingroup csslFpFunction * * This function call macro encapsulates the flow protection handling needed * for calling a void function. In particular it takes care of extracting the * flow protection token from the return value (which has been inserted by * #MCUX_CSSL_FP_FUNCTION_EXIT or #MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK) and * incorporating that in the flow protection of the current function. For * example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // ... * MCUX_CSSL_FP_FUNCTION_CALL_VOID(otherFunction()); * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) * ); * } * @endcode * * @declaration{MCUX_CSSL_FP_FUNCTION_DECL} * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED} * * @param ... The following parameters need to be passed (comma separated): * - call: The (protected) void function call that must be performed. */ #define MCUX_CSSL_FP_FUNCTION_CALL_VOID(...) \ MCUX_CSSL_FP_FUNCTION_CALL_VOID_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED * @brief Call a flow protected function from unprotected code. * @api * @ingroup csslFpFunction * * This function call macro encapsulates the flow protection handling needed * for calling a function from within a function which does not have local * flow protection, or which uses a different flow protection mechanism than * the one provided by CSSL. In particular it takes care of extracting the * protection token and result from the return value (which has been inserted * by #MCUX_CSSL_FP_FUNCTION_EXIT or #MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK). * For example: * @code * uint32_t someUnprotectedFunction(void) * { * // ... * MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED( * result, * token, * otherFunction()); * // Check the protection token * if(MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) != token) * { * return FAULT; * } * // ... The following code may use 'result' as a variable ... * } * @endcode * * @param ... The following parameters need to be passed (comma separated): * - result: Fresh variable name to store the result of \p call. * - token: Fresh variable name to store the protection token of \p call. * - call: The (protected) function call that must be performed. */ #define MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED(...) \ MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_CALL_VOID_PROTECTED * @brief Call a flow protected void function from unprotected code. * @api * @ingroup csslFpFunction * * This function call macro encapsulates the flow protection handling needed * for calling a void function from within a function which does not have flow * protection, or which uses a different flow protection mechanism than the one * provided by CSSL. In particular it takes care of extracting the protection * token and result from the return value (which has been inserted by * #MCUX_CSSL_FP_FUNCTION_EXIT or #MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK). * For example: * @code * uint32_t someUnprotectedFunction(void) * { * // ... * MCUX_CSSL_FP_FUNCTION_CALL_PROTECTED( * token, * protectedVoidFunction()); * // Check the protection token * if(MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) != token) * { * return FAULT; * } * // ... * } * @endcode * * @param ... The following parameters need to be passed (comma separated): * - token: Fresh variable name to store the protection token of \p call. * - call: The (protected) function call that must be performed. */ #define MCUX_CSSL_FP_FUNCTION_CALL_VOID_PROTECTED(...) \ MCUX_CSSL_FP_FUNCTION_CALL_VOID_PROTECTED_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_CALL_BEGIN * @brief Call a flow protected function and check the protection token. * @api * @ingroup csslFpFunction * * This function call macro encapsulates the flow protection handling needed * for calling a function from within a function which does not have local * flow protection, or which uses a different flow protection mechanism than * the one provided by CSSL. In particular it takes care of extracting the * protection token and result from the return value (which has been inserted * by #MCUX_CSSL_FP_FUNCTION_EXIT or #MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK). * For example: * @code * uint32_t someUnprotectedFunction(void) * { * // ... * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN( * result, * token, * otherFunction()); * // Check the protection token * if(MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) != token) * { * return FAULT; * } * // ... The following code may use 'result' as a variable ... * MCUX_CSSL_FP_FUNCTION_CALL_END(); * // ... result is invalid here ... * } * @endcode * * @param ... The following parameters need to be passed (comma separated): * - result: Fresh variable name to store the result of \p call. * - token: Fresh variable name to store the protection token of \p call. * - call: The (protected) function call that must be performed. */ #define MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(...) \ MCUX_CSSL_FP_FUNCTION_CALL_BEGIN_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_CALL_END * @brief End a function call section started by * #MCUX_CSSL_FP_FUNCTION_CALL_BEGIN. * @api * @ingroup csslFpFunction * * Example: * @code * uint32_t someUnprotectedFunction(void) * { * // ... * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN( * result, * token, * otherFunction()); * // Check the protection token * if(MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) != token) * { * return FAULT; * } * // ... The following code may use 'result' as a variable ... * MCUX_CSSL_FP_FUNCTION_CALL_END(); * // ... result is invalid here ... * } * @endcode * * @param ... The following parameters need to be passed (comma separated): * - result: Fresh variable name to store the result of \p call. * - token: Fresh variable name to store the protection token of \p call. * - call: The (protected) function call that must be performed. */ #define MCUX_CSSL_FP_FUNCTION_CALL_END(...) \ MCUX_CSSL_FP_FUNCTION_CALL_END_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_FUNCTION_CALLED * @brief Expectation of a called function. * @api * @ingroup csslFpFunction * * This expectation macro indicates to the flow protection mechanism that a * function call is expected to happen (if placed before the actual call), for * example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction, * MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) * ); * // ... * MCUX_CSSL_FP_FUNCTION_CALL(result, otherFunction()); * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0); * } * @endcode * Or that a function call has happened (if placed after the actual call), for * example: * @code * MCUX_CSSL_FP_FUNCTION_DEF(someFunction) // Note: no semicolon here * uint32_t someFunction(void) * { * MCUX_CSSL_FP_FUNCTION_ENTRY(someFunction); * // ... * MCUX_CSSL_FP_FUNCTION_CALL(result, otherFunction()); * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_FUNCTION_CALLED(otherFunction) * ); * } * @endcode * * @declaration{MCUX_CSSL_FP_FUNCTION_DECL} * @event{MCUX_CSSL_FP_FUNCTION_CALL} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * * @param ... The following parameters need to be passed (comma separated): * -id: Identifier of the function that is expected to be called. */ #define MCUX_CSSL_FP_FUNCTION_CALLED(...) \ MCUX_CSSL_FP_FUNCTION_CALLED_IMPL(__VA_ARGS__) /** * @defgroup csslFpLoop Looping flow protection * @brief Support for flow protected loops. * @ingroup mcuxCsslFlowProtection * * @declaration{MCUX_CSSL_FP_LOOP_DECL} * @event{MCUX_CSSL_FP_LOOP_ITERATION} * @expectation{MCUX_CSSL_FP_LOOP_ITERATIONS} */ /** * @def MCUX_CSSL_FP_LOOP_DECL * @brief Declaration of a flow protected loop. * @api * @ingroup csslFpLoop * * To inform the flow protection mechanism about a loop that needs to be * protected, a loop identifier needs to be declared. This identifier can then * be used in the event and expectation macros. For example: * @code * MCUX_CSSL_FP_LOOP_DECL(someLoopIdentifier); * for (uint32_t i = 0; i < 8; ++i) * { * MCUX_CSSL_FP_LOOP_ITERATION(someLoopIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_LOOP_ITERATIONS(someLoopIdentifier, 8) * ); * @endcode * * @event{MCUX_CSSL_FP_LOOP_ITERATION} * @expectation{MCUX_CSSL_FP_LOOP_ITERATIONS} * * @param id Identifier for the loop that is flow protected. */ #define MCUX_CSSL_FP_LOOP_DECL(id) \ MCUX_CSSL_FP_LOOP_DECL_IMPL(id) /** * @def MCUX_CSSL_FP_LOOP_ITERATION * @brief Perform a loop iteration. * @api * @ingroup csslFpLoop * * This loop iteration macro informs the flow mechanism that an iteration event * is performed for the loop declared by #MCUX_CSSL_FP_LOOP_DECL with the given * \p id. For example: * @code * MCUX_CSSL_FP_LOOP_DECL(someLoopIdentifier); * for (uint32_t i = 0; i < 8; ++i) * { * MCUX_CSSL_FP_LOOP_ITERATION(someLoopIdentifier); * } * @endcode * * @declaration{MCUX_CSSL_FP_LOOP_DECL} * @expectation{MCUX_CSSL_FP_LOOP_ITERATIONS} * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier for the loop that is flow protected. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior related to this event. */ #define MCUX_CSSL_FP_LOOP_ITERATION(...) \ MCUX_CSSL_FP_LOOP_ITERATION_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_LOOP_ITERATIONS * @brief Expected number of loop iterations. * @api * @ingroup csslFpLoop * * This expectation macro indicates to the flow protection mechanism that the * loop declared by #MCUX_CSSL_FP_LOOP_DECL with the given \p id has made * \p count iterations. For example: * @code * MCUX_CSSL_FP_LOOP_DECL(someLoopIdentifier); * for (uint32_t i = 0; i < 8; ++i) * { * MCUX_CSSL_FP_LOOP_ITERATION(someLoopIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_LOOP_ITERATIONS(someLoopIdentifier, 8) * ); * @endcode * * @declaration{MCUX_CSSL_FP_LOOP_DECL} * @event{MCUX_CSSL_FP_LOOP_ITERATION} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * * @param id Identifier of the flow protected loop. * @param count Number of expected iterations. */ #define MCUX_CSSL_FP_LOOP_ITERATIONS(id, count) \ MCUX_CSSL_FP_LOOP_ITERATIONS_IMPL(id, count) /** * @defgroup csslFpBranch Branching flow protection * @brief Support for flow protected branches. * @ingroup mcuxCsslFlowProtection * * @declaration{MCUX_CSSL_FP_BRANCH_DECL} * @event{MCUX_CSSL_FP_BRANCH_POSITIVE,MCUX_CSSL_FP_BRANCH_NEGATIVE} * @expectation{MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE,MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE} */ /** * @def MCUX_CSSL_FP_BRANCH_DECL * @brief Declaration of a flow protected branch. * @api * @ingroup csslFpBranch * * To inform the flow protection mechanism about a branch that needs to be * protected, a branch identifier needs to be declared. This identifier can * then be used in the events and expectation macros. For example: * @code * MCUX_CSSL_FP_BRANCH_DECL(someBranchIdentifier); * if (condition) * { * MCUX_CSSL_FP_BRANCH_POSITIVE(someBranchIdentifier); * } * else * { * MCUX_CSSL_FP_BRANCH_NEGATIVE(someBranchIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_BRANCH_TAKEN(someBranchIdentifier, * MCUX_CSSL_FP_BRANCH_POSITIVE_SCENARIO, condition) * ); * @endcode * * @event{MCUX_CSSL_FP_BRANCH_POSITIVE,MCUX_CSSL_FP_BRANCH_NEGATIVE} * @expectation{MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE,MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE} * * @param id Identifier for the branch that is flow protected. */ #define MCUX_CSSL_FP_BRANCH_DECL(id) \ MCUX_CSSL_FP_BRANCH_DECL_IMPL(id) /** * @def MCUX_CSSL_FP_BRANCH_POSITIVE * @brief Positive scenario for a branch is executed. * @api * @ingroup csslFpBranch * * This branch event macro informs the flow mechanism that the positive scenario * of the branch is executed for the branch declared by * #MCUX_CSSL_FP_BRANCH_DECL with the given \p id. For example: * @code * MCUX_CSSL_FP_BRANCH_DECL(someBranchIdentifier); * if (condition) * { * MCUX_CSSL_FP_BRANCH_POSITIVE(someBranchIdentifier); * } * else * { * MCUX_CSSL_FP_BRANCH_NEGATIVE(someBranchIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_CONDITIONAL_IMPL(!condition, * MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE(someBranchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_BRANCH_DECL} * @expectation{MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE} * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier for the branch for which the positive scenario is * executed. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior related to this event. */ #define MCUX_CSSL_FP_BRANCH_POSITIVE(...) \ MCUX_CSSL_FP_BRANCH_POSITIVE_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_BRANCH_NEGATIVE * @brief Negative scenario of a branch is executed. * @api * @ingroup csslFpBranch * * This branch event macro informs the flow mechanism that the positive scenario * of the branch is executed for the branch declared by * #MCUX_CSSL_FP_BRANCH_DECL with the given \p id. For example: * @code * MCUX_CSSL_FP_BRANCH_DECL(someBranchIdentifier); * if (condition) * { * MCUX_CSSL_FP_BRANCH_POSITIVE(someBranchIdentifier); * } * else * { * MCUX_CSSL_FP_BRANCH_NEGATIVE(someBranchIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * MCUX_CSSL_FP_CONDITIONAL_IMPL(!condition, * MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE(someBranchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_BRANCH_DECL} * @expectation{MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE} * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier for the branch for which the negative scenario is * executed. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior related to this event. */ #define MCUX_CSSL_FP_BRANCH_NEGATIVE(...) \ MCUX_CSSL_FP_BRANCH_NEGATIVE_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE * @brief Expectation that positive branch has been taken. * @api * @ingroup csslFpBranch * * This expectation macro indicates to the flow protection mechanism that the * branch declared by #MCUX_CSSL_FP_BRANCH_DECL with the given \p id has * executed the positive scenario (under the given \p condition). For example: * @code * MCUX_CSSL_FP_BRANCH_DECL(someBranchIdentifier); * if (condition) * { * MCUX_CSSL_FP_BRANCH_POSITIVE(someBranchIdentifier); * } * else * { * MCUX_CSSL_FP_BRANCH_NEGATIVE(someBranchIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * // Providing the condition as part of the branch expectation. * // Alternatively, the expectation can be placed in a conditional block. * MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE(someBranchIdentifier, condition) * ); * @endcode * * @declaration{MCUX_CSSL_FP_BRANCH_DECL} * @event{MCUX_CSSL_FP_BRANCH_POSITIVE} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * @see MCUX_CSSL_FP_CONDITIONAL * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the flow protected branch. * - condition: Optional, condition under which this branch is taken. */ #define MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE(...) \ MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE * @brief Expectation that negative branch has been taken. * @api * @ingroup csslFpBranch * * This expectation macro indicates to the flow protection mechanism that the * branch declared by #MCUX_CSSL_FP_BRANCH_DECL with the given \p id has * executed the negative scenario (under the given \p condition). For example: * @code * MCUX_CSSL_FP_BRANCH_DECL(someBranchIdentifier); * if (condition) * { * MCUX_CSSL_FP_BRANCH_POSITIVE(someBranchIdentifier); * } * else * { * MCUX_CSSL_FP_BRANCH_NEGATIVE(someBranchIdentifier); * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, 0, * // Providing the branch expectation as part of a conditional block. * // Alternatively, the condition can be provided in the branch expectation. * MCUX_CSSL_FP_CONDITIONAL(!condition, * MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE(someBranchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_BRANCH_DECL} * @event{MCUX_CSSL_FP_BRANCH_NEGATIVE} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * @see MCUX_CSSL_FP_CONDITIONAL * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the flow protected branch. * - condition: Optional, condition under which this branch is taken. */ #define MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE(...) \ MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE_IMPL(__VA_ARGS__) /** * @defgroup csslFpSwitch Switching flow protection * @brief Support for flow protected switches. * @ingroup mcuxCsslFlowProtection * * @declaration{MCUX_CSSL_FP_SWITCH_DECL} * @event{MCUX_CSSL_FP_SWITCH_CASE,MCUX_CSSL_FP_SWITCH_DEFAULT} * @expectation{MCUX_CSSL_FP_SWITCH_TAKEN,MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT} */ /** * @def MCUX_CSSL_FP_SWITCH_DECL * @brief Declaration of a flow protected switch. * @api * @ingroup csslFpSwitch * * To inform the flow protection mechanism about a switch that needs to be * protected, a switch identifier needs to be declared. This identifier can * then be used in the events and expectation macros. For example: * @code * MCUX_CSSL_FP_SWITCH_DECL(someSwitchIdentifier); * switch (arg) * { * case 0xC0DEu: * { * result = 0xC0DEu; * MCUX_CSSL_FP_SWITCH_CASE(someSwitchIdentifier, 0xC0DEu); * break; * } * default: * { * result = 0; * MCUX_CSSL_FP_SWITCH_DEFAULT(someSwitchIdentifier); * break; * } * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, result, * // Option 1: provide the condition as part of the switch expectation. * MCUX_CSSL_FP_SWITCH_TAKEN(someSwitchIdentifier, 0xC0DEu, 0xC0DEu == arg), * // Option 2: place the switch expectation in a conditional block. * MCUX_CSSL_FP_CONDITIONAL(0xC0DEu != arg), * MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT(someSwitchIdentifier) * ) * ); * @endcode * * @event{MCUX_CSSL_FP_SWITCH_CASE,MCUX_CSSL_FP_SWITCH_DEFAULT} * @expectation{MCUX_CSSL_FP_SWITCH_TAKEN,MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT} * * @param id Identifier for the switch that is flow protected. */ #define MCUX_CSSL_FP_SWITCH_DECL(id) \ MCUX_CSSL_FP_SWITCH_DECL_IMPL(id) /** * @def MCUX_CSSL_FP_SWITCH_CASE * @brief Case that is being handled from a switch. * @api * @ingroup csslFpSwitch * * This switch event macro informs the flow mechanism that the given \p case of * the switch is executed for the switch declared by #MCUX_CSSL_FP_SWITCH_DECL * with the given \p id. For example: * @code * MCUX_CSSL_FP_SWITCH_DECL(someSwitchIdentifier); * switch (arg) * { * case 0xC0DEu: * { * result = 0xC0DEu; * MCUX_CSSL_FP_SWITCH_CASE(someSwitchIdentifier, 0xC0DEu); * break; * } * default: * { * result = 0; * MCUX_CSSL_FP_SWITCH_DEFAULT(someSwitchIdentifier); * break; * } * } * // ... * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, result, * // Option 1: provide the condition as part of the switch expectation. * MCUX_CSSL_FP_SWITCH_TAKEN(someSwitchIdentifier, 0xC0DEu, 0xC0DEu == arg), * // Option 2: place the switch expectation in a conditional block. * MCUX_CSSL_FP_CONDITIONAL(0xC0DEu != arg), * MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT(someSwitchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_SWITCH_DECL} * @expectation{MCUX_CSSL_FP_SWITCH_TAKEN} * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the flow protected switch. * - case: Case value that is chosen in the switch. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior related to this event. */ #define MCUX_CSSL_FP_SWITCH_CASE(...) \ MCUX_CSSL_FP_SWITCH_CASE_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_SWITCH_DEFAULT * @brief Case that is being handled from a switch. * @api * @ingroup csslFpSwitch * * This switch event macro informs the flow mechanism that the default case of * the switch is executed for the switch declared by #MCUX_CSSL_FP_SWITCH_DECL * with the given \p id. For example: * @code * MCUX_CSSL_FP_SWITCH_DECL(someSwitchIdentifier); * switch (arg) * { * case 0xC0DEu: * { * result = 0xC0DEu; * MCUX_CSSL_FP_SWITCH_CASE(someSwitchIdentifier, 0xC0DEu); * break; * } * default: * { * result = 0; * MCUX_CSSL_FP_SWITCH_DEFAULT(someSwitchIdentifier); * break; * } * } * * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, result, * // Option 1: provide the condition as part of the switch expectation. * MCUX_CSSL_FP_SWITCH_TAKEN(argCheck, 0xC0DEu, 0xC0DEu == arg), * // Option 2: place the switch expectation in a conditional block. * MCUX_CSSL_FP_CONDITIONAL(0xC0DEu != arg), * MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT(someSwitchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_SWITCH_DECL} * @expectation{MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT} * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the flow protected switch. * - expect: Zero or more (comma separated) declarations of expected code * flow behavior related to this event. */ #define MCUX_CSSL_FP_SWITCH_DEFAULT(...) \ MCUX_CSSL_FP_SWITCH_DEFAULT_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_SWITCH_TAKEN * @brief Expected that a specific case is handled from a switch. * @api * @ingroup csslFpSwitch * * This expectation macro indicates to the flow protection mechanism that the * switch declared by #MCUX_CSSL_FP_SWITCH_DECL with the given \p id has * executed the \p case (under the given \p condition). For example: * @code * MCUX_CSSL_FP_SWITCH_DECL(someSwitchIdentifier); * switch (arg) * { * case 0xC0DEu: * { * result = 0xC0DEu; * MCUX_CSSL_FP_SWITCH_CASE(someSwitchIdentifier, 0xC0DEu); * break; * } * default: * { * result = 0; * MCUX_CSSL_FP_SWITCH_DEFAULT(someSwitchIdentifier); * break; * } * } * * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, result, * // Option 1: provide the condition as part of the switch expectation. * MCUX_CSSL_FP_SWITCH_TAKEN(argCheck, 0xC0DEu, 0xC0DEu == arg), * // Option 2: place the switch expectation in a conditional block. * MCUX_CSSL_FP_CONDITIONAL(0xC0DEu != arg), * MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT(someSwitchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_SWITCH_DECL} * @event{MCUX_CSSL_FP_SWITCH_CASE} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the flow protected switch. * - case: Value of the case that is expected to be chosen in the * switch. * - condition: Optional, condition under which the \p case is taken. */ #define MCUX_CSSL_FP_SWITCH_TAKEN(...) \ MCUX_CSSL_FP_SWITCH_TAKEN_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT * @brief Expected that default case is handled from a switch. * @api * @ingroup csslFpSwitch * * This expectation macro indicates to the flow protection mechanism that the * switch declared by #MCUX_CSSL_FP_SWITCH_DECL with the given \p id has * executed the default case (under the given \p condition). For example: * @code * MCUX_CSSL_FP_SWITCH_DECL(someSwitchIdentifier); * switch (arg) * { * case 0xC0DEu: * { * result = 0xC0DEu; * MCUX_CSSL_FP_SWITCH_CASE(someSwitchIdentifier, 0xC0DEu); * break; * } * default: * { * result = 0; * MCUX_CSSL_FP_SWITCH_DEFAULT(someSwitchIdentifier); * break; * } * } * * MCUX_CSSL_FP_FUNCTION_EXIT(someFunction, result, * // Option 1: provide the condition as part of the switch expectation. * MCUX_CSSL_FP_SWITCH_TAKEN(argCheck, 0xC0DEu, 0xC0DEu == arg), * // Option 2: place the switch expectation in a conditional block. * MCUX_CSSL_FP_CONDITIONAL(0xC0DEu != arg), * MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT(someSwitchIdentifier) * ) * ); * @endcode * * @declaration{MCUX_CSSL_FP_SWITCH_DECL} * @event{MCUX_CSSL_FP_SWITCH_DEFAULT} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * * @param ... The following parameters need to be passed (comma separated): * - id: Identifier of the flow protected switch. * - condition: Optional, condition under which the default case is taken. */ #define MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT(...) \ MCUX_CSSL_FP_SWITCH_TAKEN_DEFAULT_IMPL(__VA_ARGS__) /** * @defgroup csslFpExpect Expectation handling * @brief Expectation handling support functionality. * * @ingroup mcuxCsslFlowProtection */ /** * @def MCUX_CSSL_FP_EXPECT * @brief Declaration(s) of expected code flow behavior. * @api * @ingroup csslFpExpect * * This macro can be used to indicate expectations in the function body at * another location than the function entry or exit. * * @note In general the use of this macro is discouraged, to avoid a potential * security and/or code-size impact. However, it may be usefull for complex * code, where an intermediate update can actually save code, since conditions * for expectations can than be locallized. * * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED,MCUX_CSSL_FP_LOOP_ITERATIONS,MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE,MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE,MCUX_CSSL_FP_SWITCH_TAKEN} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_CONDITIONAL * * @param ... The following parameters need to be passed (comma separated): * - expect: One or more (comma separated) declarations of expected code * flow behavior. */ #define MCUX_CSSL_FP_EXPECT(...) \ MCUX_CSSL_FP_EXPECT_IMPL(__VA_ARGS__) /** * @def MCUX_CSSL_FP_CONDITIONAL * @brief Handling of conditionally expected code flow behavior. * @api * @ingroup csslFpExpect * * This macro can be used to indicate expectations that are only true under a * given \p condition. * * @expectation{MCUX_CSSL_FP_FUNCTION_CALLED,MCUX_CSSL_FP_LOOP_ITERATIONS,MCUX_CSSL_FP_BRANCH_TAKEN_POSITIVE,MCUX_CSSL_FP_BRANCH_TAKEN_NEGATIVE,MCUX_CSSL_FP_SWITCH_TAKEN} * * @see MCUX_CSSL_FP_FUNCTION_ENTRY * @see MCUX_CSSL_FP_FUNCTION_EXIT * @see MCUX_CSSL_FP_FUNCTION_EXIT_WITH_CHECK * @see MCUX_CSSL_FP_EXPECT * * @param condition Condition under which the given expectations apply. * @param ... One or more (comma separated) declarations of expected code * flow behavior. */ #define MCUX_CSSL_FP_CONDITIONAL(condition, ...) \ MCUX_CSSL_FP_CONDITIONAL_IMPL(condition, __VA_ARGS__) #endif /* MCUX_CSSL_FLOW_PROTECTION_H_ */