From c9c32f3f639bb64153c3130110f38797392cb615 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 13 Aug 2018 15:52:45 +0100 Subject: [PATCH] ECDH: Add flexible context and legacy flag We want to support alternative software implementations and we extend the ECDH context to enable this. The actual functional change that makes use of the new context is out of scope for this commit. Changing the context breaks the API and therefore it has to be excluded from the default configuration by a compile time flag. We add the compile time flag to the module header instead of `config.h`, because this is not a standalone feature, it only enables adding new implementations in the future. The new context features a union of the individual implementations and a selector that chooses the implementation in use. An alternative is to use an opaque context and function pointers, like for example the PK module does it, but it is more dangerous, error prone and tedious to implement. We leave the group ID and the point format at the top level of the structure, because they are very simple and adding an abstraction layer around them away does not come with any obvious benefit. Other alternatives considered: - Using the module level replacement mechanism in the ECP module. This would have made the use of the replacement feature more difficult and the benefit limited. - Replacing our Montgomery implementations with a new one directly. This would have prevented using Montgomery curves across implementations. (For example use implementation A for Curve448 and implementation B for Curve22519.) Also it would have been inflexible and limited to Montgomery curves. - Encoding the implementation selector and the alternative context in `mbedtls_ecp_point` somehow and rewriting `mbedtls_ecp_mul()` to dispatch between implementations. This would have been a dangerous and ugly hack, and very likely to break legacy applications. - Same as above just with hardcoding the selector and using a compile time option to make the selection. Rejected for the same reasons as above. - Using the PK module to provide to provide an entry point for alternative implementations. Like most of the above options this wouldn't have come with a new compile time option, but conceptually would have been very out of place and would have meant much more work to complete the abstraction around the context. In retrospect: - We could have used the group ID as the selector, but this would have made the code less flexible and only marginally simpler. On the other hand it would have allowed to get rid of the compile time option if a tight integration of the alternative is possible. (It does not seem possible at this point.) - We could have used the same approach we do in this commit to the `mbedtls_ecp_point` structure. Completing the abstraction around this structure would have been a much bigger and much riskier code change with increase in memory footprint, potential decrease in performance and no immediate benefit. --- include/mbedtls/ecdh.h | 67 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index 68a6989c8..cbd48414a 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -36,6 +36,18 @@ #include "ecp.h" +/* + * Use a backward compatible ECDH context. + * + * This flag is always enabled for now and future versions might add a + * configuration option that conditionally undefines this flag. + * The configuration option in question may have a different name. + * + * Features undefining this flag, must have a warning in their description in + * config.h stating that the feature breaks backward compatibility. + */ +#define MBEDTLS_ECDH_LEGACY_CONTEXT + #ifdef __cplusplus extern "C" { #endif @@ -49,6 +61,39 @@ typedef enum MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ } mbedtls_ecdh_side; +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + /** * * \warning Performing multiple operations concurrently on the same @@ -58,6 +103,7 @@ typedef enum */ typedef struct mbedtls_ecdh_context { +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_ecp_group grp; /*!< The elliptic curve used. */ mbedtls_mpi d; /*!< The private key. */ mbedtls_ecp_point Q; /*!< The public key. */ @@ -70,7 +116,26 @@ typedef struct mbedtls_ecdh_context #if defined(MBEDTLS_ECP_RESTARTABLE) int restart_enabled; /*!< The flag for restartable mode. */ mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ -#endif +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ } mbedtls_ecdh_context;