diff --git a/configs/baremetal.h b/configs/baremetal.h index 4a67c98dd..64d9e04d8 100644 --- a/configs/baremetal.h +++ b/configs/baremetal.h @@ -52,7 +52,9 @@ #define MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_MD_ID MBEDTLS_MD_SHA256 #define MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_TLS_ID MBEDTLS_SSL_HASH_SHA256 +/* Harcoded options in abstraction layers */ #define MBEDTLS_MD_SINGLE_HASH MBEDTLS_MD_INFO_SHA256 +#define MBEDTLS_PK_SINGLE_TYPE MBEDTLS_PK_INFO_ECKEY /* Key exchanges */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index ceeb2efb2..c3f1545f8 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -855,6 +855,37 @@ #undef MBEDTLS_HASHES_ENABLED #endif /* MBEDTLS_MD_SINGLE_HASH */ +/* + * Note: the dependency on TinyCrypt is reflected in several ways in the code: + * + * 1. We only define the various MBEDTLS_PK_INFO_{TYPE}_{FIELD} macros for + * TYPE == ECKEY, resolving to the TinyCrypt version. + * 2. In pk_init() and pk_free() we assume that zeroization is a proper way + * to init/free the context, which is true of mbedtls_uecc_keypair, but + * might not always hold otherwise (think hardware-accelerated ECP_ALT). + * 3. We rely on the fact that MBEDTLS_ECP_RESTARTABLE is disabled - code + * paths (and pk_info fields) that are guarded by this are currently not + * handled by the internal abstraction layers enabling PK_SINGLE_TYPE. + * + * If this dependency is ever removed, the above points need to be addressed + * in the code. + */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) && !defined(MBEDTLS_USE_TINYCRYPT) +#error "MBEDTLS_PK_SINGLE_TYPE can only be used with MBEDTLS_USE_TINYCRYPT" +#endif + +/* Note: code paths that depend on MBEDTLS_PK_RSA_ALT_SUPPORT are not ported + * to the internal abstraction layers that enable PK_SINGLE_TYPE. */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) && defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#error "MBEDTLS_PK_SINGLE_TYPE is not compatible with MBEDTLS_PK_RSA_ALT_SUPPORT" +#endif + +/* This is to avoid a situation where RSA is available, but not through the PK + * layer, which might surprise user code. */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) && defined(MBEDTLS_RSA_C) +#error "MBEDTLS_PK_SINGLE_TYPE is not compatible with MBEDTLS_RSA_C" +#endif + #if defined(MBEDTLS_THREADING_ALT) #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 3b38a5b9d..1a057a4af 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -3850,6 +3850,17 @@ */ //#define MBEDTLS_MD_SINGLE_HASH MBEDTLS_MD_INFO_SHA256 +/* Enable support for a single PK type in the PK layer. + * + * This is mainly intented to reduce code size on highly constrained system + * with large control over the set of algorithms they need to support. It will + * also reduce dynamic memory allocation. + * + * Currently this is only supported with EC keys in conjunction with the + * MBEDTLS_USE_TINYCRYPT option. Set this to MBEDTLS_PK_INFO_ECKEY to enable. + */ +//#define MBEDTLS_PK_SINGLE_TYPE MBEDTLS_PK_INFO_ECKEY + /* \} SECTION: Compile-time SSL configuration */ /* Target and application specific configurations diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index e9fd78fab..2ed9c07b6 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -49,6 +49,10 @@ #include "tinycrypt/ecc.h" #endif +#if defined(MBEDTLS_PK_SINGLE_TYPE) +#include "pk_internal.h" +#endif + #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline @@ -126,16 +130,16 @@ typedef struct mbedtls_pk_debug_item /** * \brief Public key information and operations */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) +typedef enum { + MBEDTLS_PK_INVALID_HANDLE, + MBEDTLS_PK_UNIQUE_VALID_HANDLE, +} mbedtls_pk_handle_t; +#else /* MBEDTLS_PK_SINGLE_TYPE */ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; - -/** - * \brief Public key container - */ -typedef struct mbedtls_pk_context -{ - const mbedtls_pk_info_t * pk_info; /**< Public key information */ - void * pk_ctx; /**< Underlying public key context */ -} mbedtls_pk_context; +typedef const mbedtls_pk_info_t *mbedtls_pk_handle_t; +#define MBEDTLS_PK_INVALID_HANDLE ( (mbedtls_pk_handle_t) NULL ) +#endif /* MBEDTLS_PK_SINGLE_TYPE */ #if defined(MBEDTLS_USE_TINYCRYPT) typedef struct @@ -145,13 +149,29 @@ typedef struct } mbedtls_uecc_keypair; #endif +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ +#if defined(MBEDTLS_PK_SINGLE_TYPE) + /* This is an array to make access to it more uniform with the case where + * it's a pointer to void - either way it needs casting before use. */ + unsigned char pk_ctx[sizeof( + MBEDTLS_PK_INFO_CONTEXT( MBEDTLS_PK_SINGLE_TYPE ) )]; +#else + mbedtls_pk_handle_t pk_info; /**< Public key information */ + void * pk_ctx; /**< Underlying public key context */ +#endif +} mbedtls_pk_context; + #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Context for resuming operations */ typedef struct { - const mbedtls_pk_info_t * pk_info; /**< Public key information */ + mbedtls_pk_handle_t pk_info; /**< Public key information */ void * rs_ctx; /**< Underlying restart context */ } mbedtls_pk_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ @@ -173,11 +193,18 @@ static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_USE_TINYCRYPT) +#if !defined(MBEDTLS_PK_SINGLE_TYPE) static inline mbedtls_uecc_keypair *mbedtls_pk_uecc( const mbedtls_pk_context pk ) { return( (mbedtls_uecc_keypair *) (pk).pk_ctx ); } +#else +/* Go with a macro in order to avoid making a copy of the struct (the argument + * is not a pointer so it's passed by value) and then returning an address + * inside that copy, which would be undefined behaviour. */ +#define mbedtls_pk_uecc( pk ) ( (mbedtls_uecc_keypair *) (pk).pk_ctx ) #endif +#endif /* MBEDTLS_USE_TINYCRYPT */ #if defined(MBEDTLS_ECP_C) /** @@ -213,7 +240,7 @@ typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); * * \return The PK info associated with the type or NULL if not found. */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); +mbedtls_pk_handle_t mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); /** * \brief Initialize a #mbedtls_pk_context (as NONE). @@ -264,7 +291,7 @@ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); * \note For contexts holding an RSA-alt key, use * \c mbedtls_pk_setup_rsa_alt() instead. */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); +int mbedtls_pk_setup( mbedtls_pk_context *ctx, mbedtls_pk_handle_t info ); #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h index d3b501dd9..2c7d0f98f 100644 --- a/include/mbedtls/pk_internal.h +++ b/include/mbedtls/pk_internal.h @@ -33,6 +33,90 @@ #include "pk.h" +/* + * PK information macro definitions + */ + +/* + * 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) +/* Dummy definition to keep check-names.sh happy - don't uncomment */ +//#define MBEDTLS_PK_INFO_ECKEY + +#define MBEDTLS_PK_INFO_ECKEY_CONTEXT mbedtls_uecc_keypair +#define MBEDTLS_PK_INFO_ECKEY_TYPE MBEDTLS_PK_ECKEY +#define MBEDTLS_PK_INFO_ECKEY_NAME "EC" +#define MBEDTLS_PK_INFO_ECKEY_GET_BITLEN uecc_eckey_get_bitlen +#define MBEDTLS_PK_INFO_ECKEY_CAN_DO uecc_eckey_can_do +#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 */ + +/* + * Helper macros to extract fields from PK types + */ +#define MBEDTLS_PK_INFO_CONTEXT_T( PK ) PK ## _CONTEXT +#define MBEDTLS_PK_INFO_TYPE_T( PK ) PK ## _TYPE +#define MBEDTLS_PK_INFO_NAME_T( PK ) PK ## _NAME +#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 + * field name. This allows to call these macros as + * MBEDTLS_PK_INFO_{FIELD}( MBEDTLS_PK_SINGLE_TYPE ). + * where MBEDTLS_PK_SINGLE_TYPE expands to MBEDTLS_PK_INFO_{TYPE}. */ +#define MBEDTLS_PK_INFO_CONTEXT( PK ) MBEDTLS_PK_INFO_CONTEXT_T( PK ) +#define MBEDTLS_PK_INFO_TYPE( PK ) MBEDTLS_PK_INFO_TYPE_T( PK ) +#define MBEDTLS_PK_INFO_NAME( PK ) MBEDTLS_PK_INFO_NAME_T( PK ) +#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 ) + +#if !defined(MBEDTLS_PK_SINGLE_TYPE) struct mbedtls_pk_info_t { /** Public key type */ @@ -41,18 +125,19 @@ struct mbedtls_pk_info_t /** Type name */ const char *name; - /** Get key size in bits */ + /** Get key size in bits (must be valid)*/ size_t (*get_bitlen)( const void * ); - /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) + * (must be valid) */ int (*can_do)( mbedtls_pk_type_t type ); - /** Verify signature */ + /** Verify signature (may be NULL) */ int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ); - /** Make signature */ + /** Make signature (may be NULL)*/ int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, @@ -60,13 +145,13 @@ struct mbedtls_pk_info_t void *p_rng ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /** Verify signature (restartable) */ + /** Verify signature (restartable) (may be NULL) */ int (*verify_rs_func)( 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 *rs_ctx ); - /** Make signature (restartable) */ + /** Make signature (restartable) (may be NULL) */ int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, @@ -74,39 +159,94 @@ struct mbedtls_pk_info_t void *p_rng, void *rs_ctx ); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - /** Decrypt message */ + /** Decrypt message (may be NULL) */ int (*decrypt_func)( 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 ); - /** Encrypt message */ + /** Encrypt message (may be NULL ) */ int (*encrypt_func)( 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 ); - /** Check public-private key pair */ + /** Check public-private key pair (may be NULL) */ int (*check_pair_func)( const void *pub, const void *prv ); - /** Allocate a new context */ + /** Allocate a new context (must be valid) */ void * (*ctx_alloc_func)( void ); - /** Free the given context */ + /** Free the given context (must be valid) */ void (*ctx_free_func)( void *ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /** Allocate the restart context */ + /** Allocate the restart context (may be NULL)*/ void * (*rs_alloc_func)( void ); - /** Free the restart context */ + /** Free the restart context (may be NULL) */ void (*rs_free_func)( void *rs_ctx ); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - /** Interface with the debug module */ + /** Interface with the debug module (may be NULL) */ void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); }; + +/** + * \brief This macro builds an instance of ::mbedtls_pk_info_t + * from an \c MBEDTLS_PK_INFO_{TYPE} identifier. + */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_PK_INFO( PK ) \ +{ \ + MBEDTLS_PK_INFO_TYPE( PK ), \ + MBEDTLS_PK_INFO_NAME( PK ), \ + MBEDTLS_PK_INFO_GET_BITLEN( PK ), \ + MBEDTLS_PK_INFO_CAN_DO( PK ), \ + MBEDTLS_PK_INFO_VERIFY_FUNC( PK ), \ + MBEDTLS_PK_INFO_SIGN_FUNC( PK ), \ + NULL, \ + NULL, \ + MBEDTLS_PK_INFO_DECRYPT_FUNC( PK ), \ + MBEDTLS_PK_INFO_ENCRYPT_FUNC( PK ), \ + MBEDTLS_PK_INFO_CHECK_PAIR_FUNC( PK ), \ + MBEDTLS_PK_INFO_CTX_ALLOC_FUNC( PK ), \ + MBEDTLS_PK_INFO_CTX_FREE_FUNC( PK ), \ + NULL, \ + NULL, \ + MBEDTLS_PK_INFO_DEBUG_FUNC( PK ), \ +} +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#define MBEDTLS_PK_INFO( PK ) \ +{ \ + MBEDTLS_PK_INFO_TYPE( PK ), \ + MBEDTLS_PK_INFO_NAME( PK ), \ + MBEDTLS_PK_INFO_GET_BITLEN( PK ), \ + MBEDTLS_PK_INFO_CAN_DO( PK ), \ + MBEDTLS_PK_INFO_VERIFY_FUNC( PK ), \ + MBEDTLS_PK_INFO_SIGN_FUNC( PK ), \ + MBEDTLS_PK_INFO_DECRYPT_FUNC( PK ), \ + MBEDTLS_PK_INFO_ENCRYPT_FUNC( PK ), \ + MBEDTLS_PK_INFO_CHECK_PAIR_FUNC( PK ), \ + MBEDTLS_PK_INFO_CTX_ALLOC_FUNC( PK ), \ + MBEDTLS_PK_INFO_CTX_FREE_FUNC( PK ), \ + MBEDTLS_PK_INFO_DEBUG_FUNC( PK ), \ +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_PK_SINGLE_TYPE */ + +/* + * Macros to access pk_info + */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) +#define MBEDTLS_PK_CTX_INFO( ctx ) MBEDTLS_PK_UNIQUE_VALID_HANDLE +#else +#define MBEDTLS_PK_CTX_INFO( ctx ) ( (ctx)->pk_info ) +#endif +#define MBEDTLS_PK_CTX_IS_VALID( ctx ) \ + ( MBEDTLS_PK_CTX_INFO( (ctx) ) != MBEDTLS_PK_INVALID_HANDLE ) + #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* Container for RSA-alt */ typedef struct @@ -118,6 +258,7 @@ typedef struct } mbedtls_rsa_alt_context; #endif +#if !defined(MBEDTLS_PK_SINGLE_TYPE) #if defined(MBEDTLS_RSA_C) extern const mbedtls_pk_info_t mbedtls_rsa_info; #endif @@ -138,5 +279,6 @@ extern const mbedtls_pk_info_t mbedtls_uecc_eckey_info; #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; #endif +#endif /* MBEDTLS_PK_SINGLE_TYPE */ #endif /* MBEDTLS_PK_WRAP_H */ diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index a98a458c4..826581a38 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -382,9 +382,9 @@ struct mbedtls_ssl_sig_hash_set_t */ struct mbedtls_ssl_handshake_params { - /* - * Handshake specific crypto variables - */ +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + uint8_t got_peer_pubkey; /*!< Did we store the peer's public key from its certificate? */ +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned char verify_cookie_len; /*!< Cli: cookie length Srv: flag for sending a cookie */ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 98c7e979a..1da5a2e33 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -44,7 +44,6 @@ set(src_crypto padlock.c pem.c pk.c - pk_wrap.c pkcs12.c pkcs5.c pkparse.c diff --git a/library/Makefile b/library/Makefile index 062846b7b..341888afb 100644 --- a/library/Makefile +++ b/library/Makefile @@ -80,7 +80,7 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \ md4.o md5.o \ memory_buffer_alloc.o nist_kw.o \ oid.o padlock.o pem.o \ - pk.o pk_wrap.o pkcs12.o \ + pk.o pkcs12.o \ pkcs5.o pkparse.o pkwrite.o \ platform.o platform_util.o poly1305.o \ ripemd160.o rsa_internal.o rsa.o \ diff --git a/library/pk.c b/library/pk.c index 93c57642d..fb563d0cc 100644 --- a/library/pk.c +++ b/library/pk.c @@ -29,9 +29,7 @@ #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" -#include "mbedtls/platform_util.h" - -#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #include "mbedtls/rsa.h" #endif #if defined(MBEDTLS_ECP_C) @@ -40,7 +38,24 @@ #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif +#if defined(MBEDTLS_USE_TINYCRYPT) +#include "tinycrypt/ecc.h" +#include "tinycrypt/ecc_dsa.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#endif /* MBEDTLS_USE_TINYCRYPT */ +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include #include #include @@ -50,6 +65,1221 @@ #define PK_VALIDATE( cond ) \ MBEDTLS_INTERNAL_VALIDATE( cond ) +/* + * Internal wrappers around RSA functions + */ +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( 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 ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( 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 ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( 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 ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +/* + * Internal wrappers around ECC functions - based on ECP module + */ +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( 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 ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( 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 ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( 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 *rs_ctx ); + +static int ecdsa_sign_rs_wrap( 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 *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( 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 *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( 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 *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +/* + * Internal wrappers around ECC functions - based on TinyCrypt + */ +#if defined(MBEDTLS_USE_TINYCRYPT) +/* + * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of + * those integers and convert it to the fixed-length encoding. + */ +static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end, + unsigned char *to, size_t to_len ) +{ + int ret; + size_t unpadded_len, padding_len; + + if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len, + MBEDTLS_ASN1_INTEGER ) ) != 0 ) + { + return( ret ); + } + + while( unpadded_len > 0 && **from == 0x00 ) + { + ( *from )++; + unpadded_len--; + } + + if( unpadded_len > to_len || unpadded_len == 0 ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + padding_len = to_len - unpadded_len; + memset( to, 0x00, padding_len ); + memcpy( to + padding_len, *from, unpadded_len ); + ( *from ) += unpadded_len; + + return( 0 ); +} + +/* + * Convert a signature from an ASN.1 sequence of two integers + * to a raw {r,s} buffer. Note: the provided sig buffer must be at least + * twice as big as int_size. + */ +static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, + unsigned char *sig, size_t int_size ) +{ + int ret; + size_t tmp_size; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + /* Extract r */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 ) + return( ret ); + /* Extract s */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +static size_t uecc_eckey_get_bitlen( const void *ctx ) +{ + (void) ctx; + return( (size_t) ( NUM_ECC_BYTES * 8 ) ); +} + +static int uecc_eckey_check_pair( const void *pub, const void *prv ) +{ + const mbedtls_uecc_keypair *uecc_pub = + (const mbedtls_uecc_keypair *) pub; + const mbedtls_uecc_keypair *uecc_prv = + (const mbedtls_uecc_keypair *) prv; + + if( memcmp( uecc_pub->public_key, + uecc_prv->public_key, + 2 * NUM_ECC_BYTES ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +} + +static int uecc_eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA || + type == MBEDTLS_PK_ECKEY ); +} + +static int uecc_eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + uint8_t signature[2*NUM_ECC_BYTES]; + unsigned char *p; + const struct uECC_Curve_t * uecc_curve = uECC_secp256r1(); + const mbedtls_uecc_keypair *keypair = (const mbedtls_uecc_keypair *) ctx; + + ((void) md_alg); + p = (unsigned char*) sig; + + ret = extract_ecdsa_sig( &p, sig + sig_len, signature, NUM_ECC_BYTES ); + if( ret != 0 ) + return( ret ); + + ret = uECC_verify( keypair->public_key, hash, + (unsigned) hash_len, signature, uecc_curve ); + if( ret == 0 ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + return( 0 ); +} + +/* + * Simultaneously convert and move raw MPI from the beginning of a buffer + * to an ASN.1 MPI at the end of the buffer. + * See also mbedtls_asn1_write_mpi(). + * + * p: pointer to the end of the output buffer + * start: start of the output buffer, and also of the mpi to write at the end + * n_len: length of the mpi to read from start + * + * Warning: + * The total length of the output buffer must be smaller than 128 Bytes. + */ +static int asn1_write_mpibuf( unsigned char **p, unsigned char *start, + size_t n_len ) +{ + size_t len = 0; + + if( (size_t)( *p - start ) < n_len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = n_len; + *p -= len; + memmove( *p, start, len ); + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Neither r nor s should be 0, but as a failsafe measure, still detect + * that rather than overflowing the buffer in case of an error. */ + while( len > 0 && **p == 0x00 ) + { + ++(*p); + --len; + } + + /* this is only reached if the signature was invalid */ + if( len == 0 ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + /* if the msb is 1, ASN.1 requires that we prepend a 0. + * Neither r nor s can be 0, so we can assume len > 0 at all times. */ + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + /* The ASN.1 length encoding is just a single Byte containing the length, + * as we assume that the total buffer length is smaller than 128 Bytes. */ + *--(*p) = len; + *--(*p) = MBEDTLS_ASN1_INTEGER; + len += 2; + + return( (int) len ); +} + +/* Transcode signature from uECC format to ASN.1 sequence. + * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of + * MPIs, and in-place. + * + * [in/out] sig: the signature pre- and post-transcoding + * [in/out] sig_len: signature length pre- and post-transcoding + * [int] buf_len: the available size the in/out buffer + * + * Warning: buf_len must be smaller than 128 Bytes. + */ +static int pk_ecdsa_sig_asn1_from_uecc( unsigned char *sig, size_t *sig_len, + size_t buf_len ) +{ + int ret; + size_t len = 0; + const size_t rs_len = *sig_len / 2; + unsigned char *p = sig + buf_len; + + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) ); + + /* The ASN.1 length encoding is just a single Byte containing the length, + * as we assume that the total buffer length is smaller than 128 Bytes. */ + *--p = len; + *--p = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE; + len += 2; + + memmove( sig, p, len ); + *sig_len = len; + + return( 0 ); +} + +static int uecc_eckey_sign_wrap( 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 ) +{ + const mbedtls_uecc_keypair *keypair = (const mbedtls_uecc_keypair *) ctx; + const struct uECC_Curve_t * uecc_curve = uECC_secp256r1(); + int ret; + + /* + * RFC-4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + NUM_ECC_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * + * (The ASN.1 length encodings are all 1-Byte encodings because + * the total size is smaller than 128 Bytes). + */ + #define MAX_SECP256R1_ECDSA_SIG_LEN ( 3 + 2 * ( 3 + NUM_ECC_BYTES ) ) + + ret = uECC_sign( keypair->private_key, hash, hash_len, sig, uecc_curve ); + /* TinyCrypt uses 0 to signal errors. */ + if( ret == 0 ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + *sig_len = 2 * NUM_ECC_BYTES; + + /* uECC owns its rng function pointer */ + (void) f_rng; + (void) p_rng; + (void) md_alg; + + return( pk_ecdsa_sig_asn1_from_uecc( sig, sig_len, + MAX_SECP256R1_ECDSA_SIG_LEN ) ); + + #undef MAX_SECP256R1_ECDSA_SIG_LEN +} + +#if !defined(MBEDTLS_PK_SINGLE_TYPE) +static void *uecc_eckey_alloc_wrap( void ) +{ + return( mbedtls_calloc( 1, sizeof( mbedtls_uecc_keypair ) ) ); +} + +static void uecc_eckey_free_wrap( void *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_uecc_keypair ) ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_PK_SINGLE_TYPE */ + +#if !defined(MBEDTLS_PK_SINGLE_TYPE) +const mbedtls_pk_info_t mbedtls_uecc_eckey_info = + MBEDTLS_PK_INFO( MBEDTLS_PK_INFO_ECKEY ); +#endif +#endif /* MBEDTLS_USE_TINYCRYPT */ + +/* + * Internal wrappers around ECDSA functions + */ +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( 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 ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( 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 *rs_ctx ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( 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 *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Internal wrappers for RSA-alt support + */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( 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 ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( 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 ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, +}; +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * 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 + * when hardcoding a single PK - some compilers optimize better that way. + * + * Not implemented for members that are only present in builds with + * MBEDTLS_ECP_RESTARTABLE for now, as the main target for this 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( + mbedtls_pk_handle_t info ) +{ + (void) info; + return( MBEDTLS_PK_INFO_TYPE( MBEDTLS_PK_SINGLE_TYPE ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline const char * pk_info_name( + mbedtls_pk_handle_t info ) +{ + (void) info; + return( MBEDTLS_PK_INFO_NAME( MBEDTLS_PK_SINGLE_TYPE ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline size_t pk_info_get_bitlen( + mbedtls_pk_handle_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( + mbedtls_pk_handle_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( + mbedtls_pk_handle_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( + mbedtls_pk_handle_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( + mbedtls_pk_handle_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( + mbedtls_pk_handle_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( + mbedtls_pk_handle_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 int pk_info_debug_func( + mbedtls_pk_handle_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( + mbedtls_pk_handle_t info ) +{ + return( info->type ); +} + +MBEDTLS_ALWAYS_INLINE static inline const char * pk_info_name( + mbedtls_pk_handle_t info ) +{ + return( info->name ); +} + +MBEDTLS_ALWAYS_INLINE static inline size_t pk_info_get_bitlen( + mbedtls_pk_handle_t info, const void *ctx ) +{ + return( info->get_bitlen( ctx ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_can_do( + mbedtls_pk_handle_t info, mbedtls_pk_type_t type ) +{ + return( info->can_do( type ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_verify_func( + mbedtls_pk_handle_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 ) +{ + if( info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( info->verify_func( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_sign_func( + mbedtls_pk_handle_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 ) +{ + if( info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( info->sign_func( ctx, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_decrypt_func( + mbedtls_pk_handle_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 ) +{ + if( info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( info->decrypt_func( ctx, input, ilen, output, olen, osize, + f_rng, p_rng ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_encrypt_func( + mbedtls_pk_handle_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 ) +{ + if( info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( info->encrypt_func( ctx, input, ilen, output, olen, osize, + f_rng, p_rng ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_check_pair_func( + mbedtls_pk_handle_t info, const void *pub, const void *prv ) +{ + if( info->check_pair_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( info->check_pair_func( pub, prv ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline void *pk_info_ctx_alloc_func( + mbedtls_pk_handle_t info ) +{ + return( info->ctx_alloc_func( ) ); +} + +MBEDTLS_ALWAYS_INLINE static inline void pk_info_ctx_free_func( + mbedtls_pk_handle_t info, void *ctx ) +{ + info->ctx_free_func( ctx ); +} + +MBEDTLS_ALWAYS_INLINE static inline int pk_info_debug_func( + mbedtls_pk_handle_t info, + const void *ctx, mbedtls_pk_debug_item *items ) +{ + if( info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + info->debug_func( ctx, items ); + return( 0 ); +} + +#endif /* MBEDTLS_PK_SINGLE_TYPE */ + /* * Initialise a mbedtls_pk_context */ @@ -57,8 +1287,12 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx ) { PK_VALIDATE( ctx != NULL ); - ctx->pk_info = NULL; +#if !defined(MBEDTLS_PK_SINGLE_TYPE) + ctx->pk_info = MBEDTLS_PK_INVALID_HANDLE; ctx->pk_ctx = NULL; +#else + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +#endif } /* @@ -69,8 +1303,10 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx ) if( ctx == NULL ) return; - if ( ctx->pk_info != NULL ) - ctx->pk_info->ctx_free_func( ctx->pk_ctx ); +#if !defined(MBEDTLS_PK_SINGLE_TYPE) + if( MBEDTLS_PK_CTX_IS_VALID( ctx ) ) + pk_info_ctx_free_func( MBEDTLS_PK_CTX_INFO( ctx ), ctx->pk_ctx ); +#endif mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } @@ -91,7 +1327,7 @@ void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) */ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) { - if( ctx == NULL || ctx->pk_info == NULL || + if( ctx == NULL || !MBEDTLS_PK_CTX_IS_VALID( ctx ) || ctx->pk_info->rs_free_func == NULL ) { return; @@ -99,7 +1335,7 @@ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) ctx->pk_info->rs_free_func( ctx->rs_ctx ); - ctx->pk_info = NULL; + ctx->pk_info = MBEDTLS_PK_INVALID_HANDLE; ctx->rs_ctx = NULL; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ @@ -107,8 +1343,16 @@ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) /* * Get pk_info structure from type */ -const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +mbedtls_pk_handle_t mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) { +#if defined(MBEDTLS_PK_SINGLE_TYPE) + if( pk_type == MBEDTLS_PK_INFO_TYPE( MBEDTLS_PK_SINGLE_TYPE ) ) + return( MBEDTLS_PK_UNIQUE_VALID_HANDLE ); + + return( MBEDTLS_PK_INVALID_HANDLE ); + +#else /* MBEDTLS_PK_SINGLE_TYPE */ + switch( pk_type ) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: @@ -135,22 +1379,30 @@ const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) default: return( NULL ); } +#endif /* MBEDTLS_PK_SINGLE_TYPE */ } /* * Initialise context */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +int mbedtls_pk_setup( mbedtls_pk_context *ctx, mbedtls_pk_handle_t info ) { PK_VALIDATE_RET( ctx != NULL ); - if( info == NULL || ctx->pk_info != NULL ) + if( info == MBEDTLS_PK_INVALID_HANDLE ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); +#if !defined(MBEDTLS_PK_SINGLE_TYPE) + if( ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); ctx->pk_info = info; + if( ( ctx->pk_ctx = pk_info_ctx_alloc_func( info ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); +#else + (void) ctx; +#endif + return( 0 ); } @@ -164,10 +1416,10 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, mbedtls_pk_rsa_alt_key_len_func key_len_func ) { mbedtls_rsa_alt_context *rsa_alt; - const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + mbedtls_pk_handle_t info = &mbedtls_rsa_alt_info; PK_VALIDATE_RET( ctx != NULL ); - if( ctx->pk_info != NULL ) + if( MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) @@ -194,10 +1446,10 @@ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) /* A context with null pk_info is not set up yet and can't do anything. * For backward compatibility, also accept NULL instead of a context * pointer. */ - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL || !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( 0 ); - return( ctx->pk_info->can_do( type ) ); + return( pk_info_can_do( MBEDTLS_PK_CTX_INFO( ctx ), type ) ); } /* @@ -225,10 +1477,10 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len * Helper to set up a restart context if needed */ static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, - const mbedtls_pk_info_t *info ) + mbedtls_pk_handle_t info ) { /* Don't do anything if already set up or invalid */ - if( ctx == NULL || ctx->pk_info != NULL ) + if( ctx == NULL || MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( 0 ); /* Should never happen when we're called */ @@ -258,7 +1510,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, hash != NULL ); PK_VALIDATE_RET( sig != NULL ); - if( ctx->pk_info == NULL || + if( !MBEDTLS_PK_CTX_IS_VALID( ctx ) || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -285,11 +1537,8 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, (void) rs_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - if( ctx->pk_info->verify_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len ) ); + return( pk_info_verify_func( MBEDTLS_PK_CTX_INFO( ctx ), + ctx->pk_ctx, md_alg, hash, hash_len, sig, sig_len ) ); } /* @@ -316,7 +1565,7 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, hash != NULL ); PK_VALIDATE_RET( sig != NULL ); - if( ctx->pk_info == NULL ) + if( !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ! mbedtls_pk_can_do( ctx, type ) ) @@ -381,7 +1630,7 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, hash != NULL ); PK_VALIDATE_RET( sig != NULL ); - if( ctx->pk_info == NULL || + if( !MBEDTLS_PK_CTX_IS_VALID( ctx ) || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -408,11 +1657,8 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, (void) rs_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - if( ctx->pk_info->sign_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng ) ); + return( pk_info_sign_func( MBEDTLS_PK_CTX_INFO( ctx ), ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); } /* @@ -440,14 +1686,11 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, PK_VALIDATE_RET( output != NULL || osize == 0 ); PK_VALIDATE_RET( olen != NULL ); - if( ctx->pk_info == NULL ) + if( !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - if( ctx->pk_info->decrypt_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, - output, olen, osize, f_rng, p_rng ) ); + return( pk_info_decrypt_func( MBEDTLS_PK_CTX_INFO( ctx ), ctx->pk_ctx, + input, ilen, output, olen, osize, f_rng, p_rng ) ); } /* @@ -463,14 +1706,11 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, PK_VALIDATE_RET( output != NULL || osize == 0 ); PK_VALIDATE_RET( olen != NULL ); - if( ctx->pk_info == NULL ) + if( !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - if( ctx->pk_info->encrypt_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, - output, olen, osize, f_rng, p_rng ) ); + return( pk_info_encrypt_func( MBEDTLS_PK_CTX_INFO( ctx ), ctx->pk_ctx, + input, ilen, output, olen, osize, f_rng, p_rng ) ); } /* @@ -481,25 +1721,24 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte PK_VALIDATE_RET( pub != NULL ); PK_VALIDATE_RET( prv != NULL ); - if( pub->pk_info == NULL || - prv->pk_info == NULL || - prv->pk_info->check_pair_func == NULL ) - { + if( !MBEDTLS_PK_CTX_IS_VALID( pub ) || !MBEDTLS_PK_CTX_IS_VALID( prv ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - } - if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + if( pk_info_type( prv->pk_info ) == MBEDTLS_PK_RSA_ALT ) { - if( pub->pk_info->type != MBEDTLS_PK_RSA ) + if( pk_info_type( pub->pk_info ) != MBEDTLS_PK_RSA ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); } else +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ { - if( pub->pk_info != prv->pk_info ) + if( MBEDTLS_PK_CTX_INFO( pub ) != MBEDTLS_PK_CTX_INFO( prv ) ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); } - return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); + return( pk_info_check_pair_func( MBEDTLS_PK_CTX_INFO( prv ), + pub->pk_ctx, prv->pk_ctx ) ); } /* @@ -509,10 +1748,10 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) { /* For backward compatibility, accept NULL or a context that * isn't set up yet, and return a fake value that should be safe. */ - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL || !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( 0 ); - return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); + return( pk_info_get_bitlen( MBEDTLS_PK_CTX_INFO( ctx ), ctx->pk_ctx ) ); } /* @@ -521,14 +1760,10 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) { PK_VALIDATE_RET( ctx != NULL ); - if( ctx->pk_info == NULL ) + if( !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - if( ctx->pk_info->debug_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - ctx->pk_info->debug_func( ctx->pk_ctx, items ); - return( 0 ); + return( pk_info_debug_func( MBEDTLS_PK_CTX_INFO( ctx ), ctx->pk_ctx, items ) ); } /* @@ -536,10 +1771,10 @@ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *item */ const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) { - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL || !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( "invalid PK" ); - return( ctx->pk_info->name ); + return( pk_info_name( MBEDTLS_PK_CTX_INFO( ctx ) ) ); } /* @@ -547,10 +1782,10 @@ const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) */ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) { - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL || !MBEDTLS_PK_CTX_IS_VALID( ctx ) ) return( MBEDTLS_PK_NONE ); - return( ctx->pk_info->type ); + return( pk_info_type( MBEDTLS_PK_CTX_INFO( ctx ) ) ); } #endif /* MBEDTLS_PK_C */ diff --git a/library/pk_wrap.c b/library/pk_wrap.c deleted file mode 100644 index 2bcc947f7..000000000 --- a/library/pk_wrap.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Public Key abstraction layer: wrapper functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk_internal.h" - -/* Even if RSA not activated, for the sake of RSA-alt */ -#include "mbedtls/rsa.h" - -#include - -#if defined(MBEDTLS_USE_TINYCRYPT) -#include "tinycrypt/ecc.h" -#include "tinycrypt/ecc_dsa.h" -#include "mbedtls/asn1.h" -#include "mbedtls/asn1write.h" -#endif /* MBEDTLS_USE_TINYCRYPT */ - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) || \ - defined(MBEDTLS_USE_TINYCRYPT) -#include "mbedtls/platform_util.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include -#include - -#if defined(MBEDTLS_RSA_C) -static int rsa_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_RSA || - type == MBEDTLS_PK_RSASSA_PSS ); -} - -static size_t rsa_get_bitlen( const void *ctx ) -{ - const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; - return( 8 * mbedtls_rsa_get_len( rsa ) ); -} - -static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - size_t rsa_len = mbedtls_rsa_get_len( rsa ); - -#if SIZE_MAX > UINT_MAX - if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* SIZE_MAX > UINT_MAX */ - - if( sig_len < rsa_len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, - MBEDTLS_RSA_PUBLIC, md_alg, - (unsigned int) hash_len, hash, sig ) ) != 0 ) - return( ret ); - - /* The buffer contains a valid signature followed by extra data. - * We have a special error code for that so that so that callers can - * use mbedtls_pk_verify() to check "Does the buffer start with a - * valid signature?" and not just "Does the buffer contain a valid - * signature?". */ - if( sig_len > rsa_len ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( 0 ); -} - -static int rsa_sign_wrap( 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 ) -{ - mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - -#if SIZE_MAX > UINT_MAX - if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* SIZE_MAX > UINT_MAX */ - - *sig_len = mbedtls_rsa_get_len( rsa ); - - return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - md_alg, (unsigned int) hash_len, hash, sig ) ); -} - -static int rsa_decrypt_wrap( 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 ) -{ - mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - - if( ilen != mbedtls_rsa_get_len( rsa ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, - MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); -} - -static int rsa_encrypt_wrap( 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 ) -{ - mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - *olen = mbedtls_rsa_get_len( rsa ); - - if( *olen > osize ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - - return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, - ilen, input, output ) ); -} - -static int rsa_check_pair_wrap( const void *pub, const void *prv ) -{ - return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, - (const mbedtls_rsa_context *) prv ) ); -} - -static void *rsa_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); - - if( ctx != NULL ) - mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); - - return( ctx ); -} - -static void rsa_free_wrap( void *ctx ) -{ - mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); - mbedtls_free( ctx ); -} - -static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) -{ - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.N"; - items->value = &( ((mbedtls_rsa_context *) ctx)->N ); - - items++; - - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.E"; - items->value = &( ((mbedtls_rsa_context *) ctx)->E ); -} - -const mbedtls_pk_info_t mbedtls_rsa_info = { - MBEDTLS_PK_RSA, - "RSA", - rsa_get_bitlen, - rsa_can_do, - rsa_verify_wrap, - rsa_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_decrypt_wrap, - rsa_encrypt_wrap, - rsa_check_pair_wrap, - rsa_alloc_wrap, - rsa_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_debug, -}; -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * Generic EC key - */ -static int eckey_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECKEY_DH || - type == MBEDTLS_PK_ECDSA ); -} - -static size_t eckey_get_bitlen( const void *ctx ) -{ - return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); -} - -#if defined(MBEDTLS_ECDSA_C) -/* Forward declarations */ -static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - -static int ecdsa_sign_wrap( 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 ); - -static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - mbedtls_ecdsa_context ecdsa; - - mbedtls_ecdsa_init( &ecdsa ); - - if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) - ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); - - mbedtls_ecdsa_free( &ecdsa ); - - return( ret ); -} - -static int eckey_sign_wrap( 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 ) -{ - int ret; - mbedtls_ecdsa_context ecdsa; - - mbedtls_ecdsa_init( &ecdsa ); - - if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) - ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, - f_rng, p_rng ); - - mbedtls_ecdsa_free( &ecdsa ); - - return( ret ); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -/* Forward declarations */ -static int ecdsa_verify_rs_wrap( 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 *rs_ctx ); - -static int ecdsa_sign_rs_wrap( 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 *rs_ctx ); - -/* - * Restart context for ECDSA operations with ECKEY context - * - * We need to store an actual ECDSA context, as we need to pass the same to - * the underlying ecdsa function, so we can't create it on the fly every time. - */ -typedef struct -{ - mbedtls_ecdsa_restart_ctx ecdsa_rs; - mbedtls_ecdsa_context ecdsa_ctx; -} eckey_restart_ctx; - -static void *eckey_rs_alloc( void ) -{ - eckey_restart_ctx *rs_ctx; - - void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); - - if( ctx != NULL ) - { - rs_ctx = ctx; - mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); - mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); - } - - return( ctx ); -} - -static void eckey_rs_free( void *ctx ) -{ - eckey_restart_ctx *rs_ctx; - - if( ctx == NULL) - return; - - rs_ctx = ctx; - mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); - mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); - - mbedtls_free( ctx ); -} - -static int eckey_verify_rs_wrap( 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 *rs_ctx ) -{ - int ret; - eckey_restart_ctx *rs = rs_ctx; - - /* Should never happen */ - if( rs == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - /* set up our own sub-context if needed (that is, on first run) */ - if( rs->ecdsa_ctx.grp.pbits == 0 ) - MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); - - MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, - md_alg, hash, hash_len, - sig, sig_len, &rs->ecdsa_rs ) ); - -cleanup: - return( ret ); -} - -static int eckey_sign_rs_wrap( 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 *rs_ctx ) -{ - int ret; - eckey_restart_ctx *rs = rs_ctx; - - /* Should never happen */ - if( rs == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - /* set up our own sub-context if needed (that is, on first run) */ - if( rs->ecdsa_ctx.grp.pbits == 0 ) - MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); - - MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, - hash, hash_len, sig, sig_len, - f_rng, p_rng, &rs->ecdsa_rs ) ); - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ -#endif /* MBEDTLS_ECDSA_C */ - -static int eckey_check_pair( const void *pub, const void *prv ) -{ - return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, - (const mbedtls_ecp_keypair *) prv ) ); -} - -static void *eckey_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); - - if( ctx != NULL ) - mbedtls_ecp_keypair_init( ctx ); - - return( ctx ); -} - -static void eckey_free_wrap( void *ctx ) -{ - mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); - mbedtls_free( ctx ); -} - -static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) -{ - items->type = MBEDTLS_PK_DEBUG_ECP; - items->name = "eckey.Q"; - items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); -} - -const mbedtls_pk_info_t mbedtls_eckey_info = { - MBEDTLS_PK_ECKEY, - "EC", - eckey_get_bitlen, - eckey_can_do, -#if defined(MBEDTLS_ECDSA_C) - eckey_verify_wrap, - eckey_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - eckey_verify_rs_wrap, - eckey_sign_rs_wrap, -#endif -#else /* MBEDTLS_ECDSA_C */ - NULL, - NULL, -#endif /* MBEDTLS_ECDSA_C */ - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, - eckey_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - eckey_rs_alloc, - eckey_rs_free, -#endif - eckey_debug, -}; - -/* - * EC key restricted to ECDH - */ -static int eckeydh_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECKEY_DH ); -} - -const mbedtls_pk_info_t mbedtls_eckeydh_info = { - MBEDTLS_PK_ECKEY_DH, - "EC_DH", - eckey_get_bitlen, /* Same underlying key structure */ - eckeydh_can_do, - NULL, - NULL, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, /* Same underlying key structure */ - eckey_free_wrap, /* Same underlying key structure */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - eckey_debug, /* Same underlying key structure */ -}; -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_USE_TINYCRYPT) - -/* - * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of - * those integers and convert it to the fixed-length encoding. - */ -static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end, - unsigned char *to, size_t to_len ) -{ - int ret; - size_t unpadded_len, padding_len; - - if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len, - MBEDTLS_ASN1_INTEGER ) ) != 0 ) - { - return( ret ); - } - - while( unpadded_len > 0 && **from == 0x00 ) - { - ( *from )++; - unpadded_len--; - } - - if( unpadded_len > to_len || unpadded_len == 0 ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - padding_len = to_len - unpadded_len; - memset( to, 0x00, padding_len ); - memcpy( to + padding_len, *from, unpadded_len ); - ( *from ) += unpadded_len; - - return( 0 ); -} - -/* - * Convert a signature from an ASN.1 sequence of two integers - * to a raw {r,s} buffer. Note: the provided sig buffer must be at least - * twice as big as int_size. - */ -static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, - unsigned char *sig, size_t int_size ) -{ - int ret; - size_t tmp_size; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - /* Extract r */ - if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 ) - return( ret ); - /* Extract s */ - if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -static size_t uecc_eckey_get_bitlen( const void *ctx ) -{ - (void) ctx; - return( (size_t) ( NUM_ECC_BYTES * 8 ) ); -} - -static int uecc_eckey_check_pair( const void *pub, const void *prv ) -{ - const mbedtls_uecc_keypair *uecc_pub = - (const mbedtls_uecc_keypair *) pub; - const mbedtls_uecc_keypair *uecc_prv = - (const mbedtls_uecc_keypair *) prv; - - if( memcmp( uecc_pub->public_key, - uecc_prv->public_key, - 2 * NUM_ECC_BYTES ) == 0 ) - { - return( 0 ); - } - - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -} - -static int uecc_eckey_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECDSA || - type == MBEDTLS_PK_ECKEY ); -} - -static int uecc_eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - uint8_t signature[2*NUM_ECC_BYTES]; - unsigned char *p; - const struct uECC_Curve_t * uecc_curve = uECC_secp256r1(); - const mbedtls_uecc_keypair *keypair = (const mbedtls_uecc_keypair *) ctx; - - ((void) md_alg); - p = (unsigned char*) sig; - - ret = extract_ecdsa_sig( &p, sig + sig_len, signature, NUM_ECC_BYTES ); - if( ret != 0 ) - return( ret ); - - ret = uECC_verify( keypair->public_key, hash, - (unsigned) hash_len, signature, uecc_curve ); - if( ret == 0 ) - return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); - - return( 0 ); -} - -/* - * Simultaneously convert and move raw MPI from the beginning of a buffer - * to an ASN.1 MPI at the end of the buffer. - * See also mbedtls_asn1_write_mpi(). - * - * p: pointer to the end of the output buffer - * start: start of the output buffer, and also of the mpi to write at the end - * n_len: length of the mpi to read from start - * - * Warning: - * The total length of the output buffer must be smaller than 128 Bytes. - */ -static int asn1_write_mpibuf( unsigned char **p, unsigned char *start, - size_t n_len ) -{ - size_t len = 0; - - if( (size_t)( *p - start ) < n_len ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = n_len; - *p -= len; - memmove( *p, start, len ); - - /* ASN.1 DER encoding requires minimal length, so skip leading 0s. - * Neither r nor s should be 0, but as a failsafe measure, still detect - * that rather than overflowing the buffer in case of an error. */ - while( len > 0 && **p == 0x00 ) - { - ++(*p); - --len; - } - - /* this is only reached if the signature was invalid */ - if( len == 0 ) - return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); - - /* if the msb is 1, ASN.1 requires that we prepend a 0. - * Neither r nor s can be 0, so we can assume len > 0 at all times. */ - if( **p & 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - /* The ASN.1 length encoding is just a single Byte containing the length, - * as we assume that the total buffer length is smaller than 128 Bytes. */ - *--(*p) = len; - *--(*p) = MBEDTLS_ASN1_INTEGER; - len += 2; - - return( (int) len ); -} - -/* Transcode signature from uECC format to ASN.1 sequence. - * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of - * MPIs, and in-place. - * - * [in/out] sig: the signature pre- and post-transcoding - * [in/out] sig_len: signature length pre- and post-transcoding - * [int] buf_len: the available size the in/out buffer - * - * Warning: buf_len must be smaller than 128 Bytes. - */ -static int pk_ecdsa_sig_asn1_from_uecc( unsigned char *sig, size_t *sig_len, - size_t buf_len ) -{ - int ret; - size_t len = 0; - const size_t rs_len = *sig_len / 2; - unsigned char *p = sig + buf_len; - - MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) ); - - /* The ASN.1 length encoding is just a single Byte containing the length, - * as we assume that the total buffer length is smaller than 128 Bytes. */ - *--p = len; - *--p = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE; - len += 2; - - memmove( sig, p, len ); - *sig_len = len; - - return( 0 ); -} - -static int uecc_eckey_sign_wrap( 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 ) -{ - const mbedtls_uecc_keypair *keypair = (const mbedtls_uecc_keypair *) ctx; - const struct uECC_Curve_t * uecc_curve = uECC_secp256r1(); - int ret; - - /* - * RFC-4492 page 20: - * - * Ecdsa-Sig-Value ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * Size is at most - * 1 (tag) + 1 (len) + 1 (initial 0) + NUM_ECC_BYTES for each of r and s, - * twice that + 1 (tag) + 2 (len) for the sequence - * - * (The ASN.1 length encodings are all 1-Byte encodings because - * the total size is smaller than 128 Bytes). - */ - #define MAX_SECP256R1_ECDSA_SIG_LEN ( 3 + 2 * ( 3 + NUM_ECC_BYTES ) ) - - ret = uECC_sign( keypair->private_key, hash, hash_len, sig, uecc_curve ); - /* TinyCrypt uses 0 to signal errors. */ - if( ret == 0 ) - return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); - - *sig_len = 2 * NUM_ECC_BYTES; - - /* uECC owns its rng function pointer */ - (void) f_rng; - (void) p_rng; - (void) md_alg; - - return( pk_ecdsa_sig_asn1_from_uecc( sig, sig_len, - MAX_SECP256R1_ECDSA_SIG_LEN ) ); - - #undef MAX_SECP256R1_ECDSA_SIG_LEN -} - -static void *uecc_eckey_alloc_wrap( void ) -{ - return( mbedtls_calloc( 1, sizeof( mbedtls_uecc_keypair ) ) ); -} - -static void uecc_eckey_free_wrap( void *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_uecc_keypair ) ); - mbedtls_free( ctx ); -} - -const mbedtls_pk_info_t mbedtls_uecc_eckey_info = { - MBEDTLS_PK_ECKEY, - "EC", - uecc_eckey_get_bitlen, - uecc_eckey_can_do, - uecc_eckey_verify_wrap, - uecc_eckey_sign_wrap, - NULL, - NULL, - uecc_eckey_check_pair, - uecc_eckey_alloc_wrap, - uecc_eckey_free_wrap, - NULL, -}; -#endif /* MBEDTLS_USE_TINYCRYPT */ - -#if defined(MBEDTLS_ECDSA_C) -static int ecdsa_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECDSA ); -} - -static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - ((void) md_alg); - - ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, - hash, hash_len, sig, sig_len ); - - if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( ret ); -} - -static int ecdsa_sign_wrap( 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 ) -{ - return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, - md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -static int ecdsa_verify_rs_wrap( 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 *rs_ctx ) -{ - int ret; - ((void) md_alg); - - ret = mbedtls_ecdsa_read_signature_restartable( - (mbedtls_ecdsa_context *) ctx, - hash, hash_len, sig, sig_len, - (mbedtls_ecdsa_restart_ctx *) rs_ctx ); - - if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( ret ); -} - -static int ecdsa_sign_rs_wrap( 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 *rs_ctx ) -{ - return( mbedtls_ecdsa_write_signature_restartable( - (mbedtls_ecdsa_context *) ctx, - md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, - (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); - -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ - -static void *ecdsa_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); - - if( ctx != NULL ) - mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); - - return( ctx ); -} - -static void ecdsa_free_wrap( void *ctx ) -{ - mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); - mbedtls_free( ctx ); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -static void *ecdsa_rs_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); - - if( ctx != NULL ) - mbedtls_ecdsa_restart_init( ctx ); - - return( ctx ); -} - -static void ecdsa_rs_free( void *ctx ) -{ - mbedtls_ecdsa_restart_free( ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ - -const mbedtls_pk_info_t mbedtls_ecdsa_info = { - MBEDTLS_PK_ECDSA, - "ECDSA", - eckey_get_bitlen, /* Compatible key structures */ - ecdsa_can_do, - ecdsa_verify_wrap, - ecdsa_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - ecdsa_verify_rs_wrap, - ecdsa_sign_rs_wrap, -#endif - NULL, - NULL, - eckey_check_pair, /* Compatible key structures */ - ecdsa_alloc_wrap, - ecdsa_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - ecdsa_rs_alloc, - ecdsa_rs_free, -#endif - eckey_debug, /* Compatible key structures */ -}; -#endif /* MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Support for alternative RSA-private implementations - */ - -static int rsa_alt_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_RSA ); -} - -static size_t rsa_alt_get_bitlen( const void *ctx ) -{ - const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; - - return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); -} - -static int rsa_alt_sign_wrap( 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 ) -{ - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; - -#if SIZE_MAX > UINT_MAX - if( UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* SIZE_MAX > UINT_MAX */ - - *sig_len = rsa_alt->key_len_func( rsa_alt->key ); - - return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - md_alg, (unsigned int) hash_len, hash, sig ) ); -} - -static int rsa_alt_decrypt_wrap( 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 ) -{ - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; - - ((void) f_rng); - ((void) p_rng); - - if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - return( rsa_alt->decrypt_func( rsa_alt->key, - MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); -} - -#if defined(MBEDTLS_RSA_C) -static int rsa_alt_check_pair( const void *pub, const void *prv ) -{ - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char hash[32]; - size_t sig_len = 0; - int ret; - - if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - memset( hash, 0x2a, sizeof( hash ) ); - - if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, - hash, sizeof( hash ), - sig, &sig_len, NULL, NULL ) ) != 0 ) - { - return( ret ); - } - - if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, - hash, sizeof( hash ), sig, sig_len ) != 0 ) - { - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - } - - return( 0 ); -} -#endif /* MBEDTLS_RSA_C */ - -static void *rsa_alt_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); - - if( ctx != NULL ) - memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); - - return( ctx ); -} - -static void rsa_alt_free_wrap( void *ctx ) -{ - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); - mbedtls_free( ctx ); -} - -const mbedtls_pk_info_t mbedtls_rsa_alt_info = { - MBEDTLS_PK_RSA_ALT, - "RSA-alt", - rsa_alt_get_bitlen, - rsa_alt_can_do, - NULL, - rsa_alt_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_alt_decrypt_wrap, - NULL, -#if defined(MBEDTLS_RSA_C) - rsa_alt_check_pair, -#else - NULL, -#endif - rsa_alt_alloc_wrap, - rsa_alt_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, -}; - -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -#endif /* MBEDTLS_PK_C */ diff --git a/library/pkparse.c b/library/pkparse.c index 1a73101f9..4cff8d7e2 100644 --- a/library/pkparse.c +++ b/library/pkparse.c @@ -687,7 +687,7 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, size_t len; mbedtls_asn1_buf alg_params; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; + mbedtls_pk_handle_t pk_info; PK_VALIDATE_RET( p != NULL ); PK_VALIDATE_RET( *p != NULL ); @@ -712,7 +712,7 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, return( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == MBEDTLS_PK_INVALID_HANDLE ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) @@ -1150,7 +1150,7 @@ static int pk_parse_key_pkcs8_unencrypted_der( unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; + mbedtls_pk_handle_t pk_info; /* * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) @@ -1192,7 +1192,7 @@ static int pk_parse_key_pkcs8_unencrypted_der( return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == MBEDTLS_PK_INVALID_HANDLE ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) @@ -1374,7 +1374,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, defined(MBEDTLS_PEM_PARSE_C) int ret; #endif - const mbedtls_pk_info_t *pk_info; + mbedtls_pk_handle_t pk_info; #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; @@ -1604,7 +1604,7 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, int ret; unsigned char *p; #if defined(MBEDTLS_RSA_C) - const mbedtls_pk_info_t *pk_info; + mbedtls_pk_handle_t pk_info; #endif #if defined(MBEDTLS_PEM_PARSE_C) size_t len; @@ -1631,7 +1631,7 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, if( ret == 0 ) { p = pem.buf; - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == MBEDTLS_PK_INVALID_HANDLE ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) @@ -1679,7 +1679,7 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_RSA_C) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == MBEDTLS_PK_INVALID_HANDLE ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) diff --git a/library/pkwrite.c b/library/pkwrite.c index c8d92300d..f6ff89b77 100644 --- a/library/pkwrite.c +++ b/library/pkwrite.c @@ -543,9 +543,19 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ #else /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_USE_TINYCRYPT) + +/* see above, replacing ECP_MAX_BYTES with 32 (256-bit) */ +#define ECP_PUB_DER_MAX_BYTES 30 + 2 * 32 +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * 32 + +#else /* MBEDTLS_USE_TINYCRYPT */ + #define ECP_PUB_DER_MAX_BYTES 0 #define ECP_PRV_DER_MAX_BYTES 0 +#endif /* MBEDTLS_USE_TINYCRYPT */ + #endif /* MBEDTLS_ECP_C */ #define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 0a1322ab0..ebc2a6359 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2379,11 +2379,7 @@ static int ssl_rsa_encrypt_partial_pms( mbedtls_ssl_context *ssl, } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* Because the peer CRT pubkey is embedded into the handshake - * params currently, and there's no 'is_init' functions for PK - * contexts, we need to break the abstraction and peek into - * the PK context to see if it has been initialized. */ - if( ssl->handshake->peer_pubkey.pk_info != NULL ) + if( ssl->handshake->got_peer_pubkey ) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if( ssl->session_negotiate->peer_cert != NULL ) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 69af31727..747b9f45f 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -4454,15 +4454,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) /* Skip if we haven't received a certificate from the client. * If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is set, this can be * inferred from the setting of mbedtls_ssl_session::peer_cert. - * If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is not set, it can - * be inferred from whether we've held back the peer CRT's - * public key in mbedtls_ssl_handshake_params::peer_pubkey. */ + * If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is not set, it is tracked in a + * specific variable. */ #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* Because the peer CRT pubkey is embedded into the handshake - * params currently, and there's no 'is_init' functions for PK - * contexts, we need to break the abstraction and peek into - * the PK context to see if it has been initialized. */ - if( ssl->handshake->peer_pubkey.pk_info != NULL ) + if( ssl->handshake->got_peer_pubkey ) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if( ssl->session_negotiate->peer_cert != NULL ) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 850bcb172..981009051 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -7357,6 +7357,7 @@ static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } + ssl->handshake->got_peer_pubkey = 1; return( 0 ); } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c index 60964292b..16dd1b6a2 100644 --- a/programs/pkey/key_app_writer.c +++ b/programs/pkey/key_app_writer.c @@ -39,6 +39,7 @@ #if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) #include "mbedtls/error.h" #include "mbedtls/pk.h" +#include "mbedtls/bignum.h" #include "mbedtls/error.h" #include diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c index bdedca4c9..ba4f779c8 100644 --- a/programs/pkey/pk_sign.c +++ b/programs/pkey/pk_sign.c @@ -56,6 +56,7 @@ int main( void ) #include "mbedtls/ctr_drbg.h" #include "mbedtls/md.h" #include "mbedtls/pk.h" +#include "mbedtls/bignum.h" #include #include diff --git a/programs/pkey/pk_verify.c b/programs/pkey/pk_verify.c index a6bfe3f29..f80bf640e 100644 --- a/programs/pkey/pk_verify.c +++ b/programs/pkey/pk_verify.c @@ -52,6 +52,7 @@ int main( void ) #include "mbedtls/error.h" #include "mbedtls/md.h" #include "mbedtls/pk.h" +#include "mbedtls/bignum.h" #include #include diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index 71a212d0c..0c2692179 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -2922,6 +2922,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_MD_SINGLE_HASH */ +#if defined(MBEDTLS_PK_SINGLE_TYPE) + if( strcmp( "MBEDTLS_PK_SINGLE_TYPE", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PK_SINGLE_TYPE ); + return( 0 ); + } +#endif /* MBEDTLS_PK_SINGLE_TYPE */ + /* If the symbol is not found, return an error */ return( 1 ); } diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 69f97c7fb..817c60e6d 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1511,6 +1511,47 @@ component_test_default_tinycrypt_without_legacy_ecc () { if_build_succeeded tests/compat.sh -f 'ECDHE-ECDSA\|ECDHE-PSK\|ECDH-ECDSA' } +component_test_hardcoded_pk_type () { + msg "build: default config + single PK type harcoded (tinycrypt)" + # need to enable tinycrypt first - copied from tinycrypt component + scripts/config.pl set MBEDTLS_USE_TINYCRYPT + scripts/config.pl set MBEDTLS_SSL_CONF_RNG rng_wrap + scripts/config.pl set MBEDTLS_SSL_CONF_SINGLE_EC + scripts/config.pl set MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID 23 + scripts/config.pl set MBEDTLS_SSL_CONF_SINGLE_UECC_GRP_ID MBEDTLS_UECC_DP_SECP256R1 + scripts/config.pl unset MBEDTLS_ECP_C + scripts/config.pl unset MBEDTLS_ECDH_C + scripts/config.pl unset MBEDTLS_ECDSA_C + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP192R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP224R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP256R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP384R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP521R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_BP256R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_BP384R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_BP512R1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP192K1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP224K1_ENABLED + scripts/config.pl unset MBEDTLS_ECP_DP_SECP256K1_ENABLED + # now single-PK specific configs + scripts/config.pl set MBEDTLS_PK_SINGLE_TYPE MBEDTLS_PK_INFO_ECKEY + scripts/config.pl unset MBEDTLS_PK_RSA_ALT_SUPPORT + scripts/config.pl unset MBEDTLS_RSA_C + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + scripts/config.pl unset MBEDTLS_X509_RSASSA_PSS_SUPPORT + make CFLAGS='-Werror -O1' + + msg "test: default config + single PK type harcoded (tinycrypt)" + make test + if_build_succeeded tests/ssl-opt.sh -f '^Default, DTLS$' +} + component_test_baremetal () { msg "build: lib+test+programs for baremetal.h + baremetal_test.h" record_status scripts/baremetal.sh --ram --build-only diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index fc917d003..b446f49b8 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -95,9 +95,11 @@ size_t mbedtls_rsa_key_len_func( void *ctx ) void valid_parameters( ) { mbedtls_pk_context pk; +#if !defined(MBEDTLS_PK_SINGLE_TYPE) unsigned char buf[1]; size_t len; void *options = NULL; +#endif mbedtls_pk_init( &pk ); @@ -107,7 +109,7 @@ void valid_parameters( ) TEST_VALID_PARAM( mbedtls_pk_restart_free( NULL ) ); #endif - TEST_ASSERT( mbedtls_pk_setup( &pk, NULL ) == + TEST_ASSERT( mbedtls_pk_setup( &pk, MBEDTLS_PK_INVALID_HANDLE ) == MBEDTLS_ERR_PK_BAD_INPUT_DATA ); /* In informational functions, we accept NULL where a context pointer @@ -118,6 +120,7 @@ void valid_parameters( ) TEST_ASSERT( mbedtls_pk_get_len( NULL ) == 0 ); TEST_ASSERT( mbedtls_pk_can_do( NULL, MBEDTLS_PK_NONE ) == 0 ); +#if !defined(MBEDTLS_PK_SINGLE_TYPE) TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_NONE, NULL, 0, @@ -172,6 +175,7 @@ void valid_parameters( ) NULL, &len, 0, rnd_std_rand, NULL ) == MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_PK_SINGLE_TYPE */ #if defined(MBEDTLS_PK_PARSE_C) TEST_ASSERT( mbedtls_pk_parse_key( &pk, NULL, 0, NULL, 1 ) == diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 468b806a1..84b8d320e 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -67,19 +67,19 @@ depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_ x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0 Certificate write check Server1 SHA1, RSA_ALT -depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C:MBEDTLS_PK_RSA_ALT_SUPPORT x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:-1:"data_files/server1.noauthid.crt":1 Certificate write check Server1 SHA1, RSA_ALT, key_usage -depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C:MBEDTLS_PK_RSA_ALT_SUPPORT x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1 Certificate write check Server1 SHA1, RSA_ALT, ns_cert_type -depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C:MBEDTLS_PK_RSA_ALT_SUPPORT x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1 Certificate write check Server1 SHA1, RSA_ALT, version 1 -depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C:MBEDTLS_PK_RSA_ALT_SUPPORT x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1 diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 923716594..3b9f20ffe 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -134,7 +134,7 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, TEST_ASSERT( mbedtls_pk_parse_keyfile( &issuer_key, issuer_key_file, issuer_pwd ) == 0 ); -#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* For RSA PK contexts, create a copy as an alternative RSA context. */ if( rsa_alt == 1 && mbedtls_pk_get_type( &issuer_key ) == MBEDTLS_PK_RSA ) { diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index e6f9ec815..0596aff0a 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -271,7 +271,6 @@ -