Commit 52a5f697 authored by johan's avatar johan

Add support for ECDH25519 and ECDH448 when available in bctoolbox

parent 8475e143
......@@ -5,7 +5,7 @@
@author Johan Pascal
@copyright Copyright (C) 2014 Belledonne Communications, Grenoble, France
@copyright Copyright (C) 2017 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
......@@ -76,13 +76,15 @@
* as it is used to easily sort them from faster(DH2k) to slower(EC52)
*/
#define ZRTP_KEYAGREEMENT_DH2k 0x41
#define ZRTP_KEYAGREEMENT_EC25 0x42
#define ZRTP_KEYAGREEMENT_DH3k 0x43
#define ZRTP_KEYAGREEMENT_EC38 0x44
#define ZRTP_KEYAGREEMENT_EC52 0x45
#define ZRTP_KEYAGREEMENT_Prsh 0x46
#define ZRTP_KEYAGREEMENT_Mult 0x47
#define ZRTP_KEYAGREEMENT_X255 0x42
#define ZRTP_KEYAGREEMENT_EC25 0x43
#define ZRTP_KEYAGREEMENT_X448 0x44
#define ZRTP_KEYAGREEMENT_DH3k 0x45
#define ZRTP_KEYAGREEMENT_EC38 0x46
#define ZRTP_KEYAGREEMENT_EC52 0x47
#define ZRTP_KEYAGREEMENT_Prsh 0x4e
#define ZRTP_KEYAGREEMENT_Mult 0x4f
#define ZRTP_SAS_B32 0x51
#define ZRTP_SAS_B256 0x52
......
......@@ -160,15 +160,15 @@ struct bzrtpChannelContext_struct {
uint16_t selfSequenceNumber; /**< Sequence number of the next packet to be sent */
uint16_t peerSequenceNumber; /**< Sequence number of the last valid received packet */
/* algorithm agreed after Hello message exchange(use mapping define in cryptoWrapper.h) and the function pointer to use them */
uint8_t hashAlgo; /**< hash algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoWrapper.h */
/* algorithm agreed after Hello message exchange(use mapping define in cryptoUtils.h) and the function pointer to use them */
uint8_t hashAlgo; /**< hash algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoUtils.h */
uint8_t hashLength; /**< the length in bytes of a hash generated with the agreed hash algo */
uint8_t cipherAlgo; /**< cipher algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoWrapper.h */
uint8_t cipherAlgo; /**< cipher algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoUtils.h */
uint8_t cipherKeyLength; /**< the length in bytes of the key needed by the agreed cipher block algo */
uint8_t authTagAlgo; /**< srtp authentication tag algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoWrapper.h */
uint8_t keyAgreementAlgo; /**< key agreement algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoWrapper.h */
uint8_t authTagAlgo; /**< srtp authentication tag algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoUtils.h */
uint8_t keyAgreementAlgo; /**< key agreement algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoUtils.h */
uint16_t keyAgreementLength; /**< the length in byte of the secret generated by the agreed key exchange algo */
uint8_t sasAlgo; /**< sas rendering algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoWrapper.h */
uint8_t sasAlgo; /**< sas rendering algorithm agreed on after Hello packet exchange, stored using integer mapping defined in cryptoUtils.h */
uint8_t sasLength; /**< length of the SAS depends on the algorithm agreed */
/* function pointer to the agreed algorithms - Note, key agreement manage directly this selection so it is not set here */
......@@ -204,7 +204,8 @@ struct bzrtpChannelContext_struct {
struct bzrtpContext_struct {
/* contexts */
bctbx_rng_context_t *RNGContext; /**< context for random number generation */
bctbx_DHMContext_t *DHMContext; /**< context for the Diffie-Hellman-Merkle operations. Only one DHM computation may be done during a call, so this belongs to the general context and not the channel one */
void *keyAgreementContext; /**< context for the key agreement operations. Only one key agreement computation may be done during a call, so this belongs to the general context and not the channel one */
uint8_t keyAgreementAlgo; /**< key agreement algorithm agreed on the first channel, the one performing key exchange, stored using integer mapping defined in cryptoUtils.h, */
/* flags */
uint8_t isInitialised; /**< this flag is set once the context was initialised : self ZID retrieved from cache or generated, used to unlock the creation of addtional channels */
......
......@@ -5,7 +5,7 @@
@author Johan Pascal
@copyright Copyright (C) 2014 Belledonne Communications, Grenoble, France
@copyright Copyright (C) 2017 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
......@@ -56,7 +56,8 @@ bzrtpContext_t *bzrtp_createBzrtpContext(void) {
/* start the random number generator */
context->RNGContext = bctbx_rng_context_new(); /* TODO: give a seed for the RNG? */
/* set the DHM context to NULL, it will be created if needed when creating a DHPart packet */
context->DHMContext = NULL;
context->keyAgreementContext = NULL;
context->keyAgreementAlgo = ZRTP_UNSET_ALGO;
/* set flags */
context->isSecure = 0; /* start unsecure */
......@@ -196,10 +197,16 @@ int bzrtp_destroyBzrtpContext(bzrtpContext_t *context, uint32_t selfSSRC) {
/* We have no more channel, destroy the zrtp context */
/* DHM context shall already been destroyed after s0 computation, but just in case */
if (context->DHMContext != NULL) {
bctbx_DestroyDHMContext(context->DHMContext);
context->DHMContext = NULL;
/* key agreement context shall already been destroyed after s0 computation, but just in case */
if (context->keyAgreementContext != NULL) {
if (context->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || context->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_DestroyECDHContext((bctbx_ECDHContext_t *)context->keyAgreementContext);
}
if (context->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || context->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DestroyDHMContext((bctbx_DHMContext_t *)context->keyAgreementContext);
}
context->keyAgreementContext = NULL;
context->keyAgreementAlgo = ZRTP_UNSET_ALGO;
}
/* Destroy keys and secrets */
......
......@@ -35,10 +35,10 @@
/** Return available crypto functions. For now we have
*
* - Hash: HMAC-SHA256(Mandatory)
* - CipherBlock: AES128(Mandatory)
* - CipherBlock: AES128(Mandatory), AES256(optional)
* - Auth Tag: HMAC-SHA132 and HMAC-SHA180 (These are mandatory for SRTP and depends on the SRTP implementation thus we can just suppose they are both available)
* - Key Agreement: DHM3k(Mandatory), DHM2k(optional and shall not be used except on low power devices)
* - Sas: base32(Mandatory), b256(pgp words)
* - Key Agreement: ECDH25519(not mentionned in RFC), ECDH448(not mentionned in RFC), DHM3k(Mandatory), DHM2k(optional and shall not be used except on low power devices)
* - Sas: base32(Mandatory), b256(pgp words, optional)
*/
uint8_t bzrtpUtils_getAvailableCryptoTypes(uint8_t algoType, uint8_t availableTypes[7]) {
......@@ -46,28 +46,45 @@ uint8_t bzrtpUtils_getAvailableCryptoTypes(uint8_t algoType, uint8_t availableTy
case ZRTP_HASH_TYPE:
availableTypes[0] = ZRTP_HASH_S256;
return 1;
break;
case ZRTP_CIPHERBLOCK_TYPE:
availableTypes[0] = ZRTP_CIPHER_AES1;
availableTypes[1] = ZRTP_CIPHER_AES3;
return 2;
break;
case ZRTP_AUTHTAG_TYPE:
availableTypes[0] = ZRTP_AUTHTAG_HS32;
availableTypes[1] = ZRTP_AUTHTAG_HS80;
return 2;
break;
case ZRTP_KEYAGREEMENT_TYPE:
availableTypes[0] = ZRTP_KEYAGREEMENT_DH3k;
availableTypes[1] = ZRTP_KEYAGREEMENT_DH2k;
availableTypes[2] = ZRTP_KEYAGREEMENT_Mult; /* This one shall always be at the end of the list, it is just to inform the peer ZRTP endpoint that we support the Multichannel ZRTP */
return 3;
break;
{
/* get availables types from bctoolbox */
uint32_t available_key_agreements = bctbx_key_agreement_algo_list();
uint8_t index=0;
if (available_key_agreements&BCTBX_ECDH_X25519) {
availableTypes[index] = ZRTP_KEYAGREEMENT_X255;
index++;
}
if (available_key_agreements&BCTBX_ECDH_X448) {
availableTypes[index] = ZRTP_KEYAGREEMENT_X448;
index++;
}
/* DH3k is mandatory*/
availableTypes[index] = ZRTP_KEYAGREEMENT_DH3k;
index++;
if (available_key_agreements|BCTBX_DHM_2048) {
availableTypes[index] = ZRTP_KEYAGREEMENT_DH2k;
index++;
}
availableTypes[index] = ZRTP_KEYAGREEMENT_Mult; /* This one shall always be at the end of the list, it is just to inform the peer ZRTP endpoint that we support the Multichannel ZRTP */
return index+1;
}
case ZRTP_SAS_TYPE: /* the SAS function is implemented in cryptoUtils.c and then is not directly linked to the polarSSL crypto wrapper */
availableTypes[0] = ZRTP_SAS_B32;
availableTypes[1] = ZRTP_SAS_B256;
return 2;
break;
default:
return 0;
}
......@@ -331,7 +348,7 @@ int bzrtp_cryptoAlgoAgreement(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
/* if the first choices are the same for both, select it */
if (selfCommonKeyAgreementType[0] == peerCommonKeyAgreementType[0]) {
zrtpChannelContext->keyAgreementAlgo = selfCommonKeyAgreementType[0];
} else { /* select the fastest of the two algoritm. Order is "DH2k", "EC25", "DH3k", "EC38", "EC52" */
} else { /* select the fastest of the two algoritm. Order is "DH2k", "E255", "EC25", "E448", "DH3k", "EC38", "EC52" is defined by value order from bzrtp.h */
if (peerCommonKeyAgreementType[0]<selfCommonKeyAgreementType[0]) { /* mapping to uint8_t is defined to have them in the fast to slow order */
zrtpChannelContext->keyAgreementAlgo = peerCommonKeyAgreementType[0];
} else {
......@@ -485,6 +502,12 @@ int bzrtp_updateCryptoFunctionPointers(bzrtpChannelContext_t *zrtpChannelContext
case ZRTP_KEYAGREEMENT_DH3k :
zrtpChannelContext->keyAgreementLength = 384;
break;
case ZRTP_KEYAGREEMENT_X255 :
zrtpChannelContext->keyAgreementLength = 32;
break;
case ZRTP_KEYAGREEMENT_X448 :
zrtpChannelContext->keyAgreementLength = 56;
break;
default:
return ZRTP_CRYPTOAGREEMENT_INVALIDCIPHER;
break;
......@@ -677,8 +700,12 @@ uint8_t bzrtp_cryptoAlgoTypeStringToInt(uint8_t algoType[4], uint8_t algoFamily)
return ZRTP_KEYAGREEMENT_DH3k;
} else if (memcmp(algoType, "DH2k", 4) == 0) {
return ZRTP_KEYAGREEMENT_DH2k;
} else if (memcmp(algoType, "E255", 4) == 0) {
return ZRTP_KEYAGREEMENT_X255;
} else if (memcmp(algoType, "EC25", 4) == 0) {
return ZRTP_KEYAGREEMENT_EC25;
} else if (memcmp(algoType, "E448", 4) == 0) {
return ZRTP_KEYAGREEMENT_X448;
} else if (memcmp(algoType, "EC38", 4) == 0) {
return ZRTP_KEYAGREEMENT_EC38;
} else if (memcmp(algoType, "EC52", 4) == 0) {
......@@ -760,9 +787,15 @@ void bzrtp_cryptoAlgoTypeIntToString(uint8_t algoTypeInt, uint8_t algoTypeString
case ZRTP_KEYAGREEMENT_DH2k:
memcpy(algoTypeString, "DH2k", 4);
break;
case ZRTP_KEYAGREEMENT_X255:
memcpy(algoTypeString, "E255", 4);
break;
case ZRTP_KEYAGREEMENT_EC25:
memcpy(algoTypeString, "EC25", 4);
break;
case ZRTP_KEYAGREEMENT_X448:
memcpy(algoTypeString, "E448", 4);
break;
case ZRTP_KEYAGREEMENT_DH3k:
memcpy(algoTypeString, "DH3k", 4);
break;
......
......@@ -356,6 +356,8 @@ int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpC
/* commit message length depends on the key agreement type choosen (and set in the zrtpContext->keyAgreementAlgo) */
switch(messageData->keyAgreementAlgo) {
case ZRTP_KEYAGREEMENT_DH2k :
case ZRTP_KEYAGREEMENT_X255 :
case ZRTP_KEYAGREEMENT_X448 :
case ZRTP_KEYAGREEMENT_EC25 :
case ZRTP_KEYAGREEMENT_DH3k :
case ZRTP_KEYAGREEMENT_EC38 :
......@@ -847,6 +849,8 @@ int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpCh
switch(messageData->keyAgreementAlgo) {
case ZRTP_KEYAGREEMENT_DH2k :
case ZRTP_KEYAGREEMENT_EC25 :
case ZRTP_KEYAGREEMENT_X255 :
case ZRTP_KEYAGREEMENT_X448 :
case ZRTP_KEYAGREEMENT_DH3k :
case ZRTP_KEYAGREEMENT_EC38 :
case ZRTP_KEYAGREEMENT_EC52 :
......@@ -1262,31 +1266,66 @@ bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelC
switch (zrtpChannelContext->keyAgreementAlgo) {
case ZRTP_KEYAGREEMENT_DH2k:
bctbx_keyAgreementAlgo = BCTBX_DHM_2048;
break;
case ZRTP_KEYAGREEMENT_DH3k:
{
bctbx_DHMContext_t *DHMContext = NULL;
if (zrtpChannelContext->keyAgreementAlgo==ZRTP_KEYAGREEMENT_DH2k) {
bctbx_keyAgreementAlgo = BCTBX_DHM_2048;
} else {
bctbx_keyAgreementAlgo = BCTBX_DHM_3072;
break;
default:
}
/* create DHM context */
DHMContext = (void *)bctbx_CreateDHMContext(bctbx_keyAgreementAlgo, secretLength);
if (DHMContext == NULL) {
free(zrtpPacket);
free(zrtpDHPartMessage);
*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
return NULL;
}
/* create private key and compute the public value */
bctbx_DHMCreatePublic(DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, zrtpContext->RNGContext);
zrtpDHPartMessage->pv = (uint8_t *)malloc((zrtpChannelContext->keyAgreementLength)*sizeof(uint8_t));
memcpy(zrtpDHPartMessage->pv, DHMContext->self, zrtpChannelContext->keyAgreementLength);
zrtpContext->keyAgreementContext = (void *)DHMContext; /* save DHM context in zrtp Context */
zrtpContext->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo; /* store algo in global context to be able to destroy it correctly*/
}
break;
case ZRTP_KEYAGREEMENT_X255:
case ZRTP_KEYAGREEMENT_X448:
{
bctbx_ECDHContext_t *ECDHContext = NULL;
if (zrtpChannelContext->keyAgreementAlgo==ZRTP_KEYAGREEMENT_X255) {
bctbx_keyAgreementAlgo = BCTBX_ECDH_X25519;
} else {
bctbx_keyAgreementAlgo = BCTBX_ECDH_X448;
}
zrtpContext->DHMContext = bctbx_CreateDHMContext(bctbx_keyAgreementAlgo, secretLength);
if (zrtpContext->DHMContext == NULL) {
/* Create the ECDH context */
ECDHContext = (void *)bctbx_CreateECDHContext(bctbx_keyAgreementAlgo);
if (ECDHContext == NULL) {
free(zrtpPacket);
free(zrtpDHPartMessage);
*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
return NULL;
}
/* now compute the public value */
bctbx_DHMCreatePublic(zrtpContext->DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, zrtpContext->RNGContext);
/* create private key and compute the public value */
bctbx_ECDHCreateKeyPair(ECDHContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, zrtpContext->RNGContext);
zrtpDHPartMessage->pv = (uint8_t *)malloc((zrtpChannelContext->keyAgreementLength)*sizeof(uint8_t));
memcpy(zrtpDHPartMessage->pv, zrtpContext->DHMContext->self, zrtpChannelContext->keyAgreementLength);
memcpy(zrtpDHPartMessage->pv, ECDHContext->selfPublic, zrtpChannelContext->keyAgreementLength);
zrtpContext->keyAgreementContext = (void *)ECDHContext; /* save ECDH context in zrtp Context */
zrtpContext->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo; /* store algo in global context to be able to destroy it correctly*/
}
break;
default:
free(zrtpPacket);
free(zrtpDHPartMessage);
*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
return NULL;
break;
}
/* attach the message data to the packet */
zrtpPacket->messageData = zrtpDHPartMessage;
}
......@@ -1581,6 +1620,12 @@ uint16_t computeKeyAgreementPrivateValueLength(uint8_t keyAgreementAlgo) {
case ZRTP_KEYAGREEMENT_DH2k :
pvLength = 256;
break;
case ZRTP_KEYAGREEMENT_X255 :
pvLength = 32;
break;
case ZRTP_KEYAGREEMENT_X448 :
pvLength = 56;
break;
case ZRTP_KEYAGREEMENT_EC25 :
pvLength = 64;
break;
......
......@@ -569,9 +569,18 @@ int state_keyAgreement_sendingCommit(bzrtpEvent_t event) {
zrtpChannelContext->peerPackets[DHPART_MESSAGE_STORE_ID] = zrtpPacket;
/* Compute the shared DH secret */
zrtpContext->DHMContext->peer = (uint8_t *)malloc(zrtpChannelContext->keyAgreementLength*sizeof(uint8_t));
memcpy (zrtpContext->DHMContext->peer, dhPart1Message->pv, zrtpChannelContext->keyAgreementLength);
bctbx_DHMComputeSecret(zrtpContext->DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)zrtpContext->RNGContext);
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DHMContext_t *DHMContext = (bctbx_DHMContext_t *)(zrtpContext->keyAgreementContext);
DHMContext->peer = (uint8_t *)malloc(zrtpChannelContext->keyAgreementLength*sizeof(uint8_t));
memcpy (DHMContext->peer, dhPart1Message->pv, zrtpChannelContext->keyAgreementLength);
bctbx_DHMComputeSecret(DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)zrtpContext->RNGContext);
}
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_ECDHContext_t *ECDHContext = (bctbx_ECDHContext_t *)(zrtpContext->keyAgreementContext);
ECDHContext->peerPublic = (uint8_t *)malloc(zrtpChannelContext->keyAgreementLength*sizeof(uint8_t));
memcpy (ECDHContext->peerPublic, dhPart1Message->pv, zrtpChannelContext->keyAgreementLength);
bctbx_ECDHComputeSecret(ECDHContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)zrtpContext->RNGContext);
}
/* Derive the s0 key */
bzrtp_computeS0DHMMode(zrtpContext, zrtpChannelContext);
......@@ -867,9 +876,18 @@ int state_keyAgreement_responderSendingDHPart1(bzrtpEvent_t event) {
zrtpChannelContext->peerPackets[DHPART_MESSAGE_STORE_ID] = zrtpPacket;
/* Compute the shared DH secret */
zrtpContext->DHMContext->peer = (uint8_t *)malloc(zrtpChannelContext->keyAgreementLength*sizeof(uint8_t));
memcpy (zrtpContext->DHMContext->peer, dhPart2Message->pv, zrtpChannelContext->keyAgreementLength);
bctbx_DHMComputeSecret(zrtpContext->DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)zrtpContext->RNGContext);
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DHMContext_t *DHMContext = (bctbx_DHMContext_t *)(zrtpContext->keyAgreementContext);
DHMContext->peer = (uint8_t *)malloc(zrtpChannelContext->keyAgreementLength*sizeof(uint8_t));
memcpy (DHMContext->peer, dhPart2Message->pv, zrtpChannelContext->keyAgreementLength);
bctbx_DHMComputeSecret(DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)zrtpContext->RNGContext);
}
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_ECDHContext_t *ECDHContext = (bctbx_ECDHContext_t *)(zrtpContext->keyAgreementContext);
ECDHContext->peerPublic = (uint8_t *)malloc(zrtpChannelContext->keyAgreementLength*sizeof(uint8_t));
memcpy (ECDHContext->peerPublic, dhPart2Message->pv, zrtpChannelContext->keyAgreementLength);
bctbx_ECDHComputeSecret(ECDHContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)zrtpContext->RNGContext);
}
/* Derive the s0 key */
bzrtp_computeS0DHMMode(zrtpContext, zrtpChannelContext);
......@@ -1892,7 +1910,15 @@ int bzrtp_computeS0DHMMode(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *z
dataToHash[3] = 0x01;
hashDataIndex = 4;
memcpy(dataToHash+hashDataIndex, zrtpContext->DHMContext->key, zrtpChannelContext->keyAgreementLength);
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DHMContext_t *DHMContext = (bctbx_DHMContext_t *)zrtpContext->keyAgreementContext;
memcpy(dataToHash+hashDataIndex, DHMContext->key, zrtpChannelContext->keyAgreementLength);
}
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_ECDHContext_t *ECDHContext = (bctbx_ECDHContext_t *)zrtpContext->keyAgreementContext;
memcpy(dataToHash+hashDataIndex, ECDHContext->sharedSecret, zrtpChannelContext->keyAgreementLength);
}
hashDataIndex += zrtpChannelContext->keyAgreementLength;
memcpy(dataToHash+hashDataIndex, "ZRTP-HMAC-KDF", 13);
hashDataIndex += 13;
......@@ -1949,8 +1975,14 @@ int bzrtp_computeS0DHMMode(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *z
zrtpContext->ZRTPSess);
/* clean the DHM context (secret and key shall be erased by this operation) */
bctbx_DestroyDHMContext(zrtpContext->DHMContext);
zrtpContext->DHMContext = NULL;
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DestroyDHMContext((bctbx_DHMContext_t *)(zrtpContext->keyAgreementContext));
}
if (zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || zrtpContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_DestroyECDHContext((bctbx_ECDHContext_t *)(zrtpContext->keyAgreementContext));
}
zrtpContext->keyAgreementContext = NULL;
zrtpContext->keyAgreementAlgo = ZRTP_UNSET_ALGO;
/* now derive the other keys */
return bzrtp_deriveKeysFromS0(zrtpContext, zrtpChannelContext);
......
......@@ -76,8 +76,23 @@ static uint8_t bobQueueIndex = 0;
#define ALICE_SSRC_BASE 0x12345000
#define BOB_SSRC_BASE 0x87654000
static cryptoParams_t defaultCryptoAlgoSelection = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_DH3k},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0};
static cryptoParams_t defaultCryptoAlgoSelectionNoSASValidation = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_DH3k},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,1};
static cryptoParams_t withoutX255 = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_DH3k},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0};
static cryptoParams_t withX255 = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0};
cryptoParams_t *defaultCryptoAlgoSelection(void) {
if (bctbx_key_agreement_algo_list()&BCTBX_ECDH_X25519) {
return &withX255;
}
return &withoutX255;
}
static cryptoParams_t withoutX255noSAS = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_DH3k},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,1};
static cryptoParams_t withX255noSAS = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,1};
cryptoParams_t *defaultCryptoAlgoSelectionNoSASValidation(void) {
if (bctbx_key_agreement_algo_list()&BCTBX_ECDH_X25519) {
return &withX255noSAS;
}
return &withoutX255noSAS;
}
/* static global settings and their reset function */
static uint64_t msSTC = 0; /* Simulation Time Coordinated start at 0 and increment it at each sleep, is in milliseconds */
......@@ -557,6 +572,31 @@ void test_cacheless_exchange(void) {
{{0},0,{0},0,{0},0,{0},0,{0},0,0}, /* this pattern will end the run because cipher nb is 0 */
};
/* serie tested only if ECDH is available */
cryptoParams_t ecdh_patterns[] = {
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X448},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS80},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS32},1,0},
{{ZRTP_CIPHER_AES3},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B256},1,{ZRTP_AUTHTAG_HS80},1,0},
{{0},0,{0},0,{0},0,{0},0,{0},0,0}, /* this pattern will end the run because cipher nb is 0 */
};
pattern = &patterns[0]; /* pattern is a pointer to current pattern */
while (pattern->cipherNb!=0) {
......@@ -564,7 +604,14 @@ void test_cacheless_exchange(void) {
pattern++; /* point to next row in the array of patterns */
}
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, NULL, NULL, NULL, NULL), 0, int, "%x");
/* with ECDH agreement types if available */
if (bctbx_key_agreement_algo_list()&BCTBX_ECDH_X25519) {
pattern = &ecdh_patterns[0]; /* pattern is a pointer to current pattern */
BC_ASSERT_EQUAL(multichannel_exchange(pattern, pattern, pattern, NULL, NULL, NULL, NULL), 0, int, "%x");
pattern++; /* point to next row in the array of patterns */
}
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), NULL, NULL, NULL, NULL), 0, int, "%x");
}
void test_loosy_network(void) {
......@@ -578,7 +625,7 @@ void test_loosy_network(void) {
resetGlobalParams();
timeOutLimit =100000; //outrageous time limit just to be sure to complete, not run in real time anyway
loosePacketPercentage=i;
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, NULL, NULL, NULL, NULL), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), NULL, NULL, NULL, NULL), 0, int, "%x");
}
}
}
......@@ -604,7 +651,7 @@ void test_cache_enabled_exchange(void) {
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDBob_simpleCache.sqlite"), &bobDB);
/* make a first exchange */
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), 0, int, "%x");
/* after the first exchange we shall have both pvs values at 1 and both rs1 identical and rs2 null, retrieve them from cache and check it */
/* first get each ZIDs, note give NULL as RNG context may lead to segfault in case of error(caches were not created correctly)*/
......@@ -633,7 +680,7 @@ void test_cache_enabled_exchange(void) {
BC_ASSERT_EQUAL(*colValuesBob[2], 1, int, "%d");
/* make a second exchange */
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), 0, int, "%x");
/* read new values in cache, ZIDs and zuids must be identical, read alice first to be able to check rs2 with old rs1 */
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)aliceDB, zuidAlice, "zrtp", colNames, colValuesAlice, colLengthAlice, 3), 0, int, "%x");
/* check what is now rs2 is the old rs1 */
......@@ -688,7 +735,7 @@ void test_cache_mismatch_exchange(void) {
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDBob_cacheMismatch.sqlite"), &bobDB);
/* make a first exchange */
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), 0, int, "%x");
/* after the first exchange we shall have both pvs values at 1 and both rs1 identical and rs2 null, retrieve them from cache and check it */
/* first get each ZIDs, note give NULL as RNG context may lead to segfault in case of error(caches were not created correctly)*/
......@@ -722,7 +769,7 @@ void test_cache_mismatch_exchange(void) {
/* make a second exchange : we have a cache mismatch(both on Bob and Alice side), wich means rs1 will not be backed up in rs2 which shall be NULL again */
/* rs1 will be in sync has the SAS comparison will succeed and pvs will be set to 1*/
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), RET_CACHE_MISMATCH<<16|RET_CACHE_MISMATCH, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), RET_CACHE_MISMATCH<<16|RET_CACHE_MISMATCH, int, "%x");
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)bobDB, zuidBob, "zrtp", colNames, colValuesBob, colLengthBob, 3), 0, int, "%x");
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)aliceDB, zuidAlice, "zrtp", colNames, colValuesAlice, colLengthAlice, 3), 0, int, "%x");
......@@ -748,7 +795,7 @@ void test_cache_mismatch_exchange(void) {
/* make a third exchange : we have a cache mismatch(on Bob side only), wich means rs1 will not be backed up in rs2 which shall be NULL again */
/* rs1 will be in sync has the SAS comparison will succeed and pvs will be set to 1*/
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), RET_CACHE_MISMATCH<<16, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org"), RET_CACHE_MISMATCH<<16, int, "%x");
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)bobDB, zuidBob, "zrtp", colNames, colValuesBob, colLengthBob, 3), 0, int, "%x");
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)aliceDB, zuidAlice, "zrtp", colNames, colValuesAlice, colLengthAlice, 3), 0, int, "%x");
......@@ -800,7 +847,7 @@ void test_cache_sas_not_confirmed(void) {
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDBob_simpleCache.sqlite"), &bobDB);
/* make a first exchange, Alice is instructed to not validate the SAS */
BC_ASSERT_EQUAL(multichannel_exchange_pvs_params(&defaultCryptoAlgoSelectionNoSASValidation, &defaultCryptoAlgoSelection, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org", TRUE, 0, 0), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange_pvs_params(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org", TRUE, 0, 0), 0, int, "%x");
/* after the first exchange we shall have alice pvs at 0 and bob at 1 and both rs1 identical and rs2 null, retrieve them from cache and check it */
/* first get each ZIDs, note give NULL as RNG context may lead to segfault in case of error(caches were not created correctly)*/
......@@ -829,7 +876,7 @@ void test_cache_sas_not_confirmed(void) {
/* make a second exchange, the PVS flag returned by both side shall be 0 as Alice did not validate hers on previous exchange */
/* but let them both validate this one */
BC_ASSERT_EQUAL(multichannel_exchange_pvs_params(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org", TRUE, 0, 0), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange_pvs_params(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org", TRUE, 0, 0), 0, int, "%x");
/* read new values in cache, ZIDs and zuids must be identical, read alice first to be able to check rs2 with old rs1 */
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)aliceDB, zuidAlice, "zrtp", colNames, colValuesAlice, colLengthAlice, 3), 0, int, "%x");
/* check what is now rs2 is the old rs1 */
......@@ -848,7 +895,7 @@ void test_cache_sas_not_confirmed(void) {
BC_ASSERT_EQUAL(*colValuesBob[2], 1, int, "%d");
/* make a third exchange, the PVS flag returned by both side shall be 1 */
BC_ASSERT_EQUAL(multichannel_exchange_pvs_params(NULL, NULL, &defaultCryptoAlgoSelection, aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org", TRUE, 1, 1), 0, int, "%x");
BC_ASSERT_EQUAL(multichannel_exchange_pvs_params(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bobDB, "bob@sip.linphone.org", TRUE, 1, 1), 0, int, "%x");
/* read new values in cache, ZIDs and zuids must be identical, read alice first to be able to check rs2 with old rs1 */
BC_ASSERT_EQUAL(bzrtp_cache_read((void *)aliceDB, zuidAlice, "zrtp", colNames, colValuesAlice, colLengthAlice, 3), 0, int, "%x");
/* check what is now rs2 is the old rs1 */
......
......@@ -115,7 +115,14 @@ void test_CRC32(void) {
BC_ASSERT_TRUE(bzrtp_CRC32(patterCRCinput[i], patternCRCLength[i]) == patternCRCoutput[i]);
}
}
/* expected result of tests vary according to default key agreement algorithm */
/* if EC25519 is available, this is the default, DH3k otherwise */
static uint8_t getDefaultKeyAgreementAlgo() {
if (bctbx_key_agreement_algo_list()&BCTBX_ECDH_X25519) {
return ZRTP_KEYAGREEMENT_X255;
}
return ZRTP_KEYAGREEMENT_DH3k;
}
static void setHelloMessageAlgo(bzrtpHelloMessage_t *helloMessage, uint8_t algoType, uint8_t types[7], const uint8_t typesCount) {
switch(algoType) {
case ZRTP_HASH_TYPE:
......@@ -153,17 +160,17 @@ static int compareAllAlgoTypes(bzrtpChannelContext_t *zrtpChannelContext, uint8_
static int compareAllAlgoTypesWithExpectedChangedOnly(bzrtpChannelContext_t *zrtpChannelContext, uint8_t expectedAlgoType, uint8_t expectedType) {
switch(expectedAlgoType) {
case ZRTP_HASH_TYPE:
return compareAllAlgoTypes(zrtpChannelContext, expectedType, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, ZRTP_KEYAGREEMENT_DH3k, ZRTP_SAS_B32);
return compareAllAlgoTypes(zrtpChannelContext, expectedType, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, getDefaultKeyAgreementAlgo(), ZRTP_SAS_B32);
case ZRTP_CIPHERBLOCK_TYPE:
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, expectedType, ZRTP_AUTHTAG_HS32, ZRTP_KEYAGREEMENT_DH3k, ZRTP_SAS_B32);
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, expectedType, ZRTP_AUTHTAG_HS32, getDefaultKeyAgreementAlgo(), ZRTP_SAS_B32);
case ZRTP_AUTHTAG_TYPE:
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, expectedType, ZRTP_KEYAGREEMENT_DH3k, ZRTP_SAS_B32);
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, expectedType, getDefaultKeyAgreementAlgo(), ZRTP_SAS_B32);
case ZRTP_KEYAGREEMENT_TYPE:
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, expectedType, ZRTP_SAS_B32);
case ZRTP_SAS_TYPE:
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, ZRTP_KEYAGREEMENT_DH3k, expectedType);
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, getDefaultKeyAgreementAlgo(), expectedType);
default:
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, ZRTP_KEYAGREEMENT_DH3k, ZRTP_SAS_B32);
return compareAllAlgoTypes(zrtpChannelContext, ZRTP_HASH_S256, ZRTP_CIPHER_AES1, ZRTP_AUTHTAG_HS32, getDefaultKeyAgreementAlgo(), ZRTP_SAS_B32);
}
}
......@@ -296,7 +303,7 @@ void test_algoAgreement(void) {
struct st_algo_type *cipher_type;
/* check defaults */
BC_ASSERT_TRUE(testAlgoTypeWithPacket(ZRTP_UNSET_ALGO, NULL, 0, ZRTP_KEYAGREEMENT_DH3k));
BC_ASSERT_TRUE(testAlgoTypeWithPacket(ZRTP_UNSET_ALGO, NULL, 0, getDefaultKeyAgreementAlgo()));
/* key agreement type */
agreement_type_with_packet = &agreement_types_with_packet[0];
......@@ -391,6 +398,15 @@ void test_algoSetterGetter(void) {
{ {ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_DH3k}, 8, {ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_Mult}, 2 },
{ {ZRTP_UNSET_ALGO}, 0, {ZRTP_UNSET_ALGO}, 0, }
};
/* Define another set used only if ECDH agreements are availables */
struct st_algo_setter_getter ecdh_agreement_types[] = {
{ {ZRTP_KEYAGREEMENT_X255}, 1, {ZRTP_KEYAGREEMENT_X255, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_Mult}, 3 },
{ {ZRTP_KEYAGREEMENT_X448}, 1, {ZRTP_KEYAGREEMENT_X448, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_Mult}, 3 },
{ {ZRTP_KEYAGREEMENT_X255, ZRTP_KEYAGREEMENT_X448}, 2, {ZRTP_KEYAGREEMENT_X255, ZRTP_KEYAGREEMENT_X448, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_Mult}, 4 },
{ {ZRTP_KEYAGREEMENT_X448, ZRTP_KEYAGREEMENT_X255}, 2, {ZRTP_KEYAGREEMENT_X448, ZRTP_KEYAGREEMENT_X255, ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_Mult}, 4 },
{ {ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_X448, ZRTP_KEYAGREEMENT_X255}, 3, {ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_X448, ZRTP_KEYAGREEMENT_X255, ZRTP_KEYAGREEMENT_Mult}, 4 },
{ {ZRTP_UNSET_ALGO}, 0, {ZRTP_UNSET_ALGO}, 0, }
};
struct st_algo_setter_getter *agreement_type;
struct st_algo_setter_getter cipher_types[] = {
{ {ZRTP_CIPHER_AES1}, 1, {ZRTP_CIPHER_AES1}, 1 },
......@@ -417,6 +433,15 @@ void test_algoSetterGetter(void) {
agreement_type++;
}
/* ECDH agreement type */
if (bctbx_key_agreement_algo_list()&BCTBX_ECDH_X25519) {
agreement_type = &ecdh_agreement_types[0];
while (agreement_type->contextTypesCount > 0) {
BC_ASSERT_TRUE(testAlgoSetterGetter(ZRTP_KEYAGREEMENT_TYPE, agreement_type->contextTypes, agreement_type->contextTypesCount, agreement_type->expectedTypes, agreement_type->expectedTypesCount));
agreement_type++;
}
}
/* cipher type */
cipher_type = &cipher_types[0];
while (cipher_type->contextTypesCount > 0) {
......@@ -451,6 +476,7 @@ void test_addMandatoryCryptoTypesIfNeeded(void) {
{ ZRTP_CIPHERBLOCK_TYPE, {ZRTP_UNSET_ALGO}, 0, {ZRTP_CIPHER_AES1}, 1 },
{ ZRTP_AUTHTAG_TYPE, {ZRTP_UNSET_ALGO}, 0, {ZRTP_AUTHTAG_HS32, ZRTP_AUTHTAG_HS80}, 2 },
{ ZRTP_KEYAGREEMENT_TYPE, {ZRTP_UNSET_ALGO}, 0, {ZRTP_KEYAGREEMENT_DH3k}, 1 },
{ ZRTP_KEYAGREEMENT_TYPE, {ZRTP_KEYAGREEMENT_X255}, 1, {ZRTP_KEYAGREEMENT_DH3k, ZRTP_KEYAGREEMENT_X255}, 2 },
{ ZRTP_SAS_TYPE, {ZRTP_UNSET_ALGO}, 0, {ZRTP_SAS_B32}, 1 },
{ ZRTP_AUTHTAG_TYPE, {ZRTP_AUTHTAG_HS32, ZRTP_AUTHTAG_HS80}, 2, {ZRTP_AUTHTAG_HS32, ZRTP_AUTHTAG_HS80}, 2 },
{ ZRTP_AUTHTAG_TYPE, {ZRTP_AUTHTAG_HS80, ZRTP_AUTHTAG_HS32}, 2, {ZRTP_AUTHTAG_HS80, ZRTP_AUTHTAG_HS32}, 2 },
......
......@@ -706,9 +706,19 @@ void test_parserComplete() {
/* Now Alice shall check that the PV from bob is not 1 or Prime-1 TODO*/
/* Compute the shared DH secret */
contextAlice->DHMContext->peer = (uint8_t *)malloc(contextAlice->channelContext[0]->keyAgreementLength*sizeof(uint8_t));
memcpy (contextAlice->DHMContext->peer, alice_DHPart1FromBob_message->pv, contextAlice->channelContext[0]->keyAgreementLength);
bctbx_DHMComputeSecret(contextAlice->DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)contextAlice->RNGContext);
if (contextAlice->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || contextAlice->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DHMContext_t *DHMContext = (bctbx_DHMContext_t *)(contextAlice->keyAgreementContext);
DHMContext->peer = (uint8_t *)malloc(contextAlice->channelContext[0]->keyAgreementLength*sizeof(uint8_t));
memcpy (DHMContext->peer, alice_DHPart1FromBob_message->pv, contextAlice->channelContext[0]->keyAgreementLength);
bctbx_DHMComputeSecret(DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)contextAlice->RNGContext);
}
if (contextAlice->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || contextAlice->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_ECDHContext_t *ECDHContext = (bctbx_ECDHContext_t *)(contextAlice->keyAgreementContext);
ECDHContext->peerPublic = (uint8_t *)malloc(contextAlice->channelContext[0]->keyAgreementLength*sizeof(uint8_t));
memcpy (ECDHContext->peerPublic, alice_DHPart1FromBob_message->pv, contextAlice->channelContext[0]->keyAgreementLength);
bctbx_ECDHComputeSecret(ECDHContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)contextAlice->RNGContext);
}
/* So Alice send bob her DHPart2 message which is already prepared and stored (we just need to update the sequence number) */
bzrtp_packetUpdateSequenceNumber(contextAlice->channelContext[0]->selfPackets[DHPART_MESSAGE_STORE_ID], contextAlice->channelContext[0]->selfSequenceNumber);
......@@ -760,20 +770,45 @@ void test_parserComplete() {
/* Now Bob shall check that the PV from Alice is not 1 or Prime-1 TODO*/
/* Compute the shared DH secret */
contextBob->DHMContext->peer = (uint8_t *)malloc(contextBob->channelContext[0]->keyAgreementLength*sizeof(uint8_t));
memcpy (contextBob->DHMContext->peer, bob_DHPart2FromAlice_message->pv, contextBob->channelContext[0]->keyAgreementLength);
bctbx_DHMComputeSecret(contextBob->DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)contextAlice->RNGContext);
if (contextBob->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || contextBob->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DHMContext_t *DHMContext = (bctbx_DHMContext_t *)(contextBob->keyAgreementContext);
DHMContext->peer = (uint8_t *)malloc(contextBob->channelContext[0]->keyAgreementLength*sizeof(uint8_t));
memcpy (DHMContext->peer, bob_DHPart2FromAlice_message->pv, contextBob->channelContext[0]->keyAgreementLength);
bctbx_DHMComputeSecret(DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)contextAlice->RNGContext);
}
if (contextBob->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X255 || contextBob->keyAgreementAlgo == ZRTP_KEYAGREEMENT_X448) {
bctbx_ECDHContext_t *ECDHContext = (bctbx_ECDHContext_t *)(contextBob->keyAgreementContext);
ECDHContext->peerPublic = (uint8_t *)malloc(contextBob->channelContext[0]->keyAgreementLength*sizeof(uint8_t));
memcpy (ECDHContext->peerPublic, bob_DHPart2FromAlice_message->pv, contextBob->channelContext[0]->keyAgreementLength);
bctbx_ECDHComputeSecret(ECDHContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, (void *)contextAlice->RNGContext);
}
/* JUST FOR TEST: check that the generated secrets are the same */
secretLength = bob_DHPart2FromAlice->messageLength-84; /* length of generated secret is the same than public value */
if (memcmp(contextBob->DHMContext->key, contextAlice->DHMContext->key, secretLength)==0) {
if (contextBob->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH2k || contextBob->keyAgreementAlgo == ZRTP_KEYAGREEMENT_DH3k) {
bctbx_DHMContext_t *DHMContextAlice = (bctbx_DHMContext_t *)(contextAlice->keyAgreementContext);
bctbx_DHMContext_t *DHMContextBob = (bctbx_DHMContext_t *)(contextBob->keyAgreementContext);
if (memcmp(DHMContextBob->key, DHMContextAlice->key, secretLength)==0) {
bzrtp_message("Secret Key correctly exchanged \n");
BC_PASS("Secret Key exchange OK");
} else {
BC_FAIL("Secret Key exchange failed");