From ac267f3485b19e3dcee59f8a7ab0aaeb4a2398d5 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 12 Jan 2021 07:25:41 +0000 Subject: [PATCH] Add MPS configuration option for state validation See the documentation in library/mps/common.h which this commit modifies. Signed-off-by: Hanno Becker --- library/mps/common.h | 63 ++++++++++++++++++++++++++++++++++++++++++++ library/mps/error.h | 18 +++++++++++++ 2 files changed, 81 insertions(+) diff --git a/library/mps/common.h b/library/mps/common.h index 8ea80c174f..37a4cefe54 100644 --- a/library/mps/common.h +++ b/library/mps/common.h @@ -34,6 +34,46 @@ * \{ */ +/*! This flag controls whether the MPS-internal components + * (reader, writer, Layer 1-3) perform validation of the + * expected abstract state at the entry of API calls. + * + * Context: All MPS API functions impose assumptions/preconditions on the + * context on which they operate. For example, every structure has a notion of + * state integrity which is established by `xxx_init()` and preserved by any + * calls to the MPS API which satisfy their preconditions and either succeed, + * or fail with an error code which is explicitly documented to not corrupt + * structure integrity (such as WANT_READ and WANT_WRITE); + * apart from `xxx_init()` any function assumes state integrity as a + * precondition (but usually more). If any of the preconditions is violated, + * the function's behavior is entirely undefined. + * In addition to state integrity, all MPS structures have a more refined + * notion of abstract state that the API operates on. For example, all layers + * have a notion of 'abtract read state' which indicates if incoming data has + * been passed to the user, e.g. through mps_l2_read_start() for Layer 2 + * or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to + * call these reading functions again until the incoming data has been + * explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or + * mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense, + * it's a design choice whether the API should fail gracefully on such + * non-sensical calls or not, and that's what this option is about: + * + * This option determines whether the expected abstract state + * is part of the API preconditions or not. If it is, the function's + * behavior is undefined if the abstract state is not as expected. + * If it is set, API is required to fail gracefully with error + * #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED, and without changing the abstract + * state of the input context, if the abstract state is unexpected but + * all other preconditions are satisfied. + * + * For example: Enabling this makes mps_l2_read_done() fail if + * no incoming record is currently open; disabling this would + * lead to undefined behavior in this case. + * + * Comment this to remove state validation. + */ +#define MBEDTLS_MPS_STATE_VALIDATION + /*! This flag enables/disables assertions on the internal state of MPS. * * Assertions are sanity checks that should never trigger when MPS @@ -52,6 +92,28 @@ /*! This flag controls whether tracing for MPS should be enabled. */ //#define MBEDTLS_MPS_TRACE +#if defined(MBEDTLS_MPS_STATE_VALIDATION) + +#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string ) \ + do \ + { \ + if( !(cond) ) \ + { \ + TRACE( trace_error, string ); \ + RETURN( MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED ); \ + } \ + } while( 0 ) + +#else /* MBEDTLS_MPS_STATE_VALIDATION */ + +#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string ) \ + do \ + { \ + ( cond ); \ + } while( 0 ) + +#endif /* MBEDTLS_MPS_STATE_VALIDATION */ + #if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS) #define MBEDTLS_MPS_ASSERT_RAW( cond, string ) \ @@ -70,6 +132,7 @@ #endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */ + /* \} name SECTION: MPS Configuration */ /** diff --git a/library/mps/error.h b/library/mps/error.h index 3c4180f332..8916d60683 100644 --- a/library/mps/error.h +++ b/library/mps/error.h @@ -42,6 +42,24 @@ #define MBEDTLS_MPS_ERR_BASE ( 1 << 0 ) #endif +/** + * \name SECTION: MPS general error codes + * + * \{ + */ + +#ifndef MBEDTLS_MPS_ERR_BASE +#define MBEDTLS_MPS_ERR_BASE ( 1 << 10 ) +#endif + +#define MBEDTLS_MPS_MAKE_ERROR(code) \ + ( -( MBEDTLS_MPS_ERR_BASE | (code) ) ) + + +#define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED MBEDTLS_MPS_MAKE_ERROR( 0x1 ) + +/* \} name SECTION: MPS general error codes */ + /** * \name SECTION: MPS Reader error codes *