Commit 26022db5 authored by johan's avatar johan
Browse files

Cache functionnal

- use libxml2 to manage cache
- add set/unset previously verified sas flag management interface
- clean debug code
parent 4e60d73a
...@@ -31,6 +31,14 @@ if test "$found_cunit" = "no" ; then ...@@ -31,6 +31,14 @@ if test "$found_cunit" = "no" ; then
]) ])
fi fi
dnl check libxml2
PKG_CHECK_MODULES(LIBXML2, [libxml-2.0] ,[libxml2_found=yes] ,foo=bar)
if test "$libxml2_found" != "yes" ; then
AC_MSG_WARN([libxml2 not found. Disabling cache.)])
else
AC_DEFINE(HAVE_LIBXML2,1,[defined when libxml2 is available]) ]
fi
if test "$found_cunit" = "no" ; then if test "$found_cunit" = "no" ; then
AC_MSG_WARN([Could not find cunit framework, tests are not compiled.]) AC_MSG_WARN([Could not find cunit framework, tests are not compiled.])
else else
......
...@@ -195,4 +195,18 @@ __attribute__ ((visibility ("default"))) int bzrtp_isSecure(bzrtpContext_t *zrtp ...@@ -195,4 +195,18 @@ __attribute__ ((visibility ("default"))) int bzrtp_isSecure(bzrtpContext_t *zrtp
*/ */
__attribute__ ((visibility ("default"))) int bzrtp_processMessage(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *zrtpPacketString, uint16_t zrtpPacketStringLength); __attribute__ ((visibility ("default"))) int bzrtp_processMessage(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *zrtpPacketString, uint16_t zrtpPacketStringLength);
/**
* @brief Called by user when the SAS has been verified
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
*/
__attribute__ ((visibility ("default"))) void bzrtp_SASVerified(bzrtpContext_t *zrtpContext);
/**
* @brief Called by user when the SAS has been set to unverified
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
*/
__attribute__ ((visibility ("default"))) void bzrtp_resetSASVerified(bzrtpContext_t *zrtpContext);
#endif /* ifndef BZRTP_H */ #endif /* ifndef BZRTP_H */
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#define RESPONDER 1 #define RESPONDER 1
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
typedef struct bzrtpChannelContext_struct bzrtpChannelContext_t; typedef struct bzrtpChannelContext_struct bzrtpChannelContext_t;
...@@ -71,7 +70,8 @@ typedef struct bzrtpTimer_struct { ...@@ -71,7 +70,8 @@ typedef struct bzrtpTimer_struct {
uint8_t timerStep; /**< in ms. Step between next timer fire: used to reset firingTime for next timer fire */ uint8_t timerStep; /**< in ms. Step between next timer fire: used to reset firingTime for next timer fire */
} bzrtpTimer_t; } bzrtpTimer_t;
/* the rs1 and rs2 are 256 bits long - see rfc section 4.6.1 */
#define RETAINED_SECRET_LENGTH 32
/** /**
* @brief A set of cached secrets retrieved from the cache as defined * @brief A set of cached secrets retrieved from the cache as defined
*/ */
...@@ -84,6 +84,7 @@ typedef struct cachedSecrets_struct { ...@@ -84,6 +84,7 @@ typedef struct cachedSecrets_struct {
uint8_t auxsecretLength; /**< auxiliary secret length in bytes */ uint8_t auxsecretLength; /**< auxiliary secret length in bytes */
uint8_t *pbxsecret; /**< PBX secret */ uint8_t *pbxsecret; /**< PBX secret */
uint8_t pbxsecretLength; /**< PBX secret length in bytes */ uint8_t pbxsecretLength; /**< PBX secret length in bytes */
uint8_t previouslyVerifiedSas; /* boolean, is a SAS has been previously verified with this user */
} cachedSecrets_t; } cachedSecrets_t;
/** /**
...@@ -101,8 +102,8 @@ typedef struct cachedSecretsHash_struct { ...@@ -101,8 +102,8 @@ typedef struct cachedSecretsHash_struct {
*/ */
typedef struct zrtpCallbacks_struct { typedef struct zrtpCallbacks_struct {
/* cache related functions */ /* cache related functions */
int (* bzrtp_loadCache)(uint8_t **cacheBuffer, uint32_t *cacheBufferSize); /**< Cache related function : load the whole cache file in a buffer allocated by the function, return the buffer and its size in bytes */ int (* bzrtp_loadCache)(void *clientData, uint8_t **cacheBuffer, uint32_t *cacheBufferSize); /**< Cache related function : load the whole cache file in a buffer allocated by the function, return the buffer and its size in bytes */
int (* bzrtp_writeCache)(uint8_t *input, uint32_t size); /**< Cache related function : write size bytes to cache */ int (* bzrtp_writeCache)(void *clientData, uint8_t *input, uint32_t size); /**< Cache related function : write size bytes to cache */
/* sending packets */ /* sending packets */
int (* bzrtp_sendData)(void *clientData, uint8_t *packetString, uint16_t packetLength); /**< Send a ZRTP packet to peer. Shall return 0 on success */ int (* bzrtp_sendData)(void *clientData, uint8_t *packetString, uint16_t packetLength); /**< Send a ZRTP packet to peer. Shall return 0 on success */
......
...@@ -30,7 +30,8 @@ ...@@ -30,7 +30,8 @@
#include "typedef.h" #include "typedef.h"
#define ZRTP_ZIDCACHE_INVALID_CONTEXT 0x2001 #define ZRTP_ZIDCACHE_INVALID_CONTEXT 0x2001
#define ZRTP_ZIDCACHE_UNABLETOUPDATE 0x2002 #define ZRTP_ZIDCACHE_INVALID_CACHE 0x2002
#define ZRTP_ZIDCACHE_UNABLETOUPDATE 0x2003
/** /**
* @brief : retrieve ZID from cache * @brief : retrieve ZID from cache
...@@ -55,4 +56,18 @@ int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]); ...@@ -55,4 +56,18 @@ int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]);
*/ */
int bzrtp_getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[12]); int bzrtp_getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[12]);
/**
* @brief Write the given taf into peer Node, if the tag exists, content is replaced
* Cache file is locked(TODO), read and updated during this call
*
* @param[in/out] context the current context, used to get the negotiated Hash algorithm and cache access functions and store result
* @param[in] peerZID a byte array of the peer ZID
* @param[in] tagName the tagname of node to be written, it MUST be null terminated
* @param[in] tagNameLength the length of tagname (not including the null termination char)
* @param[in] tagContent the content of the node(a byte buffer which will be converted to hexa string)
* @param[in] tagContentLength the length of the content to be written
*
* return 0 on success, error code otherwise
*/
int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *tagName, uint8_t tagNameLength, uint8_t *tagContent, uint32_t tagContentLength);
#endif /* ZIDCACHE_H */ #endif /* ZIDCACHE_H */
lib_LTLIBRARIES = libbzrtp.la lib_LTLIBRARIES = libbzrtp.la
libbzrtp_la_LIBADD= $(LIBXML2_LIBS)
libbzrtp_la_SOURCES= bzrtp.c cryptoPolarssl.c cryptoUtils.c packetParser.c zidCache.c stateMachine.c libbzrtp_la_SOURCES= bzrtp.c cryptoPolarssl.c cryptoUtils.c packetParser.c zidCache.c stateMachine.c
libbzrtp_la_LDFLAGS=-fvisibility=hidden -no-undefined libbzrtp_la_LDFLAGS=-fvisibility=hidden -no-undefined
AM_CPPFLAGS= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
AM_CFLAGS=$(LIBXML2_CFLAGS)
...@@ -109,15 +109,14 @@ bzrtpContext_t *bzrtp_createBzrtpContext(uint32_t selfSSRC) ...@@ -109,15 +109,14 @@ bzrtpContext_t *bzrtp_createBzrtpContext(uint32_t selfSSRC)
/** /**
* @brief Perform some initialisation which can't be done without some callback functions: * @brief Perform some initialisation which can't be done without some callback functions:
* - get ZID * This function is called once per session when the first channel is created.
* It must be called after the cache callback function have been set
* - load cache
* - get ZID from cache or generate it
* *
* @param[in] context The context to initialise * @param[in] context The context to initialise
*/ */
void bzrtp_initBzrtpContext(bzrtpContext_t *context) { void bzrtp_initBzrtpContext(bzrtpContext_t *context) {
/* load the cache buffer */
if (context->zrtpCallbacks.bzrtp_loadCache != 0) {
context->zrtpCallbacks.bzrtp_loadCache(&context->cacheBuffer, &(context->cacheBufferLength));
}
/* initialise ZID. Randomly generated if no ZID is found in cache or no cache found */ /* initialise ZID. Randomly generated if no ZID is found in cache or no cache found */
bzrtp_getSelfZID(context, context->selfZID); bzrtp_getSelfZID(context, context->selfZID);
...@@ -192,10 +191,10 @@ void bzrtp_destroyBzrtpContext(bzrtpContext_t *context, uint32_t selfSSRC) ...@@ -192,10 +191,10 @@ void bzrtp_destroyBzrtpContext(bzrtpContext_t *context, uint32_t selfSSRC)
int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_t functionID) { int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_t functionID) {
switch (functionID) { switch (functionID) {
case ZRTP_CALLBACK_LOADCACHE: case ZRTP_CALLBACK_LOADCACHE:
context->zrtpCallbacks.bzrtp_loadCache = (int (*)(uint8_t **, uint32_t *))functionPointer; context->zrtpCallbacks.bzrtp_loadCache = (int (*)(void *, uint8_t **, uint32_t *))functionPointer;
break; break;
case ZRTP_CALLBACK_WRITECACHE: case ZRTP_CALLBACK_WRITECACHE:
context->zrtpCallbacks.bzrtp_writeCache = (int (*)(uint8_t *, uint32_t))functionPointer; context->zrtpCallbacks.bzrtp_writeCache = (int (*)(void *, uint8_t *, uint32_t))functionPointer;
break; break;
case ZRTP_CALLBACK_SENDDATA: case ZRTP_CALLBACK_SENDDATA:
context->zrtpCallbacks.bzrtp_sendData = (int (*)(void *, uint8_t *, uint16_t))functionPointer; context->zrtpCallbacks.bzrtp_sendData = (int (*)(void *, uint8_t *, uint16_t))functionPointer;
...@@ -308,7 +307,6 @@ int bzrtp_startChannelEngine(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) { ...@@ -308,7 +307,6 @@ int bzrtp_startChannelEngine(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
int bzrtp_iterate(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint64_t timeReference) { int bzrtp_iterate(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint64_t timeReference) {
/* get channel context */ /* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC); bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
fflush(NULL);
if (zrtpChannelContext == NULL) { if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT; return BZRTP_ERROR_INVALIDCONTEXT;
...@@ -424,6 +422,32 @@ int bzrtp_isSecure(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) { ...@@ -424,6 +422,32 @@ int bzrtp_isSecure(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
} }
/*
* @brief Called by user when the SAS has been verified
* update the cache(if any) to set the previously verified flag
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
*/
void bzrtp_SASVerified(bzrtpContext_t *zrtpContext) {
if (zrtpContext != NULL) {
uint8_t pvsFlag = 1;
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"pvs", 3, &pvsFlag, 1);
}
}
/*
* @brief Called by user when the SAS has been set to unverified
* update the cache(if any) to unset the previously verified flag
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
*/
void bzrtp_resetSASVerified(bzrtpContext_t *zrtpContext) {
if (zrtpContext != NULL) {
uint8_t pvsFlag = 0;
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"pvs", 3, &pvsFlag, 1);
}
}
/* Local functions implementation */ /* Local functions implementation */
/** /**
......
...@@ -139,7 +139,6 @@ bzrtpPacket_t *bzrtp_packetCheck(const uint8_t * input, uint16_t inputLength, ui ...@@ -139,7 +139,6 @@ bzrtpPacket_t *bzrtp_packetCheck(const uint8_t * input, uint16_t inputLength, ui
* TODO: what if we got a Sequence Number overflowing the 16 bits ? */ * TODO: what if we got a Sequence Number overflowing the 16 bits ? */
uint16_t sequenceNumber = (((uint16_t)input[2])<<8) | ((uint16_t)input[3]); uint16_t sequenceNumber = (((uint16_t)input[2])<<8) | ((uint16_t)input[3]);
if (sequenceNumber <= lastValidSequenceNumber) { if (sequenceNumber <= lastValidSequenceNumber) {
printf("Sequence number check last %d current %d", lastValidSequenceNumber, sequenceNumber);
*exitCode = BZRTP_PARSER_ERROR_OUTOFORDER; *exitCode = BZRTP_PARSER_ERROR_OUTOFORDER;
return NULL; return NULL;
} }
...@@ -1219,7 +1218,7 @@ bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelC ...@@ -1219,7 +1218,7 @@ bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelC
zrtpConfirmMessage->sig_len = 0; /* signature is not supported */ zrtpConfirmMessage->sig_len = 0; /* signature is not supported */
zrtpConfirmMessage->cacheExpirationInterval = 0xFFFFFFFF; /* expiration interval is set to unlimited as recommended in rfc section 4.9 */ zrtpConfirmMessage->cacheExpirationInterval = 0xFFFFFFFF; /* expiration interval is set to unlimited as recommended in rfc section 4.9 */
zrtpConfirmMessage->E = 0; /* we are not a PBX and then will never signal an enrollment - rfc section 7.3.1 */ zrtpConfirmMessage->E = 0; /* we are not a PBX and then will never signal an enrollment - rfc section 7.3.1 */
zrtpConfirmMessage->V = 0; /* TODO: this one shall be read from the cache - rfc section 7.1 */ zrtpConfirmMessage->V = zrtpContext->cachedSecret.previouslyVerifiedSas;
zrtpConfirmMessage->A = 0; /* Go clear message is not supported - rfc section 4.7.2 */ zrtpConfirmMessage->A = 0; /* Go clear message is not supported - rfc section 4.7.2 */
zrtpConfirmMessage->D = 0; /* The is no backdoor in our implementation of ZRTP - rfc section 11 */ zrtpConfirmMessage->D = 0; /* The is no backdoor in our implementation of ZRTP - rfc section 11 */
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "string.h" #include <string.h>
#include "typedef.h" #include "typedef.h"
#include "packetParser.h" #include "packetParser.h"
#include "cryptoUtils.h" #include "cryptoUtils.h"
...@@ -35,11 +35,12 @@ ...@@ -35,11 +35,12 @@
/* Local functions prototypes */ /* Local functions prototypes */
int bzrtp_turnIntoResponder(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket, bzrtpCommitMessage_t *commitMessage); int bzrtp_turnIntoResponder(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket, bzrtpCommitMessage_t *commitMessage);
int bzrtp_responseToHelloMessage(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket, bzrtpStateMachine_t nextState); int bzrtp_responseToHelloMessage(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket);
int bzrtp_computeS0DHMMode(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext); int bzrtp_computeS0DHMMode(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
int bzrtp_computeS0MultiStreamMode(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext); int bzrtp_computeS0MultiStreamMode(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
int bzrtp_deriveKeysFromS0(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext); int bzrtp_deriveKeysFromS0(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
int bzrtp_deriveSrtpKeysFromS0(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext); int bzrtp_deriveSrtpKeysFromS0(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
int bzrtp_updateCachedSecrets(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
/* /*
* @brief This is the initial state * @brief This is the initial state
...@@ -108,11 +109,16 @@ int state_discovery_init(bzrtpEvent_t event) { ...@@ -108,11 +109,16 @@ int state_discovery_init(bzrtpEvent_t event) {
/* if we have an Hello packet, we must use it to determine which algo we will agree on */ /* if we have an Hello packet, we must use it to determine which algo we will agree on */
if (zrtpPacket->messageType == MSGTYPE_HELLO) { if (zrtpPacket->messageType == MSGTYPE_HELLO) {
retval = bzrtp_responseToHelloMessage(zrtpContext, zrtpChannelContext, zrtpPacket, state_discovery_waitingForHelloAck); retval = bzrtp_responseToHelloMessage(zrtpContext, zrtpChannelContext, zrtpPacket);
if (retval != 0) { if (retval != 0) {
return retval; return retval;
} }
/* reset the sending Hello timer as peer may have started slowly and lost all our Hello packets */
zrtpChannelContext->timer.status = BZRTP_TIMER_ON;
zrtpChannelContext->timer.firingTime = 0;
zrtpChannelContext->timer.firingCount = 0;
zrtpChannelContext->timer.timerStep = HELLO_BASE_RETRANSMISSION_STEP;
/* set next state (do not call it as we will just be waiting for a HelloACK packet from peer, nothing to do) */ /* set next state (do not call it as we will just be waiting for a HelloACK packet from peer, nothing to do) */
zrtpChannelContext->stateMachine = state_discovery_waitingForHelloAck; zrtpChannelContext->stateMachine = state_discovery_waitingForHelloAck;
...@@ -204,7 +210,7 @@ int state_discovery_waitingForHello(bzrtpEvent_t event) { ...@@ -204,7 +210,7 @@ int state_discovery_waitingForHello(bzrtpEvent_t event) {
/* packet is valid, set the sequence Number in channel context */ /* packet is valid, set the sequence Number in channel context */
zrtpChannelContext->peerSequenceNumber = zrtpPacket->sequenceNumber; zrtpChannelContext->peerSequenceNumber = zrtpPacket->sequenceNumber;
retval = bzrtp_responseToHelloMessage(zrtpContext, zrtpChannelContext, zrtpPacket, state_discovery_waitingForHelloAck); retval = bzrtp_responseToHelloMessage(zrtpContext, zrtpChannelContext, zrtpPacket);
if (retval != 0) { if (retval != 0) {
return retval; return retval;
} }
...@@ -480,28 +486,41 @@ int state_keyAgreement_sendingCommit(bzrtpEvent_t event) { ...@@ -480,28 +486,41 @@ int state_keyAgreement_sendingCommit(bzrtpEvent_t event) {
/* Check shared secret hash found in the DHPart1 message */ /* Check shared secret hash found in the DHPart1 message */
/* if we do not have the secret, don't check it as we do not expect the other part to have it neither */ /* if we do not have the secret, don't check it as we do not expect the other part to have it neither */
/* TODO: in case of cache mismatch, warn the user and erase secret as it must not be used to compute s0 */
if (zrtpContext->cachedSecret.rs1!=NULL) { if (zrtpContext->cachedSecret.rs1!=NULL) {
if (memcmp(zrtpContext->initiatorCachedSecretHash.rs1ID, dhPart1Message->rs1ID,8) != 0) { if (memcmp(zrtpContext->responderCachedSecretHash.rs1ID, dhPart1Message->rs1ID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.rs1);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.rs1= NULL;
zrtpContext->cachedSecret.rs1Length = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
if (zrtpContext->cachedSecret.rs2!=NULL) { if (zrtpContext->cachedSecret.rs2!=NULL) {
if (memcmp(zrtpContext->initiatorCachedSecretHash.rs2ID, dhPart1Message->rs2ID,8) != 0) { if (memcmp(zrtpContext->responderCachedSecretHash.rs2ID, dhPart1Message->rs2ID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.rs2);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.rs2= NULL;
zrtpContext->cachedSecret.rs2Length = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
if (zrtpContext->cachedSecret.auxsecret!=NULL) { if (zrtpContext->cachedSecret.auxsecret!=NULL) {
if (memcmp(zrtpChannelContext->initiatorAuxsecretID, dhPart1Message->auxsecretID,8) != 0) { if (memcmp(zrtpChannelContext->responderAuxsecretID, dhPart1Message->auxsecretID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.auxsecret);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.auxsecret= NULL;
zrtpContext->cachedSecret.auxsecretLength = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
if (zrtpContext->cachedSecret.pbxsecret!=NULL) { if (zrtpContext->cachedSecret.pbxsecret!=NULL) {
if (memcmp(zrtpContext->initiatorCachedSecretHash.pbxsecretID, dhPart1Message->pbxsecretID,8) != 0) { if (memcmp(zrtpContext->responderCachedSecretHash.pbxsecretID, dhPart1Message->pbxsecretID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.pbxsecret);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.pbxsecret= NULL;
zrtpContext->cachedSecret.pbxsecretLength = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
...@@ -711,26 +730,38 @@ int state_keyAgreement_responderSendingDHPart1(bzrtpEvent_t event) { ...@@ -711,26 +730,38 @@ int state_keyAgreement_responderSendingDHPart1(bzrtpEvent_t event) {
/* if we do not have the secret, don't check it as we do not expect the other part to have it neither */ /* if we do not have the secret, don't check it as we do not expect the other part to have it neither */
if (zrtpContext->cachedSecret.rs1!=NULL) { if (zrtpContext->cachedSecret.rs1!=NULL) {
if (memcmp(zrtpContext->initiatorCachedSecretHash.rs1ID, dhPart2Message->rs1ID,8) != 0) { if (memcmp(zrtpContext->initiatorCachedSecretHash.rs1ID, dhPart2Message->rs1ID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.rs1);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.rs1= NULL;
zrtpContext->cachedSecret.rs1Length = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
if (zrtpContext->cachedSecret.rs2!=NULL) { if (zrtpContext->cachedSecret.rs2!=NULL) {
if (memcmp(zrtpContext->initiatorCachedSecretHash.rs2ID, dhPart2Message->rs2ID,8) != 0) { if (memcmp(zrtpContext->initiatorCachedSecretHash.rs2ID, dhPart2Message->rs2ID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.rs2);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.rs2= NULL;
zrtpContext->cachedSecret.rs2Length = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
if (zrtpContext->cachedSecret.auxsecret!=NULL) { if (zrtpContext->cachedSecret.auxsecret!=NULL) {
if (memcmp(zrtpChannelContext->initiatorAuxsecretID, dhPart2Message->auxsecretID,8) != 0) { if (memcmp(zrtpChannelContext->initiatorAuxsecretID, dhPart2Message->auxsecretID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.auxsecret);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.auxsecret= NULL;
zrtpContext->cachedSecret.auxsecretLength = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
if (zrtpContext->cachedSecret.pbxsecret!=NULL) { if (zrtpContext->cachedSecret.pbxsecret!=NULL) {
if (memcmp(zrtpContext->initiatorCachedSecretHash.pbxsecretID, dhPart2Message->pbxsecretID,8) != 0) { if (memcmp(zrtpContext->initiatorCachedSecretHash.pbxsecretID, dhPart2Message->pbxsecretID,8) != 0) {
bzrtp_freeZrtpPacket(zrtpPacket); free(zrtpContext->cachedSecret.pbxsecret);
return BZRTP_ERROR_CACHEMISMATCH; zrtpContext->cachedSecret.pbxsecret= NULL;
zrtpContext->cachedSecret.pbxsecretLength = 0;
/*bzrtp_freeZrtpPacket(zrtpPacket);
return BZRTP_ERROR_CACHEMISMATCH;*/
} }
} }
...@@ -1077,6 +1108,9 @@ int state_confirmation_responderSendingConfirm1(bzrtpEvent_t event) { ...@@ -1077,6 +1108,9 @@ int state_confirmation_responderSendingConfirm1(bzrtpEvent_t event) {
if (retval!=0) { if (retval!=0) {
return retval; return retval;
} }
/* compute and update in cache the retained shared secret */
bzrtp_updateCachedSecrets(zrtpContext, zrtpChannelContext);
/* send them to the environment for receiver as we may receive a srtp packet in response to our conf2ACK */ /* send them to the environment for receiver as we may receive a srtp packet in response to our conf2ACK */
if (zrtpContext->zrtpCallbacks.bzrtp_srtpSecretsAvailable != NULL) { if (zrtpContext->zrtpCallbacks.bzrtp_srtpSecretsAvailable != NULL) {
...@@ -1244,6 +1278,9 @@ int state_confirmation_initiatorSendingConfirm2(bzrtpEvent_t event) { ...@@ -1244,6 +1278,9 @@ int state_confirmation_initiatorSendingConfirm2(bzrtpEvent_t event) {
/* stop the retransmission timer */ /* stop the retransmission timer */
zrtpChannelContext->timer.status = BZRTP_TIMER_OFF; zrtpChannelContext->timer.status = BZRTP_TIMER_OFF;
/* compute and update in cache the retained shared secret */
bzrtp_updateCachedSecrets(zrtpContext, zrtpChannelContext);
/* send the sender srtp keys to the client(we sent receiver only when the first confirm1 packet arrived) */ /* send the sender srtp keys to the client(we sent receiver only when the first confirm1 packet arrived) */
if (zrtpContext->zrtpCallbacks.bzrtp_srtpSecretsAvailable != NULL) { if (zrtpContext->zrtpCallbacks.bzrtp_srtpSecretsAvailable != NULL) {
zrtpContext->zrtpCallbacks.bzrtp_srtpSecretsAvailable(zrtpChannelContext->clientData, &zrtpChannelContext->srtpSecrets, ZRTP_SRTP_SECRETS_FOR_SENDER); zrtpContext->zrtpCallbacks.bzrtp_srtpSecretsAvailable(zrtpChannelContext->clientData, &zrtpChannelContext->srtpSecrets, ZRTP_SRTP_SECRETS_FOR_SENDER);
...@@ -1324,7 +1361,7 @@ int state_secure(bzrtpEvent_t event) { ...@@ -1324,7 +1361,7 @@ int state_secure(bzrtpEvent_t event) {
/* call the environment to signal we're ready to operate */ /* call the environment to signal we're ready to operate */
if (zrtpContext->zrtpCallbacks.bzrtp_startSrtpSession!= NULL) { if (zrtpContext->zrtpCallbacks.bzrtp_startSrtpSession!= NULL) {
zrtpContext->zrtpCallbacks.bzrtp_startSrtpSession(zrtpChannelContext->clientData, zrtpChannelContext->srtpSecrets.sas, 0); /* TODO: last param is the verified flag but we are cacheless for now so always 0*/ zrtpContext->zrtpCallbacks.bzrtp_startSrtpSession(zrtpChannelContext->clientData, zrtpChannelContext->srtpSecrets.sas, zrtpContext->cachedSecret.previouslyVerifiedSas);
} }
return 0; return 0;
} }
...@@ -1480,7 +1517,7 @@ int bzrtp_turnIntoResponder(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t * ...@@ -1480,7 +1517,7 @@ int bzrtp_turnIntoResponder(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *
* *
* @return 0 on succes, error code otherwise * @return 0 on succes, error code otherwise
*/ */
int bzrtp_responseToHelloMessage(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket, bzrtpStateMachine_t nextState) { int bzrtp_responseToHelloMessage(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket) {
int retval; int retval;
bzrtpHelloMessage_t *helloMessage = (bzrtpHelloMessage_t *)zrtpPacket->messageData; bzrtpHelloMessage_t *helloMessage = (bzrtpHelloMessage_t *)zrtpPacket->messageData;
...@@ -1559,6 +1596,7 @@ int bzrtp_responseToHelloMessage(bzrtpContext_t *zrtpContext, bzrtpChannelContex ...@@ -1559,6 +1596,7 @@ int bzrtp_responseToHelloMessage(bzrtpContext_t *zrtpContext, bzrtpChannelContex
/* When in PreShared mode Derive ZRTPSess, s0 from the retained secret and then all the other keys */ /* When in PreShared mode Derive ZRTPSess, s0 from the retained secret and then all the other keys */
if ((zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh)) { if ((zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh)) {
/*TODO*/
} else if (zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult) { /* when in Multistream mode, do nothing, will derive s0 from ZRTPSess when we know who is initiator */ } else if (zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult) { /* when in Multistream mode, do nothing, will derive s0 from ZRTPSess when we know who is initiator */
...@@ -1980,3 +2018,45 @@ int bzrtp_deriveSrtpKeysFromS0(bzrtpContext_t *zrtpContext, bzrtpChannelContext_ ...@@ -1980,3 +2018,45 @@ int bzrtp_deriveSrtpKeysFromS0(bzrtpContext_t *zrtpContext, bzrtpChannelContext_
return 0; return 0;
} }
/*
* @brief Compute the new rs1 and update the cached secrets according to rfc section 4.6.1
*
* param[in] zrtpContext The context we are operation on
* param[in/out] zrtpChannelContext The channel context we are operation on(contains s0)
*
* return 0 on success, error code otherwise
*/
int bzrtp_updateCachedSecrets(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext) {
/* if this channel context is in multistream mode, do nothing */
if (zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult) {
/* destroy s0 */
bzrtp_DestroyKey(zrtpChannelContext->s0, zrtpChannelContext->hashLength, zrtpContext->RNGContext);
free(zrtpChannelContext->s0);
zrtpChannelContext->s0 = NULL;
return 0;
}
/* if this channel context is not in DHM mode, backup rs1 in rs2 if it exists */
if (zrtpChannelContext->keyAgreementAlgo != ZRTP_KEYAGREEMENT_Prsh) {
if (zrtpContext->cachedSecret.rs1 != NULL) {
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"rs2", 3, zrtpContext->cachedSecret.rs1, zrtpContext->cachedSecret.rs1Length);
}
}
/* compute rs1 = KDF(s0, "retained secret", KDF_Context, 256) */
if (zrtpContext->cachedSecret.rs1 == NULL) {
zrtpContext->cachedSecret.rs1 = (uint8_t *)malloc(RETAINED_SECRET_LENGTH);
zrtpContext->cachedSecret.rs1Length = RETAINED_SECRET_LENGTH;
}
bzrtp_keyDerivationFunction(zrtpChannelContext->s0, zrtpChannelContext->hashLength, (uint8_t *)"retained secret", 15, zrtpChannelContext->KDFContext, zrtpChannelContext->KDFContextLength, 32, (void (*)(uint8_t *, uint8_t, uint8_t *, uint32_t, uint8_t, uint8_t *))zrtpChannelContext->hmacFunction, zrtpContext->cachedSecret.rs1);
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"rs1", 3, zrtpContext->cachedSecret.rs1, zrtpContext->cachedSecret.rs1Length);
/* destroy s0 */
bzrtp_DestroyKey(zrtpChannelContext->s0, zrtpChannelContext->hashLength, zrtpContext->RNGContext);
free(zrtpChannelContext->s0);
zrtpChannelContext->s0 = NULL;
return 0;
}
This diff is collapsed.
<selfZID>3e6adbe0a8e7755d30d18a24</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>c6e2b22e272ae149461098077d4790b36798bebf800fd74b7c09958746115ed1</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux></peer> <?xml version="1.0" encoding="UTF-8"?>
<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>7d4fa5bcebbfa03ca2141036ba2c060f6ef76c62cfb6d1857f377a5f55c4182c</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>99423ca64fd139a5352a571f31ecc65b3f15fd0c3bc39b710526752acb82819e</rs2></peer></cache>
<selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>3e6adbe0a8e7755d30d18a24</ZID><rs1>c6e2b22e272ae149461098077d4790b36798bebf800fd74b7c09958746115ed1</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux></peer> <?xml version="1.0" encoding="UTF-8"?>
<cache><selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>ef7692d0792a67491ae2d44e</ZID><rs1>7d4fa5bcebbfa03ca2141036ba2c060f6ef76c62cfb6d1857f377a5f55c4182c</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>99423ca64fd139a5352a571f31ecc65b3f15fd0c3bc39b710526752acb82819e</rs2></peer></cache>
...@@ -211,9 +211,19 @@ void test_parser(void) { ...@@ -211,9 +211,19 @@ void test_parser(void) {
} }
/* context structure mainly used by statemachine test, but also needed by parserComplete to get the zid Filename */
typedef struct my_Context_struct {
unsigned char nom[30]; /* nom du contexte */
bzrtpContext_t *peerContext;
bzrtpChannelContext_t *peerChannelContext;
<