Commit 81faf2e5 authored by johan's avatar johan

Enhance ECDH API

+fix memory leak in tests
parent 02caea7d
......@@ -597,7 +597,7 @@ typedef struct bctbx_ECDHContext_struct {
* @return The initialised context for the ECDH calculation(must then be freed calling the destroyECDHContext function), NULL on error
*
*/
BCTBX_PUBLIC bctbx_ECDHContext_t *bctbx_CreateECDHContext(uint8_t ECDHAlgo);
BCTBX_PUBLIC bctbx_ECDHContext_t *bctbx_CreateECDHContext(const uint8_t ECDHAlgo);
/**
*
......@@ -618,7 +618,28 @@ BCTBX_PUBLIC void bctbx_ECDHCreateKeyPair(bctbx_ECDHContext_t *context, int (*rn
* @param[in] secret The buffer holding the secret, is duplicated in the ECDH context
* @param[in] secretLength Length of previous buffer, must match the algo type setted at context creation
*/
BCTBX_PUBLIC void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, uint8_t *secret, size_t secretLength);
BCTBX_PUBLIC void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, const uint8_t *secret, const size_t secretLength);
/**
*
* @brief Set the given self public key in the ECDH context
* Warning: no check if it matches the private key value
*
* @param[in/out] context ECDH context, will store the given self public key if length is matching the pre-setted algo for this context
* @param[in] selfPublic The buffer holding the self public key, is duplicated in the ECDH context
* @param[in] selfPublicLength Length of previous buffer, must match the algo type setted at context creation
*/
BCTBX_PUBLIC void bctbx_ECDHSetSelfPublicKey(bctbx_ECDHContext_t *context, const uint8_t *selfPublic, const size_t selfPublicLength);
/**
*
* @brief Set the given peer public key in the ECDH context
*
* @param[in/out] context ECDH context, will store the given peer public key if length is matching the pre-setted algo for this context
* @param[in] peerPublic The buffer holding the peer public key, is duplicated in the ECDH context
* @param[in] peerPublicLength Length of previous buffer, must match the algo type setted at context creation
*/
BCTBX_PUBLIC void bctbx_ECDHSetPeerPublicKey(bctbx_ECDHContext_t *context, const uint8_t *peerPublic, const size_t peerPublicLength);
/**
*
......
......@@ -51,7 +51,7 @@ uint32_t bctbx_key_agreement_algo_list(void) {
/*****************************************************************************/
/* Create and initialise the ECDH Context */
bctbx_ECDHContext_t *bctbx_CreateECDHContext(uint8_t ECDHAlgo) {
bctbx_ECDHContext_t *bctbx_CreateECDHContext(const uint8_t ECDHAlgo) {
/* create the context */
bctbx_ECDHContext_t *context = (bctbx_ECDHContext_t *)bctbx_malloc(sizeof(bctbx_ECDHContext_t));
memset (context, 0, sizeof(bctbx_ECDHContext_t));
......@@ -91,13 +91,52 @@ bctbx_ECDHContext_t *bctbx_CreateECDHContext(uint8_t ECDHAlgo) {
* @param[in] secret The buffer holding the secret, is duplicated in the ECDH context
* @param[in] secretLength Length of previous buffer, must match the algo type setted at context creation
*/
void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, uint8_t *secret, size_t secretLength) {
void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, const uint8_t *secret, const size_t secretLength) {
if (context!=NULL && context->secretLength==secretLength) {
context->secret = (uint8_t *)bctbx_malloc(context->secretLength);
if (context->secret == NULL) { /* allocate a new buffer */
context->secret = (uint8_t *)bctbx_malloc(context->secretLength);
} else { /* or make sure we wipe out the existing one */
memset(context->secret, 0, context->secretLength);
}
memcpy(context->secret, secret, secretLength);
}
}
/**
*
* @brief Set the given self public key in the ECDH context
* Warning: no check if it matches the private key value
*
* @param[in/out] context ECDH context, will store the given self public key if length is matching the pre-setted algo for this context
* @param[in] selfPublic The buffer holding the self public key, is duplicated in the ECDH context
* @param[in] selfPublicLength Length of previous buffer, must match the algo type setted at context creation
*/
void bctbx_ECDHSetSelfPublicKey(bctbx_ECDHContext_t *context, const uint8_t *selfPublic, const size_t selfPublicLength) {
if (context!=NULL && context->pointCoordinateLength==selfPublicLength) {
if (context->selfPublic == NULL) {
context->selfPublic = (uint8_t *)bctbx_malloc(selfPublicLength);
}
memcpy(context->selfPublic, selfPublic, selfPublicLength);
}
}
/**
*
* @brief Set the given peer public key in the ECDH context
*
* @param[in/out] context ECDH context, will store the given peer public key if length is matching the pre-setted algo for this context
* @param[in] peerPublic The buffer holding the peer public key, is duplicated in the ECDH context
* @param[in] peerPublicLength Length of previous buffer, must match the algo type setted at context creation
*/
BCTBX_PUBLIC void bctbx_ECDHSetPeerPublicKey(bctbx_ECDHContext_t *context, const uint8_t *peerPublic, const size_t peerPublicLength) {
if (context!=NULL && context->pointCoordinateLength==peerPublicLength) {
/* allocate public key buffer if needed */
if (context->peerPublic == NULL) {
context->peerPublic = (uint8_t *)bctbx_malloc(peerPublicLength);
}
memcpy(context->peerPublic, peerPublic, peerPublicLength);
}
}
/**
*
* @brief Derive the public key from the secret setted in context and using preselected algo, following RFC7748
......@@ -106,8 +145,10 @@ void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, uint8_t *secret, size_
*/
void bctbx_ECDHDerivePublicKey(bctbx_ECDHContext_t *context) {
if (context!=NULL && context->secret!=NULL) {
/* allocate public key buffer */
context->selfPublic = (uint8_t *)bctbx_malloc(context->pointCoordinateLength);
/* allocate public key buffer if needed */
if (context->selfPublic == NULL) {
context->selfPublic = (uint8_t *)bctbx_malloc(context->pointCoordinateLength);
}
/* then generate the public value */
switch (context->algo) {
......@@ -127,7 +168,11 @@ void bctbx_ECDHDerivePublicKey(bctbx_ECDHContext_t *context) {
void bctbx_ECDHCreateKeyPair(bctbx_ECDHContext_t *context, int (*rngFunction)(void *, uint8_t *, size_t), void *rngContext) {
if (context!=NULL) {
/* first generate the random bytes of self secret and store it in context(do it directly instead of creating a temp buffer and calling SetSecretKey) */
context->secret = (uint8_t *)bctbx_malloc(context->secretLength);
if (context->secret == NULL) { /* allocate buffer if needed */
context->secret = (uint8_t *)bctbx_malloc(context->secretLength);
} else { /* otherwise make sure we wipe out previous secret */
memset(context->secret, 0, context->secretLength);
}
rngFunction(rngContext, context->secret, context->secretLength);
/* Then derive the public key */
......@@ -138,19 +183,24 @@ void bctbx_ECDHCreateKeyPair(bctbx_ECDHContext_t *context, int (*rngFunction)(vo
/* compute secret - the ->peerPublic field of context must have been set before calling this function */
void bctbx_ECDHComputeSecret(bctbx_ECDHContext_t *context, int (*rngFunction)(void *, uint8_t *, size_t), void *rngContext) {
if (context != NULL && context->secret!=NULL && context->peerPublic!=NULL) {
/* allocate shared secret buffer */
context->sharedSecret = (uint8_t *)bctbx_malloc(context->pointCoordinateLength);
if (context->sharedSecret == NULL) { /* allocate buffer if needed */
context->sharedSecret = (uint8_t *)bctbx_malloc(context->pointCoordinateLength);
} else { /* otherwise make sure we wipe out previous secret */
memset(context->sharedSecret, 0, context->pointCoordinateLength);
}
switch (context->algo) {
case BCTBX_ECDH_X25519:
if (decaf_x25519(context->sharedSecret, context->peerPublic, context->secret)==DECAF_FAILURE) {
bctbx_free(context->sharedSecret);
memset(context->sharedSecret, 0, context->pointCoordinateLength);
context->sharedSecret=NULL;
}
break;
case BCTBX_ECDH_X448:
if (decaf_x448(context->sharedSecret, context->peerPublic, context->secret)==DECAF_FAILURE) {
bctbx_free(context->sharedSecret);
memset(context->sharedSecret, 0, context->pointCoordinateLength);
context->sharedSecret=NULL;
}
break;
......@@ -167,14 +217,17 @@ void bctbx_DestroyECDHContext(bctbx_ECDHContext_t *context) {
if (context->secret != NULL) {
memset(context->secret, 0, context->secretLength);
free(context->secret);
context->secret=NULL;
}
free(context->selfPublic);
context->selfPublic=NULL;
if (context->sharedSecret != NULL) {
memset(context->sharedSecret, 0, context->pointCoordinateLength);
free(context->sharedSecret);
context->sharedSecret=NULL;
}
free(context->peerPublic);
free(context->cryptoModuleData);
context->peerPublic=NULL;
free(context);
}
}
......@@ -461,9 +514,11 @@ uint32_t bctbx_key_agreement_algo_list(void) {
/* We do not have lib decaf, implement empty stubs */
int bctbx_crypto_have_ecc(void) { return FALSE;}
bctbx_ECDHContext_t *bctbx_CreateECDHContext(uint8_t ECDHAlgo) {return NULL;}
bctbx_ECDHContext_t *bctbx_CreateECDHContext(const uint8_t ECDHAlgo) {return NULL;}
void bctbx_ECDHCreateKeyPair(bctbx_ECDHContext_t *context, int (*rngFunction)(void *, uint8_t *, size_t), void *rngContext) {return;}
void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, uint8_t *secret, size_t secretLength){return;}
void bctbx_ECDHSetSecretKey(bctbx_ECDHContext_t *context, const uint8_t *secret, const size_t secretLength){return;}
void bctbx_ECDHSetSelfPublicKey(bctbx_ECDHContext_t *context, const uint8_t *selfPublic, const size_t selfPublicLength){return;}
void bctbx_ECDHSetPeerPublicKey(bctbx_ECDHContext_t *context, const uint8_t *peerPublic, const size_t peerPublicLength){return;}
void bctbx_ECDHDerivePublicKey(bctbx_ECDHContext_t *context){return;}
void bctbx_ECDHComputeSecret(bctbx_ECDHContext_t *context, int (*rngFunction)(void *, uint8_t *, size_t), void *rngContext){return;}
void bctbx_DestroyECDHContext(bctbx_ECDHContext_t *context){return;}
......
......@@ -92,10 +92,8 @@ static void DHM(void) {
static void ECDH_exchange(bctbx_ECDHContext_t *alice, bctbx_ECDHContext_t *bob) {
/* exchange public keys */
alice->peerPublic = (uint8_t *)malloc(alice->pointCoordinateLength*sizeof(uint8_t));
memcpy(alice->peerPublic, bob->selfPublic, alice->pointCoordinateLength);
bob->peerPublic = (uint8_t *)malloc(alice->pointCoordinateLength*sizeof(uint8_t));
memcpy(bob->peerPublic, alice->selfPublic, alice->pointCoordinateLength);
bctbx_ECDHSetPeerPublicKey(alice, bob->selfPublic, alice->pointCoordinateLength);
bctbx_ECDHSetPeerPublicKey(bob, alice->selfPublic, bob->pointCoordinateLength);
/* compute shared secrets */
bctbx_ECDHComputeSecret(alice, NULL, NULL);
......@@ -161,6 +159,30 @@ static void ECDH(void) {
/* clear contexts */
bctbx_rng_context_free(RNG);
/********************************************************************/
/*** Run an exchange using patterns from RFC7748 */
/********************************************************************/
/*** Run it on the X25519 patterns ***/
/* set contexts */
alice = bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
bob = bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
/* Set private and public value */
bctbx_ECDHSetSecretKey(alice, ECDHpattern_X25519_alicePrivate, 32);
bctbx_ECDHSetSelfPublicKey(alice, ECDHpattern_X25519_alicePublic, 32);
bctbx_ECDHSetSecretKey(bob, ECDHpattern_X25519_bobPrivate, 32);
bctbx_ECDHSetSelfPublicKey(bob, ECDHpattern_X25519_bobPublic, 32);
/* Perform the key exchange and compute shared secret, it will check shared secrets are matching */
ECDH_exchange(alice, bob);
/* check shared secret according to RFC7748 patterns */
BC_ASSERT_TRUE(memcmp(alice->sharedSecret, ECDHpattern_X25519_sharedSecret, 32)==0);
/* clear contexts */
bctbx_DestroyECDHContext(alice);
bctbx_DestroyECDHContext(bob);
/********************************************************************/
/*** Run an key derivation and exchange using patterns from RFC7748 */
/********************************************************************/
......@@ -216,6 +238,30 @@ static void ECDH(void) {
bctbx_DestroyECDHContext(alice);
bctbx_DestroyECDHContext(bob);
/********************************************************************/
/*** Run an exchange using patterns from RFC7748 */
/********************************************************************/
/*** Run it on the X448 patterns ***/
/* set contexts */
alice = bctbx_CreateECDHContext(BCTBX_ECDH_X448);
bob = bctbx_CreateECDHContext(BCTBX_ECDH_X448);
/* Set private and derive the public value */
bctbx_ECDHSetSecretKey(alice, ECDHpattern_X448_alicePrivate, 56);
bctbx_ECDHSetSelfPublicKey(alice, ECDHpattern_X448_alicePublic, 56);
bctbx_ECDHSetSecretKey(bob, ECDHpattern_X448_bobPrivate, 56);
bctbx_ECDHSetSelfPublicKey(bob, ECDHpattern_X448_bobPublic, 56);
/* Perform the key exchange and compute shared secret, it will check shared secrets are matching */
ECDH_exchange(alice, bob);
/* check shared secret according to RFC7748 patterns */
BC_ASSERT_TRUE(memcmp(alice->sharedSecret, ECDHpattern_X448_sharedSecret, 56)==0);
/* clear contexts */
bctbx_DestroyECDHContext(alice);
bctbx_DestroyECDHContext(bob);
/********************************************************************/
/*** Run an key derivation and exchange using patterns from RFC7748 */
/********************************************************************/
......@@ -251,7 +297,7 @@ static void ECDH25519compat(void) {
#ifdef HAVE_MBEDTLS
int i;
bctbx_ECDHContext_t *alice;
bctbx_ECDHContext_t *alice=NULL;
bctbx_rng_context_t *RNG;
mbedtls_ecdh_context *bob=NULL;
uint8_t tmpBuffer[32];
......@@ -270,7 +316,7 @@ static void ECDH25519compat(void) {
/* Create Alice and Bob contexts */
alice = bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
bob=(mbedtls_ecdh_context *)malloc(sizeof(mbedtls_ecdh_context));
bob=(mbedtls_ecdh_context *)bctbx_malloc(sizeof(mbedtls_ecdh_context));
mbedtls_ecdh_init(bob);
mbedtls_ecp_group_load(&(bob->grp), MBEDTLS_ECP_DP_CURVE25519 );
......@@ -311,6 +357,8 @@ static void ECDH25519compat(void) {
/* clear contexts */
bctbx_DestroyECDHContext(alice);
mbedtls_ecdh_free(bob);
free(bob);
/* clear contexts */
bctbx_rng_context_free(RNG);
......@@ -378,6 +426,8 @@ static void EdDSA(void) {
bctbx_DestroyEDDSAContext(james);
bctbx_DestroyEDDSAContext(world);
}
bctbx_rng_context_free(RNG);
}
static void ed25519_to_x25519_keyconversion(void) {
......@@ -418,10 +468,10 @@ static void ed25519_to_x25519_keyconversion(void) {
static void sign_and_key_exchange(void) {
int i;
bctbx_rng_context_t *RNG;
bctbx_ECDHContext_t *aliceECDH = bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
bctbx_EDDSAContext_t *aliceEDDSA = bctbx_CreateEDDSAContext(BCTBX_EDDSA_25519);
bctbx_ECDHContext_t *bobECDH = bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
bctbx_EDDSAContext_t *bobEDDSA = bctbx_CreateEDDSAContext(BCTBX_EDDSA_25519);
bctbx_ECDHContext_t *aliceECDH = NULL;//bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
bctbx_EDDSAContext_t *aliceEDDSA = NULL;//bctbx_CreateEDDSAContext(BCTBX_EDDSA_25519);
bctbx_ECDHContext_t *bobECDH = NULL;//bctbx_CreateECDHContext(BCTBX_ECDH_X25519);
bctbx_EDDSAContext_t *bobEDDSA = NULL;//bctbx_CreateEDDSAContext(BCTBX_EDDSA_25519);
uint8_t availableAlgosEDDSA[2]={BCTBX_EDDSA_25519, BCTBX_EDDSA_448};
uint8_t availableAlgosECDH[2]={BCTBX_ECDH_X25519, BCTBX_ECDH_X448};
uint8_t availableAlgosNb=2;
......@@ -494,6 +544,8 @@ static void sign_and_key_exchange(void) {
bctbx_DestroyEDDSAContext(bobEDDSA);
bctbx_DestroyECDHContext(bobECDH);
}
bctbx_rng_context_free(RNG);
}
static void hash_test(void) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment