Commit 0f8f594e authored by johan's avatar johan

Add the state machine with multichannel support

Not functionnal yet
parent 532eab69
......@@ -58,7 +58,7 @@ if test $GCC = yes && test $wall_werror = yes; then
CFLAGS="$CFLAGS -Werror "
fi
LIBS="$LIBS -lpolarssl -lm"
LIBS="$LIBS -lpolarssl "
# Create the following files from their .in counterparts
AC_CONFIG_FILES([
......
......@@ -50,6 +50,7 @@ typedef struct bzrtpSrtpSecrets_struct {
#define BZRTP_ERROR_INVALIDCONTEXT 0x0004
#define BZRTP_ERROR_MULTICHANNELNOTSUPPORTEDBYPEER 0x0008
#define BZRTP_ERROR_UNABLETOADDCHANNEL 0x0010
#define BZRTP_ERROR_UNABLETOSTARTCHANNEL 0x0020
/**
* @brief bzrtpContext_t The ZRTP engine context
* Store current state, timers, HMAC and encryption keys
......@@ -86,23 +87,73 @@ __attribute__ ((visibility ("default"))) void bzrtp_destroyBzrtpContext(bzrtpCon
#define ZRTP_CALLBACK_WRITECACHE 0x0102
#define ZRTP_CALLBACK_SETCACHEPOSITION 0x0104
#define ZRTP_CALLBACK_GETCACHEPOSITION 0x0108
#define ZRTP_CALLBACK_SENDDATA 0x0110
/**
* @brief Allocate a function pointer to the callback function identified by his id
* @param[in] functionPointer The pointer to the function to bind as callback.
* @param[in] functionID The ID as defined above to identify which callback to be set.
* @param[in/out] context The zrtp context to set the callback function
* @param[in] functionPointer The pointer to the function to bind as callback.
* @param[in] functionID The ID as defined above to identify which callback to be set.
*
* @return 0 on success
*
*/
__attribute__ ((visibility ("default"))) int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_t functionID);
/**
* @brief Set the client data pointer in a channel context
* This pointer is returned to the client by the callbacks function, used to store associated contexts (RTP session)
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel to be linked to the client Data
* @param[in] clientData The clientData pointer, casted to a (void *)
*
* @return 0 on success
*
*/
__attribute__ ((visibility ("default"))) int bzrtp_setClientData(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, void *clientData);
/**
* @brief Add a channel to an existing context, this can be done only if the first channel has concluded a DH key agreement
*
* @param[in] selfSSRC The SSRC given to the channel context
* @param[in/out] zrtpContext The zrtp context who will get the additionnal channel. Must be in secure state.
* @param[in] selfSSRC The SSRC given to the channel context
*
* @return 0 on succes, error code otherwise
*/
__attribute__ ((visibility ("default"))) int bzrtp_addChannel(bzrtpContext_t *zrtpContext, uint32_t selfSSRC);
/**
* @brief Start the state machine of the specified channel
*
* @param[in/out] zrtpContext The ZRTP context hosting the channel to be started
* @param[in] selfSSRC The SSRC identifying the channel to be started(will start sending Hello packets and listening for some)
*
* @return 0 on succes, error code otherwise
*/
__attribute__ ((visibility ("default"))) int bzrtp_startChannelEngine(bzrtpContext_t *zrtpContext, uint32_t selfSSRC);
/**
* @brief Send the current time to a specified channel, it will check if it has to trig some timer
*
* @param[in/out] zrtpContext The ZRTP context hosting the channel
* @param[in] selfSSRC The SSRC identifying the channel
* @param[in] timeReference The current time in ms
*
* @return 0 on succes, error code otherwise
*/
__attribute__ ((visibility ("default"))) int bzrtp_iterate(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint64_t timeReference);
/**
* @brief Process a received message
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel receiving the message
* @param[in] zrtpPacketString The packet received
* @param[in] zrtpPacketStringLength Length of the packet in bytes
*
* @return 0 on success, errorcode otherwise
*/
__attribute__ ((visibility ("default"))) int bzrtp_processMessage(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *zrtpPacketString, uint16_t zrtpPacketStringLength);
#endif /* ifndef BZRTP_H */
......@@ -28,8 +28,9 @@
#include "bzrtp/bzrtp.h"
/* header of ZRTP packet is 12 bytes : Preambule/Sequence Number + ZRTP Magic Cookie + SSRC */
#define ZRTP_PACKET_HEADER_LENGTH 12
#define ZRTP_PACKET_CRC_LENGTH 4
#define ZRTP_PACKET_HEADER_LENGTH 12
#define ZRTP_PACKET_CRC_LENGTH 4
#define ZRTP_PACKET_OVERHEAD 16
#define BZRTP_PARSER_ERROR_INVALIDCRC 0xa001
#define BZRTP_PARSER_ERROR_INVALIDPACKET 0xa002
......
/**
@file stateMachine.h
@brief The state machine implementing the ZRTP protocol
Each state is defined as a function pointer and on arrival of a new event
after sanity checks, the state function is called giving the event as parameter
On a transition, the next state is called with the event which generated the transition
@author Johan Pascal
@copyright Copyright (C) 2014 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
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef STATEMACHINE_H
#define STATEMACHINE_H
#include "typedef.h"
/* types definition for event and state function */
/* the INIT event type is used to run some state for the firt time : create packet and send it */
#define BZRTP_EVENT_INIT 0
#define BZRTP_EVENT_MESSAGE 1
#define BZRTP_EVENT_TIMER 2
/* error code definition */
#define BZRTP_ERROR_UNSUPPORTEDZRTPVERSION 0xe001
#define BZRTP_ERROR_UNMATCHINGPACKETREPETITION 0xe002
#define BZRTP_ERROR_CACHEMISMATCH 0xe004
/**
* @brief The event type, used as a parameter for the state function
*/
typedef struct bzrtpEvent_struct {
uint8_t eventType; /**< Event can be a message or a timer's end */
uint8_t *bzrtpPacketString; /**< a pointer to the zrtp packet string, NULL in case of timer event */
uint16_t bzrtpPacketStringLength; /**< the length of packet string in bytes */
bzrtpContext_t *zrtpContext; /**< the current ZRTP context */
bzrtpChannelContext_t *zrtpChannelContext; /**< the current ZRTP channel hosting this state machine context */
} bzrtpEvent_t;
/**
* @brief the state function pointer definition
*/
typedef int (*bzrtpStateMachine_t)(bzrtpEvent_t);
/* state functions prototypes, split in categories corresponding to the differents protocol phases: discovery, key agreement, confirmation */
/**
* @brief This is the initial state
* On first call, we will create the Hello message and start sending it until we receive an helloACK or a hello message from peer
*
* Arrives from :
* - This is the initial state
* Goes to:
* - state_discovery_waitingForHello upon HelloACK reception
* - state_discovery_waitingForHelloAck upon Hello reception
* Send :
* - Hello until timer's end or transition
*/
int state_discovery_init(bzrtpEvent_t event);
/**
* @brief Arrives in this state coming from init upon reception on Hello ACK, we are now waiting for the Hello packet from peer
*
* Arrives from :
* - state_discovery_init upon HelloACK reception
* Goes to:
* - state_keyAgreement_sendingCommit upon Hello reception
* Send :
* - HelloACK on Hello reception
*
*/
int state_discovery_waitingForHello(bzrtpEvent_t event);
/**
* @brief We are now waiting for the HelloACK packet from peer or a Commit packet
*
* Arrives from :
* - state_discovery_init upon Hello reception
* Goes to:
* - state_keyAgreement_sendingCommit upon HelloACK reception
* - state_keyAgreement_responderSendingDHPart1 upon Commit reception in DHM mode
* - state_confirmation_responderSendingConfirm1 upon Commit reception in non DHM mode
* Send :
* - Hello until timer's end or transition
* - HelloACK on Hello reception
*
*/
int state_discovery_waitingForHelloAck(bzrtpEvent_t event);
/**
* @brief For any kind of key agreement (DHM, Mult, PreShared), we keep sending commit.
*
* Arrives from :
* - state_discovery_waitingForHello upon Hello received
* - state_discovery_waitingForHelloAck upon HelloACK received
* Goes to:
* - state_keyAgreement_initiatorSendingDHPart2 upon DHPart1 reception in DHM mode
* - state_confirmation_initiatorSendingConfirm2 upon Confirm1 reception in non DHM mode
* - state_keyAgreement_responderSendingDHPart1 upon Commit reception in DHM mode and commit contention gives us the responder role
* - state_confirmation_responderSendingConfirm1 upon Commit reception in non DHM mode and commit contention gives us the responder role
* Send :
* - Commit until timer's end or transition
* - HelloACK on Hello reception
*
*/
int state_keyAgreement_sendingCommit(bzrtpEvent_t event);
/**
* @brief For DHM mode only, responder send DHPart1 packet
*
* Arrives from:
* - state_discovery_waitingForHelloAck upon Commit reception in DHM mode
* - state_keyAgreement_sendingCommit upon Commit reception in DHM mode and commit contention gives us the responder role
* Goes to:
* - state_confirmation_responderSendingConfirm1 upon DHPart2 reception
* Send :
* - DHPart1 on Commit reception
*
*/
int state_keyAgreement_responderSendingDHPart1(bzrtpEvent_t event);
/**
* @brief For DHM mode only, initiator send DHPart2 packet
*
* Arrives from:
* - state_keyAgreement_sendingCommit upon DHPart1 reception
* Goes to:
* - state_confirmation_initiatorSendingConfirm2 upon reception of Confirm1
* Send :
* - DHPart2 until timer's end or transition
*
*/
int state_keyAgreement_initiatorSendingDHPart2(bzrtpEvent_t event);
/**
* @brief Responder send the confirm1 message
*
* Arrives from:
* - state_keyAgreement_responderSendingDHPart1 upon DHPart2 reception
* - state_keyAgreement_sendingCommit upon Commit reception in non DHM mode and commit contention gives us the responder role
* - state_discovery_waitingForHelloAck upon Commit reception in non DHM mode
* Goes to:
* - state_secure on Confirm2 reception
* Send :
* - Confirm1 on Commit or DHPart2 reception
*
*/
int state_confirmation_responderSendingConfirm1(bzrtpEvent_t event);
/**
* @brief Initiator send the confirm2 message
*
* Arrives from:
* - state_keyAgreement_initiatorSendingDHPart2 upon confirm1 reception
* - state_keyAgreement_sendingCommit upon Confirm1 reception in non DHM mode
* Goes to:
* - state_secure on Conf2ACK reception or first SRTP message
* Send :
* - Confirm2 until timer's end or transition
*
*/
int state_confirmation_initiatorSendingConfirm2(bzrtpEvent_t event);
/**
* @brief We are in secure state
*
* Arrives from:
* - state_confirmation_responderSendingConfirm1 on Confirm2 reception
* - state_confirmation_initiatorSendingConfirm2 on conf2ACK or first SRTP message
* Goes to:
* - This is the end(we do not support GoClear message), state machine may be destroyed after going to secure mode
* Send :
* - Conf2ACK on Confirm2 reception
*
*/
int state_secure(bzrtpEvent_t event);
#endif /* STATEMACHINE_H */
......@@ -27,11 +27,12 @@
/* aux secret may rarely be used define his maximum length in bytes */
#define MAX_AUX_SECRET_LENGTH 64
/* the context will store some of the sent or received packets */
#define PACKET_STORAGE_CAPACITY 3
#define PACKET_STORAGE_CAPACITY 4
#define HELLO_MESSAGE_STORE_ID 0
#define COMMIT_MESSAGE_STORE_ID 1
#define DHPART_MESSAGE_STORE_ID 2
#define CONFIRM_MESSAGE_STORE_ID 3
/* role mapping */
#define INITIATOR 0
......@@ -44,24 +45,31 @@ typedef struct bzrtpChannelContext_struct bzrtpChannelContext_t;
#include "cryptoWrapper.h"
#include "packetParser.h"
#include "stateMachine.h"
/* event and state machine related definitions */
#define BZRTP_EVENT_MESSAGE 1
#define BZRTP_EVENT_TIMER 2
/**
* @brief The event type, used as a parameter for the state function
*/
typedef struct bzrtp_event_struct {
uint8_t eventType; /**< Event can be a message or a timer's end */
bzrtpPacket_t *bzrtpPacket; /**< a pointer to the zrtp packet, NULL in case of timer event */
bzrtpContext_t *zrtpContext; /**< the current ZRTP context */
bzrtpChannelContext_t *zrtpChannelContext; /**< the current ZRTP channel hosting this state machine context */
} bzrtp_event_t;
/* timer related definitions */
#define BZRTP_TIMER_ON 1
#define BZRTP_TIMER_OFF 2
/* values for retransmission timers, as recommended in rfc section 6 */
#define HELLO_BASE_RETRANSMISSION_STEP 50
#define HELLO_CAP_RETRANSMISSION_STEP 200
#define HELLO_MAX_RETRANSMISSION_NUMBER 20
#define NON_HELLO_BASE_RETRANSMISSION_STEP 150
#define NON_HELLO_CAP_RETRANSMISSION_STEP 1200
#define NON_HELLO_MAX_RETRANSMISSION_NUMBER 10
/**
* @brief the state function pointer definition
* @brief Timer structure : The timer mechanism receives a tick giving a current time in ms
* a timer object will check on tick reception if it must fire or not
*/
typedef void (*bzrtp_stateMachine_t)(bzrtp_event_t);
typedef struct bzrtpTimer_struct {
uint8_t status; /**< Status is BZRTP_TIMER_ON or BZRTP_TIMER_OFF */
uint64_t firingTime; /**< in ms. The timer will fire if currentTime >= firingTime */
uint8_t firingCount; /**< Timer is used to resend packets, count the number of times a packet has been resent */
uint8_t timerStep; /**< in ms. Step between next timer fire: used to reset firingTime for next timer fire */
} bzrtpTimer_t;
/**
......@@ -80,11 +88,11 @@ typedef struct cachedSecrets_struct {
/**
* @brief The hash of cached secret truncated to the 64 leftmost bits
* aux secret ID is not part of it because channel context dependend while these one are session wise
*/
typedef struct cachedSecretsHash_struct {
uint8_t rs1ID[8]; /**< retained secret 1 Hash */
uint8_t rs2ID[8]; /**< retained secret 2 Hash */
uint8_t auxsecretID[8]; /**< auxiliary secret Hash */
uint8_t pbxsecretID[8]; /**< pbx secret Hash */
} cachedSecretsHash_t;
......@@ -92,10 +100,14 @@ typedef struct cachedSecretsHash_struct {
* @brief All the callback functions provided by the client needed by the ZRTP engine
*/
typedef struct zrtpCallbacks_struct {
/* cache */
int (* bzrtp_readCache)(uint8_t *output, uint16_t size); /**< Cache related function : read size bytes from cache, shall return the number of bytes read */
int (* bzrtp_writeCache)(uint8_t *input, uint16_t size); /**< Cache related function : write size bytes to cache */
int (* bzrtp_setCachePosition)(long position); /**< Cache related function : set cache position in cache file, rewind when passing 0 */
int (* bzrtp_getCachePosition)(long *position); /**< Cache related function : get the current cache position in cache file */
/* sending packets */
int (* bzrtp_sendData)(void *clientData, uint8_t *packetString, uint16_t packetLength); /**< Send a ZRTP packet to peer. Shall return 0 on success */
} zrtpCallbacks_t;
/**
......@@ -104,12 +116,18 @@ typedef struct zrtpCallbacks_struct {
*/
typedef struct bzrtpChannelContext_struct {
void *clientData; /**< this is a pointer provided by the client which is then resent as a parameter of the callbacks functions. Usefull to store RTP session context for example */
uint8_t role;/**< can be INITIATOR or RESPONDER, is set to INITIATOR at creation, may switch to responder later */
bzrtp_stateMachine_t stateMachine; /**< The state machine function, holds the current state of the channel: points to the current state function */
bzrtpStateMachine_t stateMachine; /**< The state machine function, holds the current state of the channel: points to the current state function */
bzrtpTimer_t timer; /**< a timer used to manage packets retransmission */
uint32_t selfSSRC; /**< A context is identified by his own SSRC and the peer one */
/* USELESS?? */
uint32_t peerSSRC; /**< the SSRC of the peer end point */
uint8_t peerSSRCAssociated; /**< true if this channel is already associated with a peer SSRC, false otherwise */
/* USELESS?? */
/* Hash chains, self is generated at channel context init */
uint8_t selfH[4][32]; /**< Store self 256 bits Hash images H0-H3 used to generate messages MAC */
......@@ -150,6 +168,10 @@ typedef struct bzrtpChannelContext_struct {
uint8_t *zrtpkeyr; /**< the responder mackey as defined in rfc section 4.5.3 - have a length of cipherKeyLength*/
bzrtpSrtpSecrets_t srtpSecrets; /**< the secrets keys and salt needed by SRTP */
/* shared secret hash : unlike pbx, rs1 and rs2 secret hash, the auxsecret hash use a channel dependent data (H3) and is then stored in the channel context */
uint8_t initiatorAuxsecretID[8]; /**< initiator auxiliary secret Hash */
uint8_t responderAuxsecretID[8]; /**< responder auxiliary secret Hash */
} bzrtpChannelContext_t;
/**
......@@ -165,6 +187,8 @@ typedef struct bzrtpContext_struct {
uint8_t isSecure; /**< this flag is set to 1 after the first channel have completed the ZRTP protocol exchange(i.e. when the responder have sent the conf2ACK message) */
uint8_t peerSupportMultiChannel; /**< this flag is set to 1 when the first valid HELLO packet from peer arrives if it support Multichannel ZRTP */
uint64_t timeReference; /**< in ms. This field will set at each channel State Machine start and updated at each tick after creation of the context, it is used to set the firing time of a channel timer */
/* callbacks */
zrtpCallbacks_t zrtpCallbacks; /**< structure holding all the pointers to callbacks functions needed by the ZRTP engine. Functions are set by client using the bzrtp_setCallback function */
......
lib_LTLIBRARIES = libbzrtp.la
libbzrtp_la_SOURCES= bzrtp.c cryptoPolarssl.c cryptoUtils.c packetParser.c zidCache.c
libbzrtp_la_SOURCES= bzrtp.c cryptoPolarssl.c cryptoUtils.c packetParser.c zidCache.c stateMachine.c
libbzrtp_la_LDFLAGS=-fvisibility=hidden -no-undefined
......
......@@ -23,7 +23,6 @@
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "bzrtp/bzrtp.h"
......@@ -32,6 +31,7 @@
#include "cryptoUtils.h"
#include "zidCache.h"
#include "packetParser.h"
#include "stateMachine.h"
#define BZRTP_ERROR_INVALIDCHANNELCONTEXT 0x8001
/* buffers allocation */
......@@ -39,6 +39,7 @@
/* local functions */
int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC);
void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, uint8_t channelIndex);
bzrtpChannelContext_t *getChannelContext(bzrtpContext_t *zrtpContext, uint32_t selfSSRC);
/*
* Create context structure and initialise it
......@@ -178,6 +179,9 @@ int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_
case ZRTP_CALLBACK_GETCACHEPOSITION:
context->zrtpCallbacks.bzrtp_getCachePosition = (int (*)(long *))functionPointer;
break;
case ZRTP_CALLBACK_SENDDATA:
context->zrtpCallbacks.bzrtp_sendData = (int (*)(void *, uint8_t *, uint16_t))functionPointer;
break;
default:
return BZRTP_ERROR_INVALIDCALLBACKID;
break;
......@@ -232,7 +236,162 @@ int bzrtp_addChannel(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
return 0;
}
/*
* @brief Start the state machine of the specified channel
*
* @param[in/out] zrtpContext The ZRTP context hosting the channel to be started
* @param[in] selfSSRC The SSRC identifying the channel to be started(will start sending Hello packets and listening for some)
*
* @return 0 on succes, error code otherwise
*/
int bzrtp_startChannelEngine(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
/* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_UNABLETOSTARTCHANNEL;
}
/* set the timer reference to 0 to force a message to be sent at first timer tick */
zrtpContext->timeReference = 0;
/* start the engine by setting the state to init and calling it */
zrtpChannelContext->stateMachine = state_discovery_init;
/* create an INIT event to call the init state function which will create a hello packet and start sending it */
bzrtpEvent_t initEvent;
initEvent.eventType = BZRTP_EVENT_INIT;
initEvent.bzrtpPacketString = NULL;
initEvent.bzrtpPacketStringLength = 0;
initEvent.zrtpContext = zrtpContext;
initEvent.zrtpChannelContext = zrtpChannelContext;
zrtpChannelContext->stateMachine(initEvent);
return 0;
}
/*
* @brief Send the current time to a specified channel, it will check if it has to trig some timer
*
* @param[in/out] zrtpContext The ZRTP context hosting the channel
* @param[in] selfSSRC The SSRC identifying the channel
* @param[in] timeReference The current time in ms
*
* @return 0 on succes, error code otherwise
*/
int bzrtp_iterate(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint64_t timeReference) {
/* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
/* update the context time reference used when arming timers */
zrtpContext->timeReference = timeReference;
if (zrtpChannelContext->timer.status == BZRTP_TIMER_ON) {
if (zrtpChannelContext->timer.firingTime<=timeReference) { /* we must trig the timer */
zrtpChannelContext->timer.firingCount++;
/* create a timer event */
bzrtpEvent_t timerEvent;
timerEvent.eventType = BZRTP_EVENT_TIMER;
timerEvent.bzrtpPacketString = NULL;
timerEvent.bzrtpPacketStringLength = 0;
timerEvent.zrtpContext = zrtpContext;
timerEvent.zrtpChannelContext = zrtpChannelContext;
/* send it to the state machine*/
zrtpChannelContext->stateMachine(timerEvent);
}
}
return 0;
}
/*
* @brief Set the client data pointer in a channel context
* This pointer is returned to the client by the callbacks function, used to store associated contexts (RTP session)
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel to be linked to the client Data
* @param[in] clientData The clientData pointer, casted to a (void *)
*
* @return 0 on success
*
*/
int bzrtp_setClientData(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, void *clientData) {
/* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
zrtpChannelContext->clientData = clientData;
return 0;
}
/*
* @brief Process a received message
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel receiving the message
* @param[in] zrtpPacketString The packet received
* @param[in] zrtpPacketStringLength Length of the packet in bytes
*
* @return 0 on success, errorcode otherwise
*/
int bzrtp_processMessage(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *zrtpPacketString, uint16_t zrtpPacketStringLength) {
/* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
/* build a packet event of it and send it to the state machine */
bzrtpEvent_t event;
event.eventType = BZRTP_EVENT_MESSAGE;
event.bzrtpPacketString = zrtpPacketString;
event.bzrtpPacketStringLength = zrtpPacketStringLength;
event.zrtpContext = zrtpContext;
event.zrtpChannelContext = zrtpChannelContext;
return zrtpChannelContext->stateMachine(event);
}
/* Local functions implementation */
/**
* @brief Look in the given ZRTP context for a channel referenced with given SSRC
*
* @param[in] zrtpContext The zrtp context which shall contain the channel context we are looking for
* @param[in] selfSSRC The SSRC identifying the channel context
*
* @return a pointer to the channel context, NULL if the context is invalid or channel not found
*/
bzrtpChannelContext_t *getChannelContext(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
if (zrtpContext==NULL) {
return NULL;
}
int i;
for (i=0; i<ZRTP_MAX_CHANNEL_NUMBER; i++) {
if (zrtpContext->channelContext[i]!=NULL) {
if (zrtpContext->channelContext[i]->selfSSRC == selfSSRC) {
return zrtpContext->channelContext[i];
}
}
}
return NULL; /* found no channel with this SSRC */
}
/**
* @brief Initialise the context of a channel
* Initialise some vectors
......@@ -249,9 +408,14 @@ int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
return BZRTP_ERROR_INVALIDCHANNELCONTEXT;
}
zrtpChannelContext->clientData = NULL;
/* the state machine is not started at the creation of the channel but on explicit call to the start function */
zrtpChannelContext->stateMachine = NULL;
/* timer is off */
zrtpChannelContext->timer.status = BZRTP_TIMER_OFF;
zrtpChannelContext->selfSSRC = selfSSRC;
/* initialise as initiator, switch to responder later if needed */
......@@ -317,6 +481,12 @@ void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, uint8_t channelInd
return;
}
/* reset state Machine */
zrtpChannelContext->stateMachine = NULL;
/* set timer off */
zrtpChannelContext->timer.status = BZRTP_TIMER_OFF;
/* destroy and free the key buffers */
bzrtp_DestroyKey(zrtpChannelContext->s0, zrtpChannelContext->hashLength, zrtpContext->RNGContext);
bzrtp_DestroyKey(zrtpChannelContext->KDFContext, zrtpChannelContext->KDFContextLength, zrtpContext->RNGContext);
......@@ -347,12 +517,3 @@ void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, uint8_t channelInd
zrtpChannelContext->peerPackets[i] = NULL;
}
}
/* here are the state functions for the state machine */
/**
* brief This is the initial state
* On first call, we will create the Hello message and start sending it until we receive an helloACK and a hello message from peer
* if we receive an Hello message*/
void state_discovery(bzrtp_event_t event) {
};
......@@ -139,6 +139,7 @@ bzrtpPacket_t *bzrtp_packetCheck(const uint8_t * input, uint16_t inputLength, ui
* TODO: what if we got a Sequence Number overflowing the 16 bits ? */
uint16_t sequenceNumber = (((uint16_t)input[2])<<8) | ((uint16_t)input[3]);
if (sequenceNumber <= lastValidSequenceNumber) {
printf("Sequence number check last %d current %d", lastValidSequenceNumber, sequenceNumber);
*exitCode = BZRTP_PARSER_ERROR_OUTOFORDER;
return NULL;
}
......@@ -1014,6 +1015,9 @@ int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpCh
bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t messageType, int *exitCode) {
/* allocate packet */
bzrtpPacket_t *zrtpPacket = (bzrtpPacket_t *)malloc(sizeof(bzrtpPacket_t));
memset(zrtpPacket, 0, sizeof(bzrtpPacket_t));
zrtpPacket->messageData = NULL;
zrtpPacket->packetString = NULL;
/* initialise it */
switch(messageType) {
......@@ -1124,7 +1128,7 @@ bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelC
* be the responder and not the initiator, use the initiator retained secret hashes */
memcpy(zrtpDHPartMessage->rs1ID, zrtpContext->initiatorCachedSecretHash.rs1ID, 8);
memcpy(zrtpDHPartMessage->rs2ID, zrtpContext->initiatorCachedSecretHash.rs2ID, 8);
memcpy(zrtpDHPartMessage->auxsecretID, zrtpContext->initiatorCachedSecretHash.auxsecretID, 8);
memcpy(zrtpDHPartMessage->auxsecretID, zrtpChannelContext->initiatorAuxsecretID, 8);
memcpy(zrtpDHPartMessage->pbxsecretID, zrtpContext->initiatorCachedSecretHash.pbxsecretID, 8);
/* compute the public value and insert it in the message, will then be used whatever role - initiator or responder - we assume */
......
This diff is collapsed.
......@@ -116,9 +116,6 @@ int getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[12]) {
context->cachedSecret.auxsecretLength = 0;
/* convert peerZID to a tag string */
uint8_t peerZIDtag[35];
bzrtp_createTagFromBytes((uint8_t *)"ZID", 3, peerZID, 12, peerZIDtag);
/* get the peer tag matching the given ZID, form is
* <peer>
* <ZID>data</ZID> (only this one is mandatory, data is 24 hexa char)
......@@ -130,6 +127,10 @@ int getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[12]) {
*/
/* do we have any cache access function or if we are running cacheless */
if (context->zrtpCallbacks.bzrtp_readCache != NULL) {
/* convert peerZID to a tag string */
uint8_t peerZIDtag[35];
bzrtp_createTagFromBytes((uint8_t *)"ZID", 3, peerZID, 12, peerZIDtag);
/* get the next peer tag */
while (bzrtp_findNextTag(context, bufferTag)!=-1) {
if (memcmp(bufferTag, "peer", 4) == 0) { /* we found a peer tag */
......
......@@ -5,11 +5,11 @@ bzrtpTest_SOURCES=bzrtpTest.c \
bzrtpCryptoTest.c \
bzrtpParserTest.c
AM_LDFLAGS= -lm
bzrtpTest_CFLAGS=$(CUNIT_CFLAGS)
bzrtpTest_LDFLAGS=$(CUNIT_LIBS) $(AM_LFFLAGS)
bzrtpTest_LDFLAGS=$(CUNIT_LIBS) $(AM_LDFLAGS)
AM_CPPFLAGS=-I$(top_srcdir)/include
LDADD= $(top_builddir)/src/libbzrtp.la
AM_LDFLAGS= -lm
test: bzrtpTest
./bzrtpTest
This diff is collapsed.
......@@ -21,3 +21,4 @@
*/
void test_parser(void);
void test_parserComplete(void);
void test_stateMachine(void);
......@@ -52,8 +52,9 @@ int main(int argc, char *argv[] ) {
/* Add the parser suite to the registry */
parserTestSuite = CU_add_suite("Bzrtp ZRTP Packet Parser", NULL, NULL);
CU_add_test(parserTestSuite, "Parse", test_parser);
CU_add_test(parserTestSuite, "Parse Exchange", test_parserComplete);
/* CU_add_test(parserTestSuite, "Parse", test_parser);
CU_add_test(parserTestSuite, "Parse Exchange", test_parserComplete);*/
CU_add_test(parserTestSuite, "State machine", test_stateMachine);
/* Run all suites */
printf("\n\n#### Run the Bzrtp Crypto Wrappers tests suite\n");
......
......@@ -126,7 +126,11 @@ void packetDump(bzrtpPacket_t *zrtpPacket, uint8_t addRawMessage) {
case MSGTYPE_DHPART1:
case MSGTYPE_DHPART2:
{
printf(" - Message Type : DHPart\n");
if (zrtpPacket->messageType