Make sub-context statically allocated
This makes a mbedtls_pk_context memory-wise equivalent to a
mbedtls_uecc_keypair and removes a dynamic allocation, making the PK layer
zero-cost in terms of memory when PK_SINGLE_TYPE is enabled.
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index 09a8513..b6c2998 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
@@ -137,17 +141,6 @@
#define MBEDTLS_PK_INVALID_HANDLE ( (mbedtls_pk_handle_t) NULL )
#endif /* MBEDTLS_PK_SINGLE_TYPE */
-/**
- * \brief Public key container
- */
-typedef struct mbedtls_pk_context
-{
-#if !defined(MBEDTLS_PK_SINGLE_TYPE)
- mbedtls_pk_handle_t pk_info; /**< Public key information */
-#endif
- void * pk_ctx; /**< Underlying public key context */
-} mbedtls_pk_context;
-
#if defined(MBEDTLS_USE_TINYCRYPT)
typedef struct
{
@@ -156,6 +149,22 @@
} 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
@@ -184,11 +193,18 @@
#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)
/**
diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h
index 5258cb1..2c7d0f9 100644
--- a/include/mbedtls/pk_internal.h
+++ b/include/mbedtls/pk_internal.h
@@ -50,6 +50,7 @@
/* 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
@@ -70,6 +71,7 @@
/*
* 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
@@ -94,6 +96,7 @@
* 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 )
@@ -113,6 +116,7 @@
#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 */
@@ -230,6 +234,7 @@
MBEDTLS_PK_INFO_DEBUG_FUNC( PK ), \
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+#endif /* MBEDTLS_PK_SINGLE_TYPE */
/*
* Macros to access pk_info