Commit 532eab69 authored by johan's avatar johan
Browse files

Prepare for multichannel support

Non functional
parent 0b4f6afe
......@@ -23,7 +23,7 @@
*/
#ifndef BZRTP_H
#define BZRTP_H
typedef struct bzrtpContext_struct bzrtpContext;
typedef struct bzrtpContext_struct bzrtpContext_t;
#include <stdint.h>
/**
......@@ -45,7 +45,11 @@ typedef struct bzrtpSrtpSecrets_struct {
#define ZRTP_CLIENT_IDENTIFIER "LINPHONE-ZRTPCPP"
/* error code definition */
#define BZRTP_ERROR_INVALIDCALLBACKID 0x0001
#define BZRTP_ERROR_INVALIDCALLBACKID 0x0001
#define BZRTP_ERROR_CONTEXTNOTREADY 0x0002
#define BZRTP_ERROR_INVALIDCONTEXT 0x0004
#define BZRTP_ERROR_MULTICHANNELNOTSUPPORTEDBYPEER 0x0008
#define BZRTP_ERROR_UNABLETOADDCHANNEL 0x0010
/**
* @brief bzrtpContext_t The ZRTP engine context
* Store current state, timers, HMAC and encryption keys
......@@ -53,11 +57,15 @@ typedef struct bzrtpSrtpSecrets_struct {
typedef struct bzrtpContext_struct bzrtpContext_t;
/**
* Create context structure and initialise it
* Create context structure and initialise it
* A channel context is created when creating the zrtp context.
*
* @param[in] selfSSRC The SSRC given to the channel context created within the zrtpContext
*
* @return The ZRTP engine context data
*
*/
__attribute__ ((visibility ("default"))) bzrtpContext_t *bzrtp_createBzrtpContext();
__attribute__ ((visibility ("default"))) bzrtpContext_t *bzrtp_createBzrtpContext(uint32_t selfSSRC);
/**
* @brief Perform some initialisation which can't be done without some callback functions:
......@@ -88,4 +96,13 @@ __attribute__ ((visibility ("default"))) void bzrtp_destroyBzrtpContext(bzrtpCon
*/
__attribute__ ((visibility ("default"))) int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_t functionID);
/**
* @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
*
* @return 0 on succes, error code otherwise
*/
__attribute__ ((visibility ("default"))) int bzrtp_addChannel(bzrtpContext_t *zrtpContext, uint32_t selfSSRC);
#endif /* ifndef BZRTP_H */
......@@ -28,8 +28,8 @@
#ifndef CRYPTOUTILS_H
#define CRYPTOUTILS_H
#include "packetParser.h"
#include "typedef.h"
#include "packetParser.h"
/**
*
......@@ -104,22 +104,23 @@ uint32_t bzrtp_CRC32(uint8_t *input, uint16_t length);
* rfc section 5.1.5
* The other algorithm choice will finally be set by the endpoint acting as initiator in the commit packet
*
* @param[in/out] zrtpContext The context contains the list of available algo and is set with the selected ones
* @param[in] zrtpContext The context contains the list of available algo
* @param[out] zrtpChannelContext The bzrtp channel context to be updated
* @param[in] peerHelloMessage The peer hello message containing his set of available algos
*
* return 0 on succes, error code otherwise
*
*/
int crypoAlgoAgreement(bzrtpContext_t *zrtpContext, bzrtpHelloMessage_t *peerHelloMessage);
int crypoAlgoAgreement(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpHelloMessage_t *peerHelloMessage);
/**
* @brief Update context crypto function pointer according to related values of choosen algorithms fields (hashAlgo, cipherAlgo, etc..)
*
* @param[in/out] context The bzrtp context to be updated
* @param[in/out] zrtpChannelContext The bzrtp channel context to be updated
*
* @return 0 on succes
*/
int updateCryptoFunctionPointers(bzrtpContext_t *context);
int updateCryptoFunctionPointers(bzrtpChannelContext_t *zrtpChannelContext);
/**
* @brief Map the string description of algo type to an int defined in cryptoWrapper.h
......@@ -141,7 +142,8 @@ void cryptoAlgoTypeIntToString(uint8_t algoTypeInt, uint8_t algoTypeString[4]);
/**
* @brief Destroy a key by setting it to a random number
* Key is not freed, caller must deal with memory management
* Key is not freed, caller must deal with memory management.
* Does nothing if the key pointer is NULL
*
* @param[in/out] key The key to be destroyed
* @param[in] keyLength The keyLength in bytes
......
......@@ -37,6 +37,10 @@
#define BZRTP_PARSER_ERROR_INVALIDMESSAGE 0xa008
#define BZRTP_PARSER_ERROR_INVALIDCONTEXT 0xa010
#define BZRTP_PARSER_ERROR_UNMATCHINGCONFIRMMAC 0xa020
#define BZRTP_PARSER_ERROR_UNMATCHINGSSRC 0xa040
#define BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN 0xa080
#define BZRTP_PARSER_ERROR_UNMATCHINGMAC 0xa100
#define BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE 0xa200
#define BZRTP_BUILDER_ERROR_INVALIDPACKET 0x5001
#define BZRTP_BUILDER_ERROR_INVALIDMESSAGE 0x5002
......@@ -276,41 +280,43 @@ bzrtpPacket_t *bzrtp_packetCheck(const uint8_t * input, uint16_t inputLength, ui
/**
* @brief Parse the packet to extract the message and allocate the matching message structure if needed
*
* @param[in] zrtpContext The current ZRTP context, some parameters(key agreement algorithm) may be needed to parse packet.
* @param[in] input The string buffer storing the complete ZRTP packet
* @param[in] inputLength Input length in bytes
* @param[in] zrtpPacket The zrtpPacket structure allocated by previous call to bzrtpPacketCheck
*
* @param[in] zrtpContext The current ZRTP context, some parameters(key agreement algorithm) may be needed to parse packet.
* @param[in] zrtpChannelContext The channel context this packet is intended to(channel context and packet must match peer SSRC).
* @param[in] input The string buffer storing the complete ZRTP packet
* @param[in] inputLength Input length in bytes
* @param[in] zrtpPacket The zrtpPacket structure allocated by previous call to bzrtpPacketCheck
*
* @return 0 on sucess, error code otherwise
*/
int bzrtp_packetParser(bzrtpContext_t *zrtpContext, const uint8_t * input, uint16_t inputLength, bzrtpPacket_t *zrtpPacket);
int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, const uint8_t * input, uint16_t inputLength, bzrtpPacket_t *zrtpPacket);
/**
* @brief Create an empty packet and allocate the messageData according to requested packetType
*
* @param[in] zrtpContext The current ZRTP context, some data (H chain or others, may be needed to create messages)
* @param[in] zrtpChannelContext The channel context this packet is intended to
* @param[in] messageType The 32bit integer mapped to the message type to be created
* @param[in] sourceIdentifier The SSRC of the message creator
* @param[out] exitCode 0 on success, error code otherwise
*
* @return An empty packet initialised to get data for the requested paquet tyep. NULL on error
*/
bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, uint32_t messageType, uint32_t sourceIdentifier, int *exitCode);
bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t messageType, int *exitCode);
/**
* @brief Create a ZRTP packet string from the ZRTP packet values present in the structure
* messageType, messageData and sourceIdentifier in zrtpPacket must have been correctly set before calling this function
*
* @param[in] zrtpContext A zrtp context where to find H0-H3 to compute MAC requested by some paquets or encryption's key for commit/SASRelay packet
* @param[in] zrtpContext A zrtp context where to find H0-H3 to compute MAC requested by some paquets or encryption's key for commit/SASRelay packet
* @param[in] zrtpChannelContext The channel context this packet is intended to
* @param[in/out] zrtpPacket The zrtpPacket structure containing the message Data structure, output is stored in ->packetString
* @param[in] sequenceNumber Sequence number of this packet
*
* @return 0 on success, error code otherwise
*
*/
int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpPacket_t *zrtpPacket, uint16_t sequenceNumber);
int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket, uint16_t sequenceNumber);
/**
......
......@@ -22,6 +22,8 @@
#ifndef TYPEDEF_H
#define TYPEDEF_H
/* maximum number of simultaneous channels opened in a ZRTP session */
#define ZRTP_MAX_CHANNEL_NUMBER 2
/* 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 */
......@@ -29,7 +31,7 @@
#define HELLO_MESSAGE_STORE_ID 0
#define COMMIT_MESSAGE_STORE_ID 1
#define DHPART2_MESSAGE_STORE_ID 2
#define DHPART_MESSAGE_STORE_ID 2
/* role mapping */
#define INITIATOR 0
......@@ -37,9 +39,31 @@
#include <stdint.h>
#include <stdio.h>
typedef struct bzrtpChannelContext_struct bzrtpChannelContext_t;
#include "cryptoWrapper.h"
#include "packetParser.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;
/**
* @brief the state function pointer definition
*/
typedef void (*bzrtp_stateMachine_t)(bzrtp_event_t);
/**
* @brief A set of cached secrets retrieved from the cache as defined
*/
......@@ -75,22 +99,77 @@ typedef struct zrtpCallbacks_struct {
} zrtpCallbacks_t;
/**
* @struct bzrtpContext_t structure of the ZRTP engine
* @brief The zrtp context of a channel
*
*/
typedef struct bzrtpChannelContext_struct {
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 */
uint32_t selfSSRC; /**< A context is identified by his own SSRC and the peer one */
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 */
/* 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 */
uint8_t peerH[4][32]; /**< Store peer 256 bits Hash images H0-H3 used to check messages authenticity */
/* packet storage : shall store some sent and received packets */
bzrtpPacket_t *selfPackets[PACKET_STORAGE_CAPACITY]; /**< Hello, Commit and DHPart packet locally generated */
bzrtpPacket_t *peerPackets[PACKET_STORAGE_CAPACITY]; /**< Hello, Commit and DHPart packet received from peer */
/* sequence number: self and peer */
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 */
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 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 */
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 */
/* function pointer to the agreed algorithms - Note, key agreement manage directly this selection so it is not set here */
void (*hmacFunction)(const uint8_t *key, uint8_t keyLength, const uint8_t *input, uint32_t inputLength, uint8_t hmacLength, uint8_t *output); /**< function pointer to the agreed hmacFunction */
void (*hashFunction)(const uint8_t *input, uint32_t inputLength, uint8_t hashLength, uint8_t *output); /**< function pointer to the agreed hash function */
void (*cipherEncryptionFunction)(const uint8_t *key, const uint8_t *IV, const uint8_t *input, uint16_t inputLength, uint8_t *output); /**< function pointer to the agreed cipher block function, encryption mode */
void (*cipherDecryptionFunction)(const uint8_t *key, const uint8_t *IV, const uint8_t *input, uint16_t inputLength, uint8_t *output); /**< function pointer to the agreed cipher block function, decryption mode */
void (*sasFunction)(uint32_t sas, char output[4]); /**< function pointer to the agreed sas rendering function */
/* keys */
uint8_t *s0; /**< the s0 as describred rfc section 4.4 - have a length of hashLength */
uint8_t *KDFContext; /**< defined in rfc section 4.4 */
uint16_t KDFContextLength; /**< lenght of the KDF context, is 24 + output length of the selected hash algo */
uint8_t *mackeyi; /**< the initiator mackey as defined in rfc section 4.5.3 - have a length of hashLength */
uint8_t *mackeyr; /**< the responder mackey as defined in rfc section 4.5.3 - have a length of hashLength*/
uint8_t *zrtpkeyi; /**< the initiator mackey as defined in rfc section 4.5.3 - have a length of cipherKeyLength */
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 */
} bzrtpChannelContext_t;
/**
* @brief structure of the ZRTP engine context
* Store current state, timers, HMAC and encryption keys
*/
typedef struct bzrtpContext_struct {
/* contexts */
bzrtpRNGContext_t *RNGContext; /**< context for random number generation */
bzrtpDHMContext_t *DHMContext; /**< context for the Diffie-Hellman-Merkle operations */
bzrtpDHMContext_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 */
/* flags */
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 */
/* role : can be INITIATOR or RESPONDER, is set to INITIATOR at creation, may switch to responder later */
uint8_t role;
/* 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 */
/* Hash chains, self is generated at context init */
uint8_t selfH[4][32]; /**< Store self 256 bits Hash images H0-H3 used to generate messages MAC */
uint8_t peerH[4][32]; /**< Store peer 256 bits Hash images H0-H3 used to check messages authenticity */
/* channel contexts */
bzrtpChannelContext_t *channelContext[ZRTP_MAX_CHANNEL_NUMBER]; /**< All the context data needed for a channel are stored in a dedicated structure */
/* List of available algorithms, initialised with algo implemented in cryptoWrapper but can be then be modified according to user settings */
uint8_t hc; /**< hash count -zrtpPacket set to 0 means we support only HMAC-SHA256 (4 bits) */
......@@ -104,23 +183,6 @@ typedef struct bzrtpContext_struct {
uint8_t sc; /**< sas count - set to 0 means we support only base32 (4 bits) */
uint8_t supportedSas[7]; /**< list of supported Sas representations mapped to uint8_t */
/* 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 */
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 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 */
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 */
void (*hmacFunction)(const uint8_t *key, uint8_t keyLength, const uint8_t *input, uint32_t inputLength, uint8_t hmacLength, uint8_t *output);
void (*hashFunction)(const uint8_t *input, uint32_t inputLength, uint8_t hashLength, uint8_t *output);
void (*cipherEncryptionFunction)(const uint8_t *key, const uint8_t *IV, const uint8_t *input, uint16_t inputLength, uint8_t *output);
void (*cipherDecryptionFunction)(const uint8_t *key, const uint8_t *IV, const uint8_t *input, uint16_t inputLength, uint8_t *output);
void (*sasFunction)(uint32_t sas, char output[4]);
/* ZIDs and cache */
uint8_t selfZID[12]; /**< The ZRTP Identifier of this ZRTP end point - a random if running cache less */
uint8_t peerZID[12]; /**< The ZRTP Identifier of the peer ZRTP end point - given by the Hello packet */
......@@ -128,30 +190,13 @@ typedef struct bzrtpContext_struct {
cachedSecretsHash_t initiatorCachedSecretHash; /**< The hash of cached secret from initiator side, computed as described in rfc section 4.3.1 */
cachedSecretsHash_t responderCachedSecretHash; /**< The hash of cached secret from responder side, computed as described in rfc section 4.3.1 */
/* sequence number: self and peer */
uint16_t selfSequenceNumber; /**< Sequence number of the next packet to be sent */
uint16_t peerSequenceNumber; /**< Sequence number of the last valid received packet */
/* packet storage : shall store some sent and received packets */
bzrtpPacket_t *selfPackets[PACKET_STORAGE_CAPACITY]; /**< Hello and DHPart packet locally generated */
bzrtpPacket_t *peerPackets[PACKET_STORAGE_CAPACITY]; /**< Hello and DHPart packet received from peer */
/* keys */
uint8_t *s0; /**< the s0 as describred rfc section 4.4 - have a length of hashLength */
uint8_t *KDFContext; /**< defined in rfc section 4.4 */
uint16_t KDFContextLength; /**< lenght of the KDF context, is 24 + output length of the selected hash algo */
uint8_t *ZRTPSess; /**< ZRTP session key as described in rfc section 4.5.2 */
uint8_t ZRTPSessLength; /**< length of ZRTP session key depends on agreed hash algorithm */
uint8_t *mackeyi; /**< the initiator mackey as defined in rfc section 4.5.3 - have a length of hashLength */
uint8_t *mackeyr; /**< the responder mackey as defined in rfc section 4.5.3 - have a length of hashLength*/
uint8_t *zrtpkeyi; /**< the initiator mackey as defined in rfc section 4.5.3 - have a length of cipherKeyLength */
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 */
} bzrtpContext_t;
} bzrtpContext_t;
#endif /* ifndef TYPEDEF_H */
......@@ -31,17 +31,23 @@
#include "cryptoWrapper.h"
#include "cryptoUtils.h"
#include "zidCache.h"
#include "packetParser.h"
#define BZRTP_ERROR_INVALIDCHANNELCONTEXT 0x8001
/* buffers allocation */
/* internal functions */
/* local functions */
int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC);
void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, uint8_t channelIndex);
/**
* Create context structure and initialise it
/*
* Create context structure and initialise it
* A channel context is created to, the selfSSRC is given to it
*
* @return The ZRTP engine context data
*
*/
bzrtpContext_t *bzrtp_createBzrtpContext()
bzrtpContext_t *bzrtp_createBzrtpContext(uint32_t selfSSRC)
{
int i;
/*** create and intialise the context structure ***/
......@@ -53,14 +59,24 @@ bzrtpContext_t *bzrtp_createBzrtpContext()
/* set the DHM context to NULL, it will be created if needed when creating a DHPart packet */
context->DHMContext = NULL;
/* set flags */
context->isSecure = 0; /* start unsecure */
context->peerSupportMultiChannel = 0; /* peer does not support Multichannel by default */
/* set to NULL all callbacks pointer */
context->zrtpCallbacks.bzrtp_readCache = NULL;
context->zrtpCallbacks.bzrtp_writeCache = NULL;
context->zrtpCallbacks.bzrtp_setCachePosition = NULL;
context->zrtpCallbacks.bzrtp_getCachePosition = NULL;
/* initialise as initiator, switch to responder later if needed */
context->role = INITIATOR;
/* allocate 1 channel context, set all the others pointers to NULL */
context->channelContext[0] = (bzrtpChannelContext_t *)malloc(sizeof(bzrtpChannelContext_t));
memset(context->channelContext[0], 0, sizeof(bzrtpChannelContext_t));
bzrtp_initChannelContext(context, context->channelContext[0], selfSSRC);
for (i=1; i<ZRTP_MAX_CHANNEL_NUMBER; i++) {
context->channelContext[i] = NULL;
}
/* get the list of crypto algorithms provided by the crypto module */
/* this list may then be updated according to users settings */
......@@ -70,15 +86,6 @@ bzrtpContext_t *bzrtp_createBzrtpContext()
context->kc = bzrtpCrypto_getAvailableCryptoTypes(ZRTP_KEYAGREEMENT_TYPE, context->supportedKeyAgreement);
context->sc = bzrtpCrypto_getAvailableCryptoTypes(ZRTP_SAS_TYPE, context->supportedSas);
/* reset choosen algo and their functions */
context->hashAlgo = ZRTP_UNSET_ALGO;
context->cipherAlgo = ZRTP_UNSET_ALGO;
context->authTagAlgo = ZRTP_UNSET_ALGO;
context->keyAgreementAlgo = ZRTP_UNSET_ALGO;
context->sasAlgo = ZRTP_UNSET_ALGO;
updateCryptoFunctionPointers(context);
/* initialise cached secret buffer to null */
context->cachedSecret.rs1 = NULL;
context->cachedSecret.rs1Length = 0;
......@@ -89,34 +96,10 @@ bzrtpContext_t *bzrtp_createBzrtpContext()
context->cachedSecret.auxsecret = NULL;
context->cachedSecret.auxsecretLength = 0;
/* create H0 (32 bytes random) and derive using implicit Hash(SHA256) H1,H2,H3 */
bzrtpCrypto_getRandom(context->RNGContext, context->selfH[0], 32);
bzrtpCrypto_sha256(context->selfH[0], 32, 32, context->selfH[1]);
bzrtpCrypto_sha256(context->selfH[1], 32, 32, context->selfH[2]);
bzrtpCrypto_sha256(context->selfH[2], 32, 32, context->selfH[3]);
/* initialise the self Sequence number to a random and peer to 0
* (which may lead to reject the first hello packet if peer initialise his sequence number to 0) */
bzrtpCrypto_getRandom(context->RNGContext, (uint8_t *)&(context->selfSequenceNumber), 2);
context->selfSequenceNumber = context->selfSequenceNumber>>4; /* first 4 bits to zero in order to avoid reaching FFFF and turning back to 0 */
context->peerSequenceNumber = 0;
/* initialisation of packet storage */
for (i=0; i<PACKET_STORAGE_CAPACITY; i++) {
context->selfPackets[i] = NULL;
context->peerPackets[i] = NULL;
}
/* initialise key buffers */
context->s0 = NULL;
context->KDFContext = NULL;
context->KDFContextLength = 0;
context->ZRTPSess = NULL;
context->ZRTPSessLength = 0;
context->mackeyi = NULL;
context->mackeyr = NULL;
context->zrtpkeyi = NULL;
context->zrtpkeyr = NULL;
return context;
}
......@@ -140,31 +123,35 @@ void bzrtp_initBzrtpContext(bzrtpContext_t *context) {
*/
void bzrtp_destroyBzrtpContext(bzrtpContext_t *context)
{
int i;
/* destroy contexts */
bzrtpCrypto_destroyRNG(context->RNGContext);
bzrtpCrypto_DestroyDHMContext(context->DHMContext);
context->DHMContext = NULL;
/* destroy channel contexts */
for (i=0; i<ZRTP_MAX_CHANNEL_NUMBER; i++) {
bzrtp_destroyChannelContext(context, i);
context->channelContext[i] = NULL;
}
/* free allocated buffers */
free(context->cachedSecret.rs1);
free(context->cachedSecret.rs2);
free(context->cachedSecret.pbxsecret);
free(context->cachedSecret.auxsecret);
free(context->ZRTPSess);
int i;
for (i=0; i<PACKET_STORAGE_CAPACITY; i++) {
free(context->selfPackets[i]);
free(context->peerPackets[i]);
}
context->cachedSecret.rs1=NULL;
context->cachedSecret.rs2=NULL;
context->cachedSecret.pbxsecret=NULL;
context->cachedSecret.auxsecret=NULL;
context->ZRTPSess=NULL;
free(context->s0);
free(context->KDFContext);
free(context->ZRTPSess);
free(context->mackeyi);
free(context->mackeyr);
free(context->zrtpkeyi);
free(context->zrtpkeyr);
/* destroy the RNG context at the end because it may be needed to destroy some keys */
bzrtpCrypto_destroyRNG(context->RNGContext);
context->RNGContext = NULL;
free(context);
return;
}
......@@ -197,3 +184,175 @@ int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_
}
return 0;
}
int bzrtp_addChannel(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
/* is zrtp context valid */
if (zrtpContext==NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
/* is ZRTP context able to add a channel (means channel 0 has already performed the secrets generation) */
if (zrtpContext->isSecure == 0) {
return BZRTP_ERROR_CONTEXTNOTREADY;
}
/* check the peer support Multichannel(shall be set in the first Hello message received) */
if (zrtpContext->peerSupportMultiChannel == 0) {
return BZRTP_ERROR_MULTICHANNELNOTSUPPORTEDBYPEER;
}
/* get the first free channel context from ZRTP context and create a channel context */
bzrtpChannelContext_t *zrtpChannelContext = NULL;
int i=0;
while(i<ZRTP_MAX_CHANNEL_NUMBER && zrtpChannelContext==NULL) {
if (zrtpContext->channelContext[i] == NULL) {
int retval;
zrtpChannelContext = (bzrtpChannelContext_t *)malloc(sizeof(bzrtpChannelContext_t));
memset(zrtpChannelContext, 0, sizeof(bzrtpChannelContext_t));
retval = bzrtp_initChannelContext(zrtpContext, zrtpChannelContext, selfSSRC);
if (retval != 0) {
free(zrtpChannelContext);
return retval;
}
} else {
i++;
}
}
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_UNABLETOADDCHANNEL;
}
/* attach the created channel to the ZRTP context */
zrtpContext->channelContext[i] = zrtpChannelContext;
printf ("Added channel index %d\n", i);
return 0;
}
/* Local functions implementation */
/**
* @brief Initialise the context of a channel
* Initialise some vectors
*
* @param[in] zrtpContext The zrtpContext hosting this channel, needed to acces the RNG
* @param[out] zrtpChanneContext The channel context to be initialised
* @param[in] selfSSRC The SSRC allocated to this channel
*
* @return 0 on success, error code otherwise
*/
int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC) {
int i;
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCHANNELCONTEXT;
}
/* the state machine is not started at the creation of the channel but on explicit call to the start function */
zrtpChannelContext->stateMachine = NULL;
zrtpChannelContext->selfSSRC = selfSSRC;
/* initialise as initiator, switch to responder later if needed */
zrtpChannelContext->role = INITIATOR;
/* create H0 (32 bytes random) and derive using implicit Hash(SHA256) H1,H2,H3 */
bzrtpCrypto_getRandom(zrtpContext->RNGContext, zrtpChannelContext->selfH[0], 32);
bzrtpCrypto_sha256(zrtpChannelContext->selfH[0], 32, 32, zrtpChannelContext->selfH[1]);
bzrtpCrypto_sha256(zrtpChannelContext->selfH[1], 32, 32, zrtpChannelContext->selfH[2]);
bzrtpCrypto_sha256(zrtpChannelContext->selfH[2], 32, 32, zrtpChannelContext->selfH[3]);
/* initialisation of packet storage */
for (i=0; i<PACKET_STORAGE_CAPACITY; i++) {
zrtpChannelContext->selfPackets[i] = NULL;
zrtpChannelContext->peerPackets[i] = NULL;
}
/* initialise the self Sequence number to a random and peer to 0 */
bzrtpCrypto_getRandom(zrtpContext->RNGContext, (uint8_t *)&(zrtpChannelContext->selfSequenceNumber), 2);
zrtpChannelContext->selfSequenceNumber &= 0x0FFF; /* first 4 bits to zero in order to avoid reaching FFFF and turning back to 0 */
zrtpChannelContext->selfSequenceNumber++; /* be sure it is not initialised to 0 */
zrtpChannelContext->peerSequenceNumber = 0;
/* reset choosen algo and their functions */
zrtpChannelContext->hashAlgo = ZRTP_UNSET_ALGO;
zrtpChannelContext->cipherAlgo = ZRTP_UNSET_ALGO;
zrtpChannelContext->authTagAlgo = ZRTP_UNSET_ALGO;
zrtpChannelContext->keyAgreementAlgo = ZRTP_UNSET_ALGO;
zrtpChannelContext->sasAlgo = ZRTP_UNSET_ALGO;
updateCryptoFunctionPointers(zrtpChannelContext);
/* initialise key buffers */
zrtpChannelContext->s0 = NULL;
zrtpChannelContext->KDFContext = NULL;
zrtpChannelContext->KDFContextLength = 0;
zrtpChannelContext->mackeyi = NULL;
zrtpChannelContext->mackeyr = NULL;
zrtpChannelContext->zrtpkeyi = NULL;
zrtpChannelContext->zrtpkeyr = NULL;
return 0;
}
/**
* @brief Destroy the context of a channel