From 08620cbb62b7ce26d58cdba335b7b87407764929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 19 Sep 2019 10:45:14 +0200 Subject: [PATCH] Implement static dispatch with SINGLE_PK_TYPE For optional functions, we introduce an extra macro to tell if the function is omitted. As the C preprocessor doesn't directly support comparing strings, testing if the _FUNC macro is defined to NULL isn't obvious. One could probably play tricks to avoid the need for _OMIT macros, but the small amount of (entirely local) duplication here is probably a lesser evil than extra preprocessor complexity. --- include/mbedtls/pk_internal.h | 18 ++++ library/pk.c | 172 +++++++++++++++++++++++++++++++++- 2 files changed, 188 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h index fd89aa947..65bd8e93b 100644 --- a/include/mbedtls/pk_internal.h +++ b/include/mbedtls/pk_internal.h @@ -41,6 +41,9 @@ * Each PK type that can be used with MBEDTLS_PK_SINGLE_TYPE needs to have * the following MBEDTLS_PK_INFO_{FIELD} definitions, plus a dummy one for the * base name. For now, only ECKEY with MBEDTLS_USE_TINYCRYPT is defined. + * + * For optional functions that are omitted, we need both the _FUNC field + * defined to NULL, and an extra macro _OMIT defined to 1. */ #if defined(MBEDTLS_USE_TINYCRYPT) @@ -54,11 +57,14 @@ #define MBEDTLS_PK_INFO_ECKEY_VERIFY_FUNC uecc_eckey_verify_wrap #define MBEDTLS_PK_INFO_ECKEY_SIGN_FUNC uecc_eckey_sign_wrap #define MBEDTLS_PK_INFO_ECKEY_DECRYPT_FUNC NULL +#define MBEDTLS_PK_INFO_ECKEY_DECRYPT_OMIT 1 #define MBEDTLS_PK_INFO_ECKEY_ENCRYPT_FUNC NULL +#define MBEDTLS_PK_INFO_ECKEY_ENCRYPT_OMIT 1 #define MBEDTLS_PK_INFO_ECKEY_CHECK_PAIR_FUNC uecc_eckey_check_pair #define MBEDTLS_PK_INFO_ECKEY_CTX_ALLOC_FUNC uecc_eckey_alloc_wrap #define MBEDTLS_PK_INFO_ECKEY_CTX_FREE_FUNC uecc_eckey_free_wrap #define MBEDTLS_PK_INFO_ECKEY_DEBUG_FUNC NULL +#define MBEDTLS_PK_INFO_ECKEY_DEBUG_OMIT 1 #endif /* MBEDTLS_USE_TINYCRYPT */ /* @@ -69,13 +75,19 @@ #define MBEDTLS_PK_INFO_GET_BITLEN_T( PK ) PK ## _GET_BITLEN #define MBEDTLS_PK_INFO_CAN_DO_T( PK ) PK ## _CAN_DO #define MBEDTLS_PK_INFO_VERIFY_FUNC_T( PK ) PK ## _VERIFY_FUNC +#define MBEDTLS_PK_INFO_VERIFY_OMIT_T( PK ) PK ## _VERIFY_OMIT #define MBEDTLS_PK_INFO_SIGN_FUNC_T( PK ) PK ## _SIGN_FUNC +#define MBEDTLS_PK_INFO_SIGN_OMIT_T( PK ) PK ## _SIGN_OMIT #define MBEDTLS_PK_INFO_DECRYPT_FUNC_T( PK ) PK ## _DECRYPT_FUNC +#define MBEDTLS_PK_INFO_DECRYPT_OMIT_T( PK ) PK ## _DECRYPT_OMIT #define MBEDTLS_PK_INFO_ENCRYPT_FUNC_T( PK ) PK ## _ENCRYPT_FUNC +#define MBEDTLS_PK_INFO_ENCRYPT_OMIT_T( PK ) PK ## _ENCRYPT_OMIT #define MBEDTLS_PK_INFO_CHECK_PAIR_FUNC_T( PK ) PK ## _CHECK_PAIR_FUNC +#define MBEDTLS_PK_INFO_CHECK_PAIR_OMIT_T( PK ) PK ## _CHECK_PAIR_OMIT #define MBEDTLS_PK_INFO_CTX_ALLOC_FUNC_T( PK ) PK ## _CTX_ALLOC_FUNC #define MBEDTLS_PK_INFO_CTX_FREE_FUNC_T( PK ) PK ## _CTX_FREE_FUNC #define MBEDTLS_PK_INFO_DEBUG_FUNC_T( PK ) PK ## _DEBUG_FUNC +#define MBEDTLS_PK_INFO_DEBUG_OMIT_T( PK ) PK ## _DEBUG_OMIT /* Wrappers around MBEDTLS_PK_INFO_{FIELD}_T() which makes sure that * the argument is macro-expanded before concatenated with the @@ -87,13 +99,19 @@ #define MBEDTLS_PK_INFO_GET_BITLEN( PK ) MBEDTLS_PK_INFO_GET_BITLEN_T( PK ) #define MBEDTLS_PK_INFO_CAN_DO( PK ) MBEDTLS_PK_INFO_CAN_DO_T( PK ) #define MBEDTLS_PK_INFO_VERIFY_FUNC( PK ) MBEDTLS_PK_INFO_VERIFY_FUNC_T( PK ) +#define MBEDTLS_PK_INFO_VERIFY_OMIT( PK ) MBEDTLS_PK_INFO_VERIFY_OMIT_T( PK ) #define MBEDTLS_PK_INFO_SIGN_FUNC( PK ) MBEDTLS_PK_INFO_SIGN_FUNC_T( PK ) +#define MBEDTLS_PK_INFO_SIGN_OMIT( PK ) MBEDTLS_PK_INFO_SIGN_OMIT_T( PK ) #define MBEDTLS_PK_INFO_DECRYPT_FUNC( PK ) MBEDTLS_PK_INFO_DECRYPT_FUNC_T( PK ) +#define MBEDTLS_PK_INFO_DECRYPT_OMIT( PK ) MBEDTLS_PK_INFO_DECRYPT_OMIT_T( PK ) #define MBEDTLS_PK_INFO_ENCRYPT_FUNC( PK ) MBEDTLS_PK_INFO_ENCRYPT_FUNC_T( PK ) +#define MBEDTLS_PK_INFO_ENCRYPT_OMIT( PK ) MBEDTLS_PK_INFO_ENCRYPT_OMIT_T( PK ) #define MBEDTLS_PK_INFO_CHECK_PAIR_FUNC( PK ) MBEDTLS_PK_INFO_CHECK_PAIR_FUNC_T( PK ) +#define MBEDTLS_PK_INFO_CHECK_PAIR_OMIT( PK ) MBEDTLS_PK_INFO_CHECK_PAIR_OMIT_T( PK ) #define MBEDTLS_PK_INFO_CTX_ALLOC_FUNC( PK ) MBEDTLS_PK_INFO_CTX_ALLOC_FUNC_T( PK ) #define MBEDTLS_PK_INFO_CTX_FREE_FUNC( PK ) MBEDTLS_PK_INFO_CTX_FREE_FUNC_T( PK ) #define MBEDTLS_PK_INFO_DEBUG_FUNC( PK ) MBEDTLS_PK_INFO_DEBUG_FUNC_T( PK ) +#define MBEDTLS_PK_INFO_DEBUG_OMIT( PK ) MBEDTLS_PK_INFO_DEBUG_OMIT_T( PK ) struct mbedtls_pk_info_t { diff --git a/library/pk.c b/library/pk.c index ef08eb7b0..9f85718c9 100644 --- a/library/pk.c +++ b/library/pk.c @@ -1001,8 +1001,9 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /* - * Access to members of the pk_info structure. These are meant to be replaced - * by zero-runtime-cost accessors when a single PK type is hardcoded. + * Access to members of the pk_info structure. When a single PK type is + * hardcoded, these should have zero runtime cost; otherwise, the usual + * dynamic dispatch based on pk_info is used. * * For function members, don't make a getter, but a function that directly * calls the method, so that we can entirely get rid of function pointers @@ -1012,6 +1013,171 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { * MBEDTLS_ECP_RESTARTABLE for now, as the main target for hardcoded is builds * with MBEDTLS_USE_TINYCRYPT, which don't have MBEDTLS_ECP_RESTARTABLE. */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) + +MBEDTLS_ALWAYS_INLINE static inline mbedtls_pk_type_t pk_info_type( + const mbedtls_pk_info_t *info ) +{ + (void) info; + return( MBEDTLS_PK_INFO_TYPE( MBEDTLS_PK_SINGLE_TYPE ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline const char * pk_info_name( + const mbedtls_pk_info_t *info ) +{ + (void) info; + return( MBEDTLS_PK_INFO_NAME( MBEDTLS_PK_SINGLE_TYPE ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline size_t pk_info_get_bitlen( + const mbedtls_pk_info_t *info, const void *ctx ) +{ + (void) info; + return( MBEDTLS_PK_INFO_GET_BITLEN( MBEDTLS_PK_SINGLE_TYPE )( ctx ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_can_do( + const mbedtls_pk_info_t *info, mbedtls_pk_type_t type ) +{ + (void) info; + return( MBEDTLS_PK_INFO_CAN_DO( MBEDTLS_PK_SINGLE_TYPE )( type ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_verify_func( + const mbedtls_pk_info_t *info, void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + (void) info; +#if MBEDTLS_PK_INFO_VERIFY_OMIT( MBEDTLS_PK_SINGLE_TYPE ) + (void) ctx; + (void) md_alg; + (void) hash; + (void) hash_len; + (void) sig; + (void) sig_len; + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + return( MBEDTLS_PK_INFO_VERIFY_FUNC( MBEDTLS_PK_SINGLE_TYPE )( + ctx, md_alg, hash, hash_len, sig, sig_len ) ); +#endif +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_sign_func( + const mbedtls_pk_info_t *info, void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + (void) info; +#if MBEDTLS_PK_INFO_SIGN_OMIT( MBEDTLS_PK_SINGLE_TYPE ) + (void) ctx; + (void) md_alg; + (void) hash; + (void) hash_len; + (void) sig; + (void) sig_len; + (void) f_rng; + (void) p_rng; + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + return( MBEDTLS_PK_INFO_SIGN_FUNC( MBEDTLS_PK_SINGLE_TYPE )( + ctx, md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +#endif +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_decrypt_func( + const mbedtls_pk_info_t *info, void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + (void) info; +#if MBEDTLS_PK_INFO_DECRYPT_OMIT( MBEDTLS_PK_SINGLE_TYPE ) + (void) ctx; + (void) input; + (void) ilen; + (void) output; + (void) olen; + (void) osize; + (void) f_rng; + (void) p_rng; + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + return( MBEDTLS_PK_INFO_DECRYPT_FUNC( MBEDTLS_PK_SINGLE_TYPE )( + ctx, input, ilen, output, olen, osize, f_rng, p_rng ) ); +#endif +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_encrypt_func( + const mbedtls_pk_info_t *info, void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + (void) info; +#if MBEDTLS_PK_INFO_ENCRYPT_OMIT( MBEDTLS_PK_SINGLE_TYPE ) + (void) ctx; + (void) input; + (void) ilen; + (void) output; + (void) olen; + (void) osize; + (void) f_rng; + (void) p_rng; + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + return( MBEDTLS_PK_INFO_ENCRYPT_FUNC( MBEDTLS_PK_SINGLE_TYPE )( + ctx, input, ilen, output, olen, osize, f_rng, p_rng ) ); +#endif +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_check_pair_func( + const mbedtls_pk_info_t *info, const void *pub, const void *prv ) +{ + (void) info; +#if MBEDTLS_PK_INFO_CHECK_PAIR_OMIT( MBEDTLS_PK_SINGLE_TYPE ) + (void) pub; + (void) prv; + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#else + return( MBEDTLS_PK_INFO_CHECK_PAIR_FUNC( MBEDTLS_PK_SINGLE_TYPE )( + pub, prv ) ); +#endif +} + +MBEDTLS_ALWAYS_INLINE static inline void *pk_info_ctx_alloc_func( + const mbedtls_pk_info_t *info ) +{ + (void) info; + return( MBEDTLS_PK_INFO_CTX_ALLOC_FUNC( MBEDTLS_PK_SINGLE_TYPE )( ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline void pk_info_ctx_free_func( + const mbedtls_pk_info_t *info, void *ctx ) +{ + (void) info; + MBEDTLS_PK_INFO_CTX_FREE_FUNC( MBEDTLS_PK_SINGLE_TYPE )( ctx ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_debug_func( + const mbedtls_pk_info_t *info, + const void *ctx, mbedtls_pk_debug_item *items ) +{ + (void) info; +#if MBEDTLS_PK_INFO_DEBUG_OMIT( MBEDTLS_PK_SINGLE_TYPE ) + (void) ctx; + (void) items; + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + return( MBEDTLS_PK_INFO_DEBUG_FUNC( MBEDTLS_PK_SINGLE_TYPE )( ctx, items ) ); +#endif +} + +#else /* MBEDTLS_PK_SINGLE_TYPE */ MBEDTLS_ALWAYS_INLINE static inline mbedtls_pk_type_t pk_info_type( const mbedtls_pk_info_t *info ) @@ -1122,6 +1288,8 @@ MBEDTLS_ALWAYS_INLINE static inline int pk_info_debug_func( return( 0 ); } +#endif /* MBEDTLS_PK_SINGLE_TYPE */ + /* * Initialise a mbedtls_pk_context */