Commit 987effd8 authored by johan's avatar johan

Implement peer Hello Hash functionnality

parent d35cad27
......@@ -138,6 +138,9 @@ typedef struct bzrtpCallbacks_struct {
#define BZRTP_ERROR_MULTICHANNELNOTSUPPORTEDBYPEER 0x0008
#define BZRTP_ERROR_UNABLETOADDCHANNEL 0x0010
#define BZRTP_ERROR_UNABLETOSTARTCHANNEL 0x0020
#define BZRTP_ERROR_OUTPUTBUFFER_LENGTH 0x0040
#define BZRTP_ERROR_HELLOHASH_MISMATCH 0x0080
/**
* @brief bzrtpContext_t The ZRTP engine context
* Store current state, timers, HMAC and encryption keys
......@@ -297,6 +300,32 @@ BZRTP_EXPORT uint8_t bzrtp_getSupportedCryptoTypes(bzrtpContext_t *zrtpContext,
*/
BZRTP_EXPORT void bzrtp_setSupportedCryptoTypes(bzrtpContext_t *zrtpContext, uint8_t algoType, uint8_t supportedTypes[7], uint8_t supportedTypesCount);
/**
* @brief Set the peer hello hash given by signaling to a ZRTP channel
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel
* @param[in] peerHelloHashHexString A NULL terminated string containing the hexadecimal form of the hash received in signaling,
* may contain ZRTP version as header.
* @param[in] peerHelloHashHexStringLength Length of hash string (shall be at least 64 as the hash is a SHA256 so 32 bytes,
* more if it contains the version header)
*
* @return 0 on success, errorcode otherwise
*/
BZRTP_EXPORT int bzrtp_setPeerHelloHash(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *peerHelloHashHexString, size_t peerHelloHashHexStringLength);
/**
* @brief Get the self hello hash from ZRTP channel
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel
* @param[out] output A NULL terminated string containing the hexadecimal form of the hash received in signaling,
* contain ZRTP version as header. Buffer must be allocated by caller.
* @param[in] outputLength Length of output buffer, shall be at least 70 : 5 chars for version, 64 for the hash itself, SHA256), NULL termination
*
* @return 0 on success, errorcode otherwise
*/
BZRTP_EXPORT int bzrtp_getSelfHelloHash(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *output, size_t outputLength);
#define BZRTP_CUSTOMCACHE_USEKDF 1
#define BZRTP_CUSTOMCACHE_PLAINDATA 0
......
......@@ -190,4 +190,41 @@ void cryptoAlgoTypeIntToString(uint8_t algoTypeInt, uint8_t algoTypeString[4]);
*/
void bzrtp_DestroyKey(uint8_t *key, uint8_t keyLength, void *rngContext);
/**
* @brief Convert an hexadecimal string into the corresponding byte buffer
*
* @param[out] outputBytes The output bytes buffer, must have a length of half the input string buffer
* @param[in] inputString The input string buffer, must be hexadecimal(it is not checked by function, any non hexa char is converted to 0)
* @param[in] inputStringLength The length in chars of the string buffer, output is half this length
*/
void bzrtp_strToUint8(uint8_t *outputBytes, uint8_t *inputString, uint16_t inputStringLength);
/**
* @brief Convert a byte buffer into the corresponding hexadecimal string
*
* @param[out] outputString The output string buffer, must have a length of twice the input bytes buffer
* @param[in] inputBytes The input bytes buffer
* @param[in] inputBytesLength The length in bytes buffer, output is twice this length
*/
void bzrtp_int8ToStr(uint8_t *outputString, uint8_t *inputBytes, uint16_t inputBytesLength);
/**
* @brief convert an hexa char [0-9a-fA-F] into the corresponding unsigned integer value
* Any invalid char will be converted to zero without any warning
*
* @param[in] inputChar a char which shall be in range [0-9a-fA-F]
*
* @return the unsigned integer value in range [0-15]
*/
uint8_t bzrtp_charToByte(uint8_t inputChar);
/**
* @brief convert a byte which value is in range [0-15] into an hexa char [0-9a-fA-F]
*
* @param[in] inputByte an integer which shall be in range [0-15]
*
* @return the hexa char [0-9a-f] corresponding to the input
*/
uint8_t bzrtp_byteToChar(uint8_t inputByte);
#endif /* CRYPTOUTILS_H */
......@@ -144,7 +144,7 @@ void bzrtpCrypto_sha256(const uint8_t *input,
* @param[in] keyLength HMAC key length
* @param[in] input Input data buffer
* @param[in] inputLength Input data length
* @param[in] hmacLength Length of output required in bytes, HMAC output is truncated to the hmacLength left bytes. 32 bytes maximum
* @param[in] hmacLength Length of output required in bytes, HMAC output is truncated to the hmacLength left bytes. 20 bytes maximum
* @param[out] output Output data buffer
*
*/
......
......@@ -137,6 +137,9 @@ struct bzrtpChannelContext_struct {
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 */
/* peer Hello hash : store the peer hello hash when given by signaling */
uint8_t *peerHelloHash; /**< peer hello hash - SHA256 of peer Hello packet, given through signaling, shall be a 32 bytes buffer */
/* 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 */
......
......@@ -35,10 +35,11 @@
#define BZRTP_ERROR_INVALIDCHANNELCONTEXT 0x8001
/* local functions */
int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC);
void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
bzrtpChannelContext_t *getChannelContext(bzrtpContext_t *zrtpContext, uint32_t selfSSRC);
/* local functions prototypes */
static int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC);
static void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext);
static bzrtpChannelContext_t *getChannelContext(bzrtpContext_t *zrtpContext, uint32_t selfSSRC);
static uint8_t copyCryptoTypes(uint8_t destination[7], uint8_t source[7], uint8_t size);
/*
* Create context structure and initialise it
......@@ -186,13 +187,26 @@ void bzrtp_destroyBzrtpContext(bzrtpContext_t *context, uint32_t selfSSRC) {
return;
}
/*
* @brief Allocate a function pointer to the callback function identified by his id
* @param[in/out] context The zrtp context to set the callback function
* @param[in] cbs A structure containing all the callbacks to supply.
*
* @return 0 on success
*/
int bzrtp_setCallbacks(bzrtpContext_t *context, const bzrtpCallbacks_t *cbs) {
context->zrtpCallbacks=*cbs;
return 0;
}
/**
* @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/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
*/
int bzrtp_addChannel(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
bzrtpChannelContext_t *zrtpChannelContext = NULL;
int i=0;
......@@ -551,6 +565,191 @@ int bzrtp_resetRetransmissionTimer(bzrtpContext_t *zrtpContext, uint32_t selfSSR
return 0;
}
/**
* @brief Get the supported crypto types
*
* @param[int] zrtpContext The ZRTP context we're dealing with
* @param[in] algoType mapped to defines, must be in [ZRTP_HASH_TYPE, ZRTP_CIPHERBLOCK_TYPE, ZRTP_AUTHTAG_TYPE, ZRTP_KEYAGREEMENT_TYPE or ZRTP_SAS_TYPE]
* @param[out] supportedTypes mapped to uint8_t value of the 4 char strings giving the supported types as string according to rfc section 5.1.2 to 5.1.6
*
* @return number of supported types, 0 on error
*/
uint8_t bzrtp_getSupportedCryptoTypes(bzrtpContext_t *zrtpContext, uint8_t algoType, uint8_t supportedTypes[7])
{
if (zrtpContext==NULL) {
return 0;
}
switch(algoType) {
case ZRTP_HASH_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedHash, zrtpContext->hc);
case ZRTP_CIPHERBLOCK_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedCipher, zrtpContext->cc);
case ZRTP_AUTHTAG_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedAuthTag, zrtpContext->ac);
case ZRTP_KEYAGREEMENT_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedKeyAgreement, zrtpContext->kc);
case ZRTP_SAS_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedSas, zrtpContext->sc);
default:
return 0;
}
}
/**
* @brief set the supported crypto types
*
* @param[int/out] zrtpContext The ZRTP context we're dealing with
* @param[in] algoType mapped to defines, must be in [ZRTP_HASH_TYPE, ZRTP_CIPHERBLOCK_TYPE, ZRTP_AUTHTAG_TYPE, ZRTP_KEYAGREEMENT_TYPE or ZRTP_SAS_TYPE]
* @param[in] supportedTypes mapped to uint8_t value of the 4 char strings giving the supported types as string according to rfc section 5.1.2 to 5.1.6
* @param[in] supportedTypesCount number of supported crypto types
*/
void bzrtp_setSupportedCryptoTypes(bzrtpContext_t *zrtpContext, uint8_t algoType, uint8_t supportedTypes[7], uint8_t supportedTypesCount)
{
uint8_t implementedTypes[7];
uint8_t implementedTypesCount;
if (zrtpContext==NULL) {
return;
}
implementedTypesCount = bzrtpCrypto_getAvailableCryptoTypes(algoType, implementedTypes);
switch(algoType) {
case ZRTP_HASH_TYPE:
zrtpContext->hc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedHash);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedHash, &zrtpContext->hc);
break;
case ZRTP_CIPHERBLOCK_TYPE:
zrtpContext->cc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedCipher);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedCipher, &zrtpContext->cc);
break;
case ZRTP_AUTHTAG_TYPE:
zrtpContext->ac = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedAuthTag);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedAuthTag, &zrtpContext->ac);
break;
case ZRTP_KEYAGREEMENT_TYPE:
zrtpContext->kc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedKeyAgreement);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedKeyAgreement, &zrtpContext->kc);
break;
case ZRTP_SAS_TYPE:
zrtpContext->sc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedSas);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedSas, &zrtpContext->sc);
break;
}
}
/**
* @brief Set the peer hello hash given by signaling to a ZRTP channel
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel
* @param[out] peerHelloHashHexString A NULL terminated string containing the hexadecimal form of the hash received in signaling,
* may contain ZRTP version as header.
* @param[in] peerHelloHashHexStringLength Length of hash string (shall be at least 64 as the hash is a SHA256 so 32 bytes,
* more if it contains the version header)
*
* @return 0 on success, errorcode otherwise
*/
int bzrtp_setPeerHelloHash(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *peerHelloHashHexString, size_t peerHelloHashHexStringLength) {
int i=0;
uint8_t *hexHashString = NULL;
size_t hexHashStringLength = peerHelloHashHexStringLength;
/* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
/* parse the given peerHelloHash, it may formatted <version> <hexa string hash> or just <hexa string hash> */
/* just ignore anything(we do not care about version number) before a ' ' if found */
while (hexHashString==NULL && i<peerHelloHashHexStringLength) {
if (strncmp((const char *)(peerHelloHashHexString+i), " ", 1) == 0) {
hexHashString = peerHelloHashHexString+i+1;
hexHashStringLength -= (i+1);
}
i++;
}
if (hexHashString == NULL) { /* there were no ' ' in the input string so it shall be the hex hash only without version number */
hexHashString = peerHelloHashHexString;
}
/* allocate memory to store the hash, length will be hexa string length/2 - check it wasn't already allocated */
if (zrtpChannelContext->peerHelloHash) {
free(zrtpChannelContext->peerHelloHash);
}
zrtpChannelContext->peerHelloHash = (uint8_t *)malloc(hexHashStringLength/2*sizeof(uint8_t));
/* convert to uint8 the hex string */
bzrtp_strToUint8(zrtpChannelContext->peerHelloHash, hexHashString, hexHashStringLength);
/* Do we already have the peer Hello packet, if yes, check it match the hash */
if (zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID] != NULL) {
uint8_t computedPeerHelloHash[32];
/* compute hash using implicit hash function: SHA256, skip packet header in the packetString buffer as the hash must be computed on message only */
bzrtpCrypto_sha256(zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH,
zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength,
32,
computedPeerHelloHash);
/* check they are the same */
if (memcmp(computedPeerHelloHash, zrtpChannelContext->peerHelloHash, 32)!=0) {
return BZRTP_ERROR_HELLOHASH_MISMATCH;
}
}
return 0;
}
/**
* @brief Get the self hello hash from ZRTP channel
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] selfSSRC The SSRC identifying the channel
* @param[out] output A NULL terminated string containing the hexadecimal form of the hash received in signaling,
* contain ZRTP version as header. Buffer must be allocated by caller.
* @param[in] outputLength Length of output buffer, shall be at least 70 : 5 chars for version, 64 for the hash itself, SHA256), NULL termination
*
* @return 0 on success, errorcode otherwise
*/
int bzrtp_getSelfHelloHash(bzrtpContext_t *zrtpContext, uint32_t selfSSRC, uint8_t *output, size_t outputLength) {
uint8_t helloHash[32];
/* get channel context */
bzrtpChannelContext_t *zrtpChannelContext = getChannelContext(zrtpContext, selfSSRC);
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
/* check we have the Hello packet in context */
if (zrtpChannelContext->selfPackets[HELLO_MESSAGE_STORE_ID] == NULL) {
return BZRTP_ERROR_CONTEXTNOTREADY;
}
/* check output length : version length +' '+64 hex hash + null termination */
if (outputLength < strlen(ZRTP_VERSION)+1+64+1) {
return BZRTP_ERROR_OUTPUTBUFFER_LENGTH;
}
/* compute hash using implicit hash function: SHA256, skip packet header in the packetString buffer as the hash must be computed on message only */
bzrtpCrypto_sha256(zrtpChannelContext->selfPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH,
zrtpChannelContext->selfPackets[HELLO_MESSAGE_STORE_ID]->messageLength,
32,
helloHash);
/* add version header */
strcpy((char *)output, ZRTP_VERSION);
output[strlen(ZRTP_VERSION)]=' ';
/* convert hash to hex string and set it in the output buffer */
bzrtp_int8ToStr(output+strlen(ZRTP_VERSION)+1, helloHash, 32);
/* add NULL termination */
output[strlen(ZRTP_VERSION)+1+64]='\0';
return 0;
}
/* Local functions implementation */
/**
......@@ -561,7 +760,7 @@ int bzrtp_resetRetransmissionTimer(bzrtpContext_t *zrtpContext, uint32_t selfSSR
*
* @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) {
static bzrtpChannelContext_t *getChannelContext(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
int i;
if (zrtpContext==NULL) {
......@@ -588,7 +787,7 @@ bzrtpChannelContext_t *getChannelContext(bzrtpContext_t *zrtpContext, uint32_t s
*
* @return 0 on success, error code otherwise
*/
int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC) {
static int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t selfSSRC) {
int i;
if (zrtpChannelContext == NULL) {
return BZRTP_ERROR_INVALIDCHANNELCONTEXT;
......@@ -622,6 +821,7 @@ int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
zrtpChannelContext->selfPackets[i] = NULL;
zrtpChannelContext->peerPackets[i] = NULL;
}
zrtpChannelContext->peerHelloHash = NULL;
/* initialise the self Sequence number to a random and peer to 0 */
bzrtpCrypto_getRandom(zrtpContext->RNGContext, (uint8_t *)&(zrtpChannelContext->selfSequenceNumber), 2);
......@@ -672,7 +872,7 @@ int bzrtp_initChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
* @param[in] zrtpContext The zrtpContext hosting this channel, needed to acces the RNG
* @param[in] zrtpChannelContext The channel context to be destroyed
*/
void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext) {
static void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext) {
int i;
/* check there is something to be freed */
......@@ -715,6 +915,8 @@ void bzrtp_destroyChannelContext(bzrtpContext_t *zrtpContext, bzrtpChannelContex
zrtpChannelContext->selfPackets[i] = NULL;
zrtpChannelContext->peerPackets[i] = NULL;
}
free(zrtpChannelContext->peerHelloHash);
zrtpChannelContext->peerHelloHash = NULL;
/* destroy and free the srtp and sas struture */
bzrtp_DestroyKey(zrtpChannelContext->srtpSecrets.selfSrtpKey, zrtpChannelContext->srtpSecrets.selfSrtpKeyLength, zrtpContext->RNGContext);
......@@ -743,76 +945,4 @@ static uint8_t copyCryptoTypes(uint8_t destination[7], uint8_t source[7], uint8_
return size;
}
/**
* @brief Get the supported crypto types
*
* @param[int] zrtpContext The ZRTP context we're dealing with
* @param[in] algoType mapped to defines, must be in [ZRTP_HASH_TYPE, ZRTP_CIPHERBLOCK_TYPE, ZRTP_AUTHTAG_TYPE, ZRTP_KEYAGREEMENT_TYPE or ZRTP_SAS_TYPE]
* @param[out] supportedTypes mapped to uint8_t value of the 4 char strings giving the supported types as string according to rfc section 5.1.2 to 5.1.6
*
* @return number of supported types, 0 on error
*/
uint8_t bzrtp_getSupportedCryptoTypes(bzrtpContext_t *zrtpContext, uint8_t algoType, uint8_t supportedTypes[7])
{
if (zrtpContext==NULL) {
return 0;
}
switch(algoType) {
case ZRTP_HASH_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedHash, zrtpContext->hc);
case ZRTP_CIPHERBLOCK_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedCipher, zrtpContext->cc);
case ZRTP_AUTHTAG_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedAuthTag, zrtpContext->ac);
case ZRTP_KEYAGREEMENT_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedKeyAgreement, zrtpContext->kc);
case ZRTP_SAS_TYPE:
return copyCryptoTypes(supportedTypes, zrtpContext->supportedSas, zrtpContext->sc);
default:
return 0;
}
}
/**
* @brief set the supported crypto types
*
* @param[int/out] zrtpContext The ZRTP context we're dealing with
* @param[in] algoType mapped to defines, must be in [ZRTP_HASH_TYPE, ZRTP_CIPHERBLOCK_TYPE, ZRTP_AUTHTAG_TYPE, ZRTP_KEYAGREEMENT_TYPE or ZRTP_SAS_TYPE]
* @param[in] supportedTypes mapped to uint8_t value of the 4 char strings giving the supported types as string according to rfc section 5.1.2 to 5.1.6
* @param[in] supportedTypesCount number of supported crypto types
*/
void bzrtp_setSupportedCryptoTypes(bzrtpContext_t *zrtpContext, uint8_t algoType, uint8_t supportedTypes[7], uint8_t supportedTypesCount)
{
uint8_t implementedTypes[7];
uint8_t implementedTypesCount;
if (zrtpContext==NULL) {
return;
}
implementedTypesCount = bzrtpCrypto_getAvailableCryptoTypes(algoType, implementedTypes);
switch(algoType) {
case ZRTP_HASH_TYPE:
zrtpContext->hc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedHash);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedHash, &zrtpContext->hc);
break;
case ZRTP_CIPHERBLOCK_TYPE:
zrtpContext->cc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedCipher);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedCipher, &zrtpContext->cc);
break;
case ZRTP_AUTHTAG_TYPE:
zrtpContext->ac = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedAuthTag);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedAuthTag, &zrtpContext->ac);
break;
case ZRTP_KEYAGREEMENT_TYPE:
zrtpContext->kc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedKeyAgreement);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedKeyAgreement, &zrtpContext->kc);
break;
case ZRTP_SAS_TYPE:
zrtpContext->sc = selectCommonAlgo(supportedTypes, supportedTypesCount, implementedTypes, implementedTypesCount, zrtpContext->supportedSas);
addMandatoryCryptoTypesIfNeeded(algoType, zrtpContext->supportedSas, &zrtpContext->sc);
break;
}
}
......@@ -731,3 +731,77 @@ void bzrtp_DestroyKey(uint8_t *key, uint8_t keyLength, void *rngContext) {
}
}
/**
* @brief Convert an hexadecimal string into the corresponding byte buffer
*
* @param[out] outputBytes The output bytes buffer, must have a length of half the input string buffer
* @param[in] inputString The input string buffer, must be hexadecimal(it is not checked by function, any non hexa char is converted to 0)
* @param[in] inputStringLength The length in chars of the string buffer, output is half this length
*/
void bzrtp_strToUint8(uint8_t *outputBytes, uint8_t *inputString, uint16_t inputStringLength) {
int i;
for (i=0; i<inputStringLength/2; i++) {
outputBytes[i] = (bzrtp_charToByte(inputString[2*i]))<<4 | bzrtp_charToByte(inputString[2*i+1]);
}
}
/**
* @brief Convert a byte buffer into the corresponding hexadecimal string
*
* @param[out] outputString The output string buffer, must have a length of twice the input bytes buffer
* @param[in] inputBytes The input bytes buffer
* @param[in] inputBytesLength The length in bytes buffer, output is twice this length
*/
void bzrtp_int8ToStr(uint8_t *outputString, uint8_t *inputBytes, uint16_t inputBytesLength) {
int i;
for (i=0; i<inputBytesLength; i++) {
outputString[2*i] = bzrtp_byteToChar((inputBytes[i]>>4)&0x0F);
outputString[2*i+1] = bzrtp_byteToChar(inputBytes[i]&0x0F);
}
}
/**
* @brief convert an hexa char [0-9a-fA-F] into the corresponding unsigned integer value
* Any invalid char will be converted to zero without any warning
*
* @param[in] inputChar a char which shall be in range [0-9a-fA-F]
*
* @return the unsigned integer value in range [0-15]
*/
uint8_t bzrtp_charToByte(uint8_t inputChar) {
/* 0-9 */
if (inputChar>0x29 && inputChar<0x3A) {
return inputChar - 0x30;
}
/* a-f */
if (inputChar>0x60 && inputChar<0x67) {
return inputChar - 0x57; /* 0x57 = 0x61(a) + 0x0A*/
}
/* A-F */
if (inputChar>0x40 && inputChar<0x47) {
return inputChar - 0x37; /* 0x37 = 0x41(a) + 0x0A*/
}
/* shall never arrive here, string is not Hex*/
return 0;
}
/**
* @brief convert a byte which value is in range [0-15] into an hexa char [0-9a-fA-F]
*
* @param[in] inputByte an integer which shall be in range [0-15]
*
* @return the hexa char [0-9a-f] corresponding to the input
*/
uint8_t bzrtp_byteToChar(uint8_t inputByte) {
inputByte &=0x0F; /* restrict the input value to range [0-15] */
/* 0-9 */
if(inputByte<0x0A) {
return inputByte+0x30;
}
/* a-f */
return inputByte + 0x57;
}
......@@ -211,8 +211,24 @@ int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpC
switch (zrtpPacket->messageType) {
case MSGTYPE_HELLO :
{
/* allocate a Hello message structure */
bzrtpHelloMessage_t *messageData;
/* Do we have a peerHelloHash to check */
if (zrtpChannelContext->peerHelloHash != NULL) {
uint8_t computedPeerHelloHash[32];
/* compute hash using implicit hash function: SHA256, skip packet header in the packetString buffer as the hash must be computed on message only */
bzrtpCrypto_sha256(input+ZRTP_PACKET_HEADER_LENGTH,
inputLength - ZRTP_PACKET_OVERHEAD,
32,
computedPeerHelloHash);
/* check they are the same */
if (memcmp(computedPeerHelloHash, zrtpChannelContext->peerHelloHash, 32)!=0) {
return BZRTP_ERROR_HELLOHASH_MISMATCH;
}
}
/* allocate a Hello message structure */
messageData = (bzrtpHelloMessage_t *)malloc(sizeof(bzrtpHelloMessage_t));
/* fill it */
......
......@@ -29,6 +29,7 @@
#include "zidCache.h"
#include "typedef.h"
#include "cryptoUtils.h"
#ifdef HAVE_LIBXML2
......@@ -39,11 +40,7 @@
#define XML_HEADER_STRING "<?xml version='1.0' encoding='utf-8'?>"
#define XML_HEADER_SIZE 38
/* Local functions prototypes */
void bzrtp_strToUint8(uint8_t *outputBytes, uint8_t *inputString, uint16_t inputLength);
void bzrtp_int8ToStr(uint8_t *outputString, uint8_t *inputBytes, uint16_t inputBytesLength);
uint8_t bzrtp_byteToChar(uint8_t inputByte);
uint8_t bzrtp_charToByte(uint8_t inputChar);
void bzrtp_writeCache(bzrtpContext_t *zrtpContext);
static void bzrtp_writeCache(bzrtpContext_t *zrtpContext);
int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]) {
uint8_t *selfZidHex = NULL;
......@@ -339,7 +336,7 @@ int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *t
* @param[in/out] zrtpContext The zrtp context containing the cacheBuffer
*
*/
void bzrtp_writeCache(bzrtpContext_t *zrtpContext) {
static void bzrtp_writeCache(bzrtpContext_t *zrtpContext) {
/* dump the xml document into a string */
xmlChar *xmlStringOutput;
int xmlStringLength;
......@@ -348,80 +345,6 @@ void bzrtp_writeCache(bzrtpContext_t *zrtpContext) {
zrtpContext->zrtpCallbacks.bzrtp_writeCache(zrtpContext->channelContext[0]->clientData, xmlStringOutput, xmlStringLength);
xmlFree(xmlStringOutput);
}
/**
* @brief Convert an hexadecimal string into the corresponding byte buffer
*
* @param[out] outputBytes The output bytes buffer, must have a length of half the input string buffer
* @param[in] inputString The input string buffer, must be hexadecimal(it is not checked by function, any non hexa char is converted to 0)
* @param[in] inputStringLength The length in chars of the string buffer, output is half this length
*/
void bzrtp_strToUint8(uint8_t *outputBytes, uint8_t *inputString, uint16_t inputStringLength) {
int i;
for (i=0; i<inputStringLength/2; i++) {
outputBytes[i] = (bzrtp_charToByte(inputString[2*i]))<<4 | bzrtp_charToByte(inputString[2*i+1]);
}
}
/**
* @brief Convert a byte buffer into the corresponding hexadecimal string
*
* @param[out] outputString The output string buffer, must have a length of twice the input bytes buffer
* @param[in] inputBytes The input bytes buffer
* @param[in] inputBytesLength The length in bytes buffer, output is twice this length
*/
void bzrtp_int8ToStr(uint8_t *outputString, uint8_t *inputBytes, uint16_t inputBytesLength) {
int i;
for (i=0; i<inputBytesLength; i++) {
outputString[2*i] = bzrtp_byteToChar((inputBytes[i]>>4)&0x0F);
outputString[2*i+1] = bzrtp_byteToChar(inputBytes[i]&0x0F);
}
}
/**
* @brief convert an hexa char [0-9a-fA-F] into the corresponding unsigned integer value
* Any invalid char will be converted to zero without any warning
*
* @param[in] inputChar a char which shall be in range [0-9a-fA-F]
*
* @return the unsigned integer value in range [0-15]
*/
uint8_t bzrtp_charToByte(uint8_t inputChar) {
/* 0-9 */
if (inputChar>0x29 && inputChar<0x3A) {
return inputChar - 0x30;
}
/* a-f */
if (inputChar>0x60 && inputChar<0x67) {
return inputChar - 0x57; /* 0x57 = 0x61(a) + 0x0A*/
}
/* A-F */
if (inputChar>0x40 && inputChar<0x47) {
return inputChar - 0x37; /* 0x37 = 0x41(a) + 0x0A*/
}
/* shall never arrive here, string is not Hex*/
return 0;
}
/**
* @brief convert a byte which value is in range [0-15] into an hexa char [0-9a-fA-F]
*
* @param[in] inputByte an integer which shall be in range [0-15]
*
* @return the hexa char [0-9a-f] corresponding to the input
*/
uint8_t bzrtp_byteToChar(uint8_t inputByte) {
inputByte &=0x0F; /* restrict the input value to range [0-15] */
/* 0-9 */
if(inputByte<0x0A) {
return inputByte+0x30;
}
/* a-f */
return inputByte + 0x57;
}
#else /* NOT HAVE_LIBXML2 */
int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]) {
......
......@@ -59,6 +59,10 @@ static uint32_t patternZRTPMetaData[TEST_PACKET_NUMBER][3] = {
{28, 0x09f7, 0x12345678} /* conf2ACK*/
};
static const uint8_t patternZRTPHelloHash12345678[70]="1.10 13e9f407367895861f0eee6707ba30aca05a0ad9997625e9279ad5d08485aa9d";
static const uint8_t patternZRTPHelloHash87654321[70]="1.10 8a286f762a00f21907fe937801894ce4f4ac6a7d2b9acd61eb25b014f905df77";
static const uint8_t patternZRTPIncorrectHelloHash12345678[70]="1.10 23e9f407367895861f0eee6707ba30aca05a0ad9997625e9279ad5d08485aa9d";
static const uint8_t patternZRTPPackets[TEST_PACKET_NUMBER][512] = {
/* This is a Hello packet, sequence number is 0x09f1, SSRC 0x12345678 */
{0x10, 0x00, 0x09, 0xf1, 0x5a, 0x52, 0x54, 0x50, 0x12, 0x34, 0x56, 0x78, 0x50, 0x5a, 0x00, 0x1e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x31, 0x30, 0x4c, 0x49, 0x4e, 0x50, 0x48, 0x4f, 0x4e, 0x45, 0x2d, 0x5a, 0x52, 0x54, 0x50, 0x43, 0x50, 0x50, 0xe8, 0xd5, 0x26, 0xc1, 0x3a, 0x0c, 0x4c, 0x6a, 0xce, 0x18, 0xaa, 0xc7, 0xc4, 0xa4, 0x07, 0x0e, 0x65, 0x7a, 0x4d, 0xca, 0x78, 0xf2, 0xcc, 0xcd, 0x20, 0x50, 0x38, 0x73, 0xe9, 0x7e, 0x08, 0x29, 0x7e, 0xb0, 0x04, 0x97, 0xc0, 0xfe, 0xb2, 0xc9, 0x24, 0x31, 0x49, 0x7f, 0x00, 0x01, 0x12, 0x31, 0x53, 0x32, 0x35, 0x36, 0x41, 0x45, 0x53, 0x31, 0x48, 0x53, 0x33, 0x32, 0x48, 0x53, 0x38, 0x30, 0x44, 0x48, 0x33, 0x6b, 0x44, 0x48, 0x32, 0x6b, 0x4d, 0x75, 0x6c, 0x74, 0x42, 0x33, 0x32, 0x20, 0xa0, 0xfd, 0x0f, 0xad, 0xeb, 0xe0, 0x86, 0x56, 0xe3, 0x65, 0x81, 0x02},
......@@ -154,18 +158,31 @@ void test_parser(void) {
/* set the role: 87654321 is initiator in our exchange pattern */
context12345678->channelContext[0]->role = RESPONDER;
/* set the peer hello packet Hash for context 12345678, the other one will be set after Hello Packet reception */
bzrtp_setPeerHelloHash(context12345678, 0x12345678, (uint8_t *)patternZRTPHelloHash87654321, strlen((const char *)patternZRTPHelloHash87654321));
for (i=0; i<TEST_PACKET_NUMBER; i++) {
uint8_t freePacketFlag = 1;
/* parse a packet string from patterns */
zrtpPacket = bzrtp_packetCheck(patternZRTPPackets[i], patternZRTPMetaData[i][0], (patternZRTPMetaData[i][1])-1, &retval);
retval += bzrtp_packetParser((patternZRTPMetaData[i][2]==0x87654321)?context12345678:context87654321, (patternZRTPMetaData[i][2]==0x87654321)?context12345678->channelContext[0]:context87654321->channelContext[0], patternZRTPPackets[i], patternZRTPMetaData[i][0], zrtpPacket);
/*printf("parsing Ret val is %x index is %d\n", retval, i);*/
bzrtp_message("parsing Ret val is %x index is %d\n", retval, i);
CU_ASSERT_EQUAL_FATAL(retval,0);
/* We must store some packets in the context if we want to be able to parse further packets */
/* Check also the zrtp hello hash */
if (zrtpPacket->messageType==MSGTYPE_HELLO) {
if (patternZRTPMetaData[i][2]==0x87654321) {
context12345678->channelContext[0]->peerPackets[HELLO_MESSAGE_STORE_ID] = zrtpPacket;
} else {
context87654321->channelContext[0]->peerPackets[HELLO_MESSAGE_STORE_ID] = zrtpPacket;
/* Set an incorrect peerHello Hash after the packet hello packet arrives */
retval = bzrtp_setPeerHelloHash(context87654321, 0x87654321, (uint8_t *)patternZRTPIncorrectHelloHash12345678, strlen((const char *)patternZRTPIncorrectHelloHash12345678));
CU_ASSERT_EQUAL_FATAL(retval,BZRTP_ERROR_HELLOHASH_MISMATCH);
/* Set the correct one */
retval = bzrtp_setPeerHelloHash(context87654321, 0x87654321, (uint8_t *)patternZRTPHelloHash12345678, strlen((const char *)patternZRTPHelloHash12345678));
CU_ASSERT_EQUAL_FATAL(retval,0);
}
freePacketFlag = 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment