packetParser.c 71.1 KB
Newer Older
johan's avatar
johan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/**
 @file packetParser.c
 
 @brief functions to parse and generate a ZRTP packet 
 
 @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
22
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
johan's avatar
johan committed
23 24 25 26 27 28
 */

#include <stdlib.h>
#include <string.h>
#include "typedef.h"
#include "packetParser.h"
29
#include <bctoolbox/crypto.h>
johan's avatar
johan committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#include "cryptoUtils.h"

/* DEBUG */
#include <stdio.h>

/* minimum length of a ZRTP packet: 12 bytes header + 12 bytes message(shortest are ACK messages) + 4 bytes CRC */
#define ZRTP_MIN_PACKET_LENGTH 28

/* maximum length of a ZRTP packet: 3072 bytes get it from GNU-ZRTP CPP code */
#define ZRTP_MAX_PACKET_LENGTH 3072

/* header of ZRTP message is 12 bytes : Preambule/Message Length + Message Type(2 words) */
#define ZRTP_MESSAGE_HEADER_LENGTH 12

/* length of the non optional and fixed part of all messages, in bytes */
#define ZRTP_HELLOMESSAGE_FIXED_LENGTH			88 
#define ZRTP_HELLOACKMESSAGE_FIXED_LENGTH		12
#define ZRTP_COMMITMESSAGE_FIXED_LENGTH 		84
#define ZRTP_DHPARTMESSAGE_FIXED_LENGTH 		84
#define ZRTP_CONFIRMMESSAGE_FIXED_LENGTH		76 
#define ZRTP_CONF2ACKMESSAGE_FIXED_LENGTH 		12
#define ZRTP_ERRORMESSAGE_FIXED_LENGTH 			16
#define ZRTP_ERRORACKMESSAGE_FIXED_LENGTH 		12
#define ZRTP_GOCLEARMESSAGE_FIXED_LENGTH		20 
#define ZRTP_CLEARACKMESSAGE_FIXED_LENGTH 		12
#define ZRTP_SASRELAYMESSAGE_FIXED_LENGTH 		76
#define ZRTP_RELAYACKMESSAGE_FIXED_LENGTH 		12
#define ZRTP_PINGMESSAGE_FIXED_LENGTH 			24
#define ZRTP_PINGACKMESSAGE_FIXED_LENGTH 		36

/*** local functions prototypes ***/

/**
 * Return the variable private value length in bytes according to given key agreement algorythm
 *
 * @param[in]	keyAgreementAlgo	The key agreement algo mapped to an integer as defined in cryptoWrapper.h
 *
 * @return		the private value length in bytes
 *
 */
uint16_t computeKeyAgreementPrivateValueLength(uint8_t keyAgreementAlgo);

/**
 * @brief Retrieve the 8 char string value message type from the int32_t code
 *
 * @param[in] messageType		The messageType code
 *
 * @return	an 9 char string : 8 chars message type as specified in rfc section 5.1.1 + string terminating char
 */
uint8_t *messageTypeInttoString(uint32_t messageType);

/**
 * @brief Map the 8 char string value message type to an int32_t
 *
 * @param[in] messageTypeString		an 8 bytes string matching a zrtp message type
 *
 * @return	a 32-bits unsigned integer mapping the message type
 */
int32_t messageTypeStringtoInt(uint8_t messageTypeString[8]);

/**
 * @brief Write the message header(preambule, length, message type) into the given output buffer
 *
 * @param[out]	outputBuffer		Message starts at the begining of this buffer
 * @param[in]	messageLength		Message length in bytes! To be converted into 32bits words before being inserted in the message header
 * @param[in]	messageType			An 8 chars string for the message type (validity is not checked by this function)
 *
 */
void zrtpMessageSetHeader(uint8_t *outputBuffer, uint16_t messageLength, uint8_t messageType[8]);




/*** Public functions implementation ***/

/* First call this function to check packet validity and create the packet structure */
bzrtpPacket_t *bzrtp_packetCheck(const uint8_t * input, uint16_t inputLength, uint16_t lastValidSequenceNumber, int *exitCode) {
107 108 109 110 111
	bzrtpPacket_t *zrtpPacket;
	uint16_t sequenceNumber;
	uint32_t packetCRC;
	uint16_t messageLength;
	uint32_t messageType;
johan's avatar
johan committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

	/* first check that the packet is a ZRTP one */
	/* is the length compatible with a ZRTP packet */ 
	if ((inputLength<ZRTP_MIN_PACKET_LENGTH) || (inputLength>ZRTP_MAX_PACKET_LENGTH)) {
		 *exitCode = BZRTP_PARSER_ERROR_INVALIDPACKET;
		 return NULL;
	}

	/* check ZRTP packet format from rfc section 5 
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 1|Not Used (set to zero) |         Sequence Number       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                 Magic Cookie 'ZRTP' (0x5a525450)              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Source Identifier                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                                                               |
   |           ZRTP Message (length depends on Message Type)       |
   |                            . . .                              |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          CRC (1 word)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
	if ((input[0]>>4 != 0x01) || (input[4]!= (uint8_t)((ZRTP_MAGIC_COOKIE>>24)&0xFF)) || (input[5]!= (uint8_t)((ZRTP_MAGIC_COOKIE>>16)&0xFF)) || (input[6]!= (uint8_t)((ZRTP_MAGIC_COOKIE>>8)&0xFF)) || (input[7]!= (uint8_t)(ZRTP_MAGIC_COOKIE&0xFF))) {
		*exitCode = BZRTP_PARSER_ERROR_INVALIDPACKET;
		return NULL;
	}

	/* Check the sequence number : it must be > to the last valid one (given in parameter) to discard out of order packets
	 * TODO: what if we got a Sequence Number overflowing the 16 bits ? */
144
	sequenceNumber = (((uint16_t)input[2])<<8) | ((uint16_t)input[3]);
johan's avatar
johan committed
145 146 147 148 149 150
	if (sequenceNumber <= lastValidSequenceNumber) {
		*exitCode = BZRTP_PARSER_ERROR_OUTOFORDER;
		return NULL;
	}

	/* Check the CRC : The CRC is calculated across the entire ZRTP packet, including the ZRTP header and the ZRTP message, but not including the CRC field.*/
151
	packetCRC = ((((uint32_t)input[inputLength-4])<<24)&0xFF000000) | ((((uint32_t)input[inputLength-3])<<16)&0x00FF0000) | ((((uint32_t)input[inputLength-2])<<8)&0x0000FF00) | (((uint32_t)input[inputLength-1])&0x000000FF);
johan's avatar
johan committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
	if (bzrtp_CRC32((uint8_t *)input, inputLength - 4) != packetCRC) {
		*exitCode = BZRTP_PARSER_ERROR_INVALIDCRC;
		return NULL;
	}

	/* check message header : 
	 *  0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0|             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            Message Type Block            (2 words)            |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
	if ((input[ZRTP_PACKET_HEADER_LENGTH]!=0x50) || (input[ZRTP_PACKET_HEADER_LENGTH+1]!=0x5a)) {
		*exitCode = BZRTP_PARSER_ERROR_INVALIDMESSAGE;
		return NULL;
	}

	/* get the length from the message: it is expressed in 32bits words, convert it to bytes (4*) */
172
	messageLength = 4*(((((uint16_t)input[ZRTP_PACKET_HEADER_LENGTH+2])<<8)&0xFF00) | (((uint16_t)input[ZRTP_PACKET_HEADER_LENGTH+3])&0x00FF));
johan's avatar
johan committed
173 174

	/* get the message Type */
175
	messageType = messageTypeStringtoInt((uint8_t *)(input+ZRTP_PACKET_HEADER_LENGTH+4));
johan's avatar
johan committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199

	if (messageType == MSGTYPE_INVALID) {
		*exitCode = BZRTP_PARSER_ERROR_INVALIDMESSAGE;
		return NULL;
	}

	/* packet and message seems to be valid, so allocate a structure and parse it */
	zrtpPacket = (bzrtpPacket_t *)malloc(sizeof(bzrtpPacket_t));
	memset(zrtpPacket, 0, sizeof(bzrtpPacket_t));
	zrtpPacket->sequenceNumber = sequenceNumber;
	zrtpPacket->messageLength = messageLength;
	zrtpPacket->messageType = messageType;
	zrtpPacket->messageData = NULL;
	zrtpPacket->packetString = NULL;

	/* get the SSRC */
	zrtpPacket->sourceIdentifier = ((((uint32_t)input[8])<<24)&0xFF000000) | ((((uint32_t)input[9])<<16)&0x00FF0000) | ((((uint32_t)input[10])<<8)&0x0000FF00) | (((uint32_t)input[11])&0x000000FF);

	*exitCode = 0;
	return zrtpPacket;
}


/* Call this function after the packetCheck one, to actually parse the packet : create and fill the messageData structure */
johan's avatar
johan committed
200
int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, const uint8_t * input, uint16_t inputLength, bzrtpPacket_t *zrtpPacket) {
johan's avatar
johan committed
201 202 203 204 205 206 207 208 209 210 211

	int i;

	/* now allocate and fill the correct message structure according to the message type */
	/* messageContent points to the begining of the ZRTP message */
	uint8_t *messageContent = (uint8_t *)(input+ZRTP_PACKET_HEADER_LENGTH+ZRTP_MESSAGE_HEADER_LENGTH);

	switch (zrtpPacket->messageType) {
		case MSGTYPE_HELLO : 
			{
				bzrtpHelloMessage_t *messageData;
212 213 214 215 216

				/* 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 */
jehan's avatar
jehan committed
217
					bctbx_sha256(input+ZRTP_PACKET_HEADER_LENGTH,
218 219 220 221 222 223 224 225 226 227 228
						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 */
johan's avatar
johan committed
229 230 231 232 233 234
				messageData = (bzrtpHelloMessage_t *)malloc(sizeof(bzrtpHelloMessage_t));

				/* fill it */
				memcpy(messageData->version, messageContent, 4);
				messageContent +=4;
				memcpy(messageData->clientIdentifier, messageContent, 16);
johan's avatar
johan committed
235
				messageData->clientIdentifier[16] = '\0'; /* be sure the clientIdentifier is a NULL terminated string */
johan's avatar
johan committed
236 237 238 239 240 241 242 243 244
				messageContent +=16;
				memcpy(messageData->H3, messageContent, 32);
				messageContent +=32;
				memcpy(messageData->ZID, messageContent, 12);
				messageContent +=12;
				messageData->S = ((*messageContent)>>6)&0x01;
				messageData->M = ((*messageContent)>>5)&0x01;
				messageData->P = ((*messageContent)>>4)&0x01;
				messageContent +=1;
245
				messageData->hc = MIN((*messageContent)&0x0F, 7);
johan's avatar
johan committed
246
				messageContent +=1;
247 248
				messageData->cc = MIN(((*messageContent)>>4)&0x0F, 7);
				messageData->ac = MIN((*messageContent)&0x0F, 7);
johan's avatar
johan committed
249
				messageContent +=1;
250 251
				messageData->kc = MIN(((*messageContent)>>4)&0x0F, 7);
				messageData->sc = MIN((*messageContent)&0x0F, 7);
johan's avatar
johan committed
252 253 254 255 256 257 258 259
				messageContent +=1;

				/* Check message length according to value in hc, cc, ac, kc and sc */
				if (zrtpPacket->messageLength != ZRTP_HELLOMESSAGE_FIXED_LENGTH + 4*((uint16_t)(messageData->hc)+(uint16_t)(messageData->cc)+(uint16_t)(messageData->ac)+(uint16_t)(messageData->kc)+(uint16_t)(messageData->sc))) {
					free(messageData);
					return BZRTP_PARSER_ERROR_INVALIDMESSAGE;
				}

260
				/* parse the variable length part: algorithms types */
johan's avatar
johan committed
261
				for (i=0; i<messageData->hc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
262
					messageData->supportedHash[i] = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_HASH_TYPE);
johan's avatar
johan committed
263 264 265
					messageContent +=4;
				}
				for (i=0; i<messageData->cc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
266
					messageData->supportedCipher[i] = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_CIPHERBLOCK_TYPE);
johan's avatar
johan committed
267 268 269
					messageContent +=4;
				}
				for (i=0; i<messageData->ac; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
270
					messageData->supportedAuthTag[i] = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_AUTHTAG_TYPE);
johan's avatar
johan committed
271 272 273
					messageContent +=4;
				}
				for (i=0; i<messageData->kc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
274
					messageData->supportedKeyAgreement[i] = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_KEYAGREEMENT_TYPE);
johan's avatar
johan committed
275 276 277
					messageContent +=4;
				}
				for (i=0; i<messageData->sc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
278
					messageData->supportedSas[i] = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_SAS_TYPE);
johan's avatar
johan committed
279 280 281
					messageContent +=4;
				}

Ghislain MARY's avatar
Ghislain MARY committed
282 283 284 285 286
				bzrtp_addMandatoryCryptoTypesIfNeeded(ZRTP_HASH_TYPE, messageData->supportedHash, &messageData->hc);
				bzrtp_addMandatoryCryptoTypesIfNeeded(ZRTP_CIPHERBLOCK_TYPE, messageData->supportedCipher, &messageData->cc);
				bzrtp_addMandatoryCryptoTypesIfNeeded(ZRTP_AUTHTAG_TYPE, messageData->supportedAuthTag, &messageData->ac);
				bzrtp_addMandatoryCryptoTypesIfNeeded(ZRTP_KEYAGREEMENT_TYPE, messageData->supportedKeyAgreement, &messageData->kc);
				bzrtp_addMandatoryCryptoTypesIfNeeded(ZRTP_SAS_TYPE, messageData->supportedSas, &messageData->sc);
johan's avatar
johan committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

				memcpy(messageData->MAC, messageContent, 8);
				
				/* attach the message structure to the packet one */
				zrtpPacket->messageData = (void *)messageData;

				/* the parsed Hello packet must be saved as it may be used to generate commit message or the total_hash */
				zrtpPacket->packetString = (uint8_t *)malloc(inputLength*sizeof(uint8_t));
				memcpy(zrtpPacket->packetString, input, inputLength); /* store the whole packet even if we may use the message only */
			}
			break; /* MSGTYPE_HELLO */

		case MSGTYPE_HELLOACK :
			{
				/* check message length */
				if (zrtpPacket->messageLength != ZRTP_HELLOACKMESSAGE_FIXED_LENGTH) {
					return BZRTP_PARSER_ERROR_INVALIDMESSAGE;
				}


			}
			break; /* MSGTYPE_HELLOACK */

		case MSGTYPE_COMMIT:
			{
312 313 314 315 316
				uint8_t checkH3[32];
				uint8_t checkMAC[32];
				bzrtpHelloMessage_t *peerHelloMessageData;
				uint16_t variableLength = 0;

johan's avatar
johan committed
317 318 319 320 321 322 323
				/* allocate a commit message structure */
				bzrtpCommitMessage_t *messageData;
				messageData = (bzrtpCommitMessage_t *)malloc(sizeof(bzrtpCommitMessage_t));

				/* fill the structure */
				memcpy(messageData->H2, messageContent, 32);
				messageContent +=32;
johan's avatar
johan committed
324 325 326 327 328 329 330

				/* We have now H2, check it matches the H3 we had in the hello message H3=SHA256(H2) and that the Hello message MAC is correct */
				if (zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID] == NULL) {
					free (messageData);
					/* we have no Hello message in this channel, this commit shall never have arrived, discard it as invalid */
					return BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE;
				}
331
				peerHelloMessageData = (bzrtpHelloMessage_t *)zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageData;
johan's avatar
johan committed
332
				/* Check H3 = SHA256(H2) */
jehan's avatar
jehan committed
333
				bctbx_sha256(messageData->H2, 32, 32, checkH3);
johan's avatar
johan committed
334 335 336 337 338 339
				if (memcmp(checkH3, peerHelloMessageData->H3, 32) != 0) {
					free (messageData);
					return BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN;
				}
				/* Check the hello MAC message. 
				 * MAC is 8 bytes long and is computed on the message(skip the ZRTP_PACKET_HEADER) and exclude the mac itself (-8 bytes from message Length) */
jehan's avatar
jehan committed
340
				bctbx_hmacSha256(messageData->H2, 32, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength-8, 8, checkMAC);
johan's avatar
johan committed
341 342 343 344 345
				if (memcmp(checkMAC, peerHelloMessageData->MAC, 8) != 0) {
					free (messageData);
					return BZRTP_PARSER_ERROR_UNMATCHINGMAC;
				}

johan's avatar
johan committed
346 347
				memcpy(messageData->ZID, messageContent, 12);
				messageContent +=12;
Ghislain MARY's avatar
Ghislain MARY committed
348
				messageData->hashAlgo = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_HASH_TYPE);
johan's avatar
johan committed
349
				messageContent += 4;
Ghislain MARY's avatar
Ghislain MARY committed
350
				messageData->cipherAlgo = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_CIPHERBLOCK_TYPE);
johan's avatar
johan committed
351
				messageContent += 4;
Ghislain MARY's avatar
Ghislain MARY committed
352
				messageData->authTagAlgo = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_AUTHTAG_TYPE);
johan's avatar
johan committed
353
				messageContent += 4;
Ghislain MARY's avatar
Ghislain MARY committed
354
				messageData->keyAgreementAlgo = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_KEYAGREEMENT_TYPE);
johan's avatar
johan committed
355 356 357 358
				messageContent += 4;
				/* commit message length depends on the key agreement type choosen (and set in the zrtpContext->keyAgreementAlgo) */
				switch(messageData->keyAgreementAlgo) {
					case ZRTP_KEYAGREEMENT_DH2k :
359 360
					case ZRTP_KEYAGREEMENT_X255 :
					case ZRTP_KEYAGREEMENT_X448 :
johan's avatar
johan committed
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
					case ZRTP_KEYAGREEMENT_EC25 :
					case ZRTP_KEYAGREEMENT_DH3k :
					case ZRTP_KEYAGREEMENT_EC38 :
					case ZRTP_KEYAGREEMENT_EC52 :
						variableLength = 32; /* hvi is 32 bytes length in DH Commit message format */
						break;
					case ZRTP_KEYAGREEMENT_Prsh :
						variableLength = 24; /* nonce (16 bytes) and keyID(8 bytes) are 24 bytes length in preshared Commit message format */
						break;
					case ZRTP_KEYAGREEMENT_Mult :
						variableLength = 16; /* nonce is 24 bytes length in multistream Commit message format */
						break;
					default:
						free(messageData);
						return BZRTP_PARSER_ERROR_INVALIDMESSAGE;
				}

				if (zrtpPacket->messageLength != ZRTP_COMMITMESSAGE_FIXED_LENGTH + variableLength) {
					free(messageData);
					return BZRTP_PARSER_ERROR_INVALIDMESSAGE;
				}
Ghislain MARY's avatar
Ghislain MARY committed
382
				messageData->sasAlgo = bzrtp_cryptoAlgoTypeStringToInt(messageContent, ZRTP_SAS_TYPE);
johan's avatar
johan committed
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
				messageContent += 4;

				/* if it is a multistream or preshared commit, get the 16 bytes nonce */
				if ((messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) || (messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult)) {
					memcpy(messageData->nonce, messageContent, 16);
					messageContent +=16;

					/* and the keyID for preshared commit only */
					if (messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) {
						memcpy(messageData->keyID, messageContent, 8);
						messageContent +=8;
					}
				} else { /* it's a DH commit message, get the hvi */
					memcpy(messageData->hvi, messageContent, 32);
					messageContent +=32;
				}

				/* get the MAC and attach the message data to the packet structure */
				memcpy(messageData->MAC, messageContent, 8);
				zrtpPacket->messageData = (void *)messageData;

				/* the parsed commit packet must be saved as it is used to generate the total_hash */
				zrtpPacket->packetString = (uint8_t *)malloc(inputLength*sizeof(uint8_t));
				memcpy(zrtpPacket->packetString, input, inputLength); /* store the whole packet even if we may use the message only */
			}
			break; /* MSGTYPE_COMMIT */
		case MSGTYPE_DHPART1 :
		case MSGTYPE_DHPART2 :
			{
412 413
				bzrtpDHPartMessage_t *messageData;

johan's avatar
johan committed
414
				/*check message length, depends on the selected key agreement algo set in zrtpContext */
johan's avatar
johan committed
415
				uint16_t pvLength = computeKeyAgreementPrivateValueLength(zrtpChannelContext->keyAgreementAlgo);
johan's avatar
johan committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
				if (pvLength == 0) {
					return BZRTP_PARSER_ERROR_INVALIDCONTEXT;
				}

				if (zrtpPacket->messageLength != ZRTP_DHPARTMESSAGE_FIXED_LENGTH+pvLength) {
					return BZRTP_PARSER_ERROR_INVALIDMESSAGE;
				}

				/* allocate a DHPart message structure and pv */
				messageData = (bzrtpDHPartMessage_t *)malloc(sizeof(bzrtpDHPartMessage_t));
				messageData->pv = (uint8_t *)malloc(pvLength*sizeof(uint8_t));

				/* fill the structure */
				memcpy(messageData->H1, messageContent, 32);
				messageContent +=32;
johan's avatar
johan committed
431 432

				/* We have now H1, check it matches the H2 we had in the commit message H2=SHA256(H1) and that the Commit message MAC is correct */
johan's avatar
johan committed
433
				if ( zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) { /* do it only if we are responder (we received a commit packet) */
johan's avatar
johan committed
434 435
					uint8_t checkH2[32];
					uint8_t checkMAC[32];
436 437
					bzrtpCommitMessage_t *peerCommitMessageData;

johan's avatar
johan committed
438 439 440 441 442
					if (zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID] == NULL) {
						free (messageData);
						/* we have no Commit message in this channel, this DHPart2 shall never have arrived, discard it as invalid */
						return BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE;
					}
443
					peerCommitMessageData = (bzrtpCommitMessage_t *)zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID]->messageData;
johan's avatar
johan committed
444
					/* Check H2 = SHA256(H1) */
jehan's avatar
jehan committed
445
					bctbx_sha256(messageData->H1, 32, 32, checkH2);
johan's avatar
johan committed
446 447 448 449 450 451
					if (memcmp(checkH2, peerCommitMessageData->H2, 32) != 0) {
						free (messageData);
						return BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN;
					}
					/* Check the Commit MAC message. 
					 * MAC is 8 bytes long and is computed on the message(skip the ZRTP_PACKET_HEADER) and exclude the mac itself (-8 bytes from message Length) */
jehan's avatar
jehan committed
452
					bctbx_hmacSha256(messageData->H1, 32, zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID]->messageLength-8, 8, checkMAC);
johan's avatar
johan committed
453 454 455 456
					if (memcmp(checkMAC, peerCommitMessageData->MAC, 8) != 0) {
						free (messageData);
						return BZRTP_PARSER_ERROR_UNMATCHINGMAC;
					}
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482

					/* Check the hvi received in the commit message  - RFC section 4.4.1.1*/
					/* First compute the expected hvi */
					/* hvi = hash(initiator's DHPart2 message(current zrtpPacket)) || responder's Hello message) using the agreed hash function truncated to 256 bits */
					/* create a string with the messages concatenated */
					{
						uint8_t computedHvi[32];
						uint16_t HelloMessageLength = zrtpChannelContext->selfPackets[HELLO_MESSAGE_STORE_ID]->messageLength;
						uint16_t DHPartHelloMessageStringLength = zrtpPacket->messageLength + HelloMessageLength;

						uint8_t *DHPartHelloMessageString = (uint8_t *)malloc(DHPartHelloMessageStringLength*sizeof(uint8_t));

						memcpy(DHPartHelloMessageString, input+ZRTP_PACKET_HEADER_LENGTH, zrtpPacket->messageLength);
						memcpy(DHPartHelloMessageString+zrtpPacket->messageLength, zrtpChannelContext->selfPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, HelloMessageLength);

						zrtpChannelContext->hashFunction(DHPartHelloMessageString, DHPartHelloMessageStringLength, 32, computedHvi);

						free(DHPartHelloMessageString);

						/* Compare computed and received hvi */
						if (memcmp(computedHvi, peerCommitMessageData->hvi, 32)!=0) {
							free (messageData);
							return BZRTP_PARSER_ERROR_UNMATCHINGHVI;
						}
					}

johan's avatar
johan committed
483 484 485 486
				} else { /* if we are initiator(we didn't received any commit message and then no H2), we must check that H3=SHA256(SHA256(H1)) and the Hello message MAC */
					uint8_t checkH2[32];
					uint8_t checkH3[32];
					uint8_t checkMAC[32];
487 488
					bzrtpHelloMessage_t *peerHelloMessageData;

johan's avatar
johan committed
489 490 491 492 493
					if (zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID] == NULL) {
						free (messageData);
						/* we have no Hello message in this channel, this DHPart1 shall never have arrived, discard it as invalid */
						return BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE;
					}
494
					peerHelloMessageData = (bzrtpHelloMessage_t *)zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageData;
johan's avatar
johan committed
495
					/* Check H3 = SHA256(SHA256(H1)) */
jehan's avatar
jehan committed
496 497
					bctbx_sha256(messageData->H1, 32, 32, checkH2);
					bctbx_sha256(checkH2, 32, 32, checkH3);
johan's avatar
johan committed
498 499 500 501 502 503
					if (memcmp(checkH3, peerHelloMessageData->H3, 32) != 0) {
						free (messageData);
						return BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN;
					}
					/* Check the hello MAC message. 
					 * MAC is 8 bytes long and is computed on the message(skip the ZRTP_PACKET_HEADER) and exclude the mac itself (-8 bytes from message Length) */
jehan's avatar
jehan committed
504
					bctbx_hmacSha256(checkH2, 32, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength-8, 8, checkMAC);
johan's avatar
johan committed
505 506 507 508 509 510 511
					if (memcmp(checkMAC, peerHelloMessageData->MAC, 8) != 0) {
						free (messageData);
						return BZRTP_PARSER_ERROR_UNMATCHINGMAC;
					}

				}

johan's avatar
johan committed
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
				memcpy(messageData->rs1ID, messageContent, 8);
				messageContent +=8;
				memcpy(messageData->rs2ID, messageContent, 8);
				messageContent +=8;
				memcpy(messageData->auxsecretID, messageContent, 8);
				messageContent +=8;
				memcpy(messageData->pbxsecretID, messageContent, 8);
				messageContent +=8;
				memcpy(messageData->pv, messageContent, pvLength);
				messageContent +=pvLength;
				memcpy(messageData->MAC, messageContent, 8);

				/* attach the message structure to the packet one */
				zrtpPacket->messageData = (void *)messageData;

527
				/* the parsed packet must be saved as it is used to generate the total_hash */
johan's avatar
johan committed
528 529 530 531 532 533 534 535 536
				zrtpPacket->packetString = (uint8_t *)malloc(inputLength*sizeof(uint8_t));
				memcpy(zrtpPacket->packetString, input, inputLength); /* store the whole packet even if we may use the message only */
			}
			break; /* MSGTYPE_DHPART1 and MSGTYPE_DHPART2 */
		case MSGTYPE_CONFIRM1:
		case MSGTYPE_CONFIRM2:
			{
				uint8_t *confirmMessageKey = NULL;
				uint8_t *confirmMessageMacKey = NULL;
537 538 539 540 541 542
				bzrtpConfirmMessage_t *messageData;
				uint16_t cipherTextLength;
				uint8_t computedHmac[8];
				uint8_t *confirmPlainMessageBuffer;
				uint8_t *confirmPlainMessage;

johan's avatar
johan committed
543
				/* we shall first decrypt and validate the message, check we have the keys to do it */
johan's avatar
johan committed
544
				if (zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) { /* responder uses initiator's keys to decrypt */
johan's avatar
johan committed
545
					if ((zrtpChannelContext->zrtpkeyi == NULL) || (zrtpChannelContext->mackeyi == NULL)) {
johan's avatar
johan committed
546 547
						return BZRTP_PARSER_ERROR_INVALIDCONTEXT;
					}
johan's avatar
johan committed
548 549
					confirmMessageKey = zrtpChannelContext->zrtpkeyi;
					confirmMessageMacKey = zrtpChannelContext->mackeyi;
johan's avatar
johan committed
550 551
				}

johan's avatar
johan committed
552
				if (zrtpChannelContext->role == BZRTP_ROLE_INITIATOR) { /* the iniator uses responder's keys to decrypt */
johan's avatar
johan committed
553
					if ((zrtpChannelContext->zrtpkeyr == NULL) || (zrtpChannelContext->mackeyr == NULL)) {
johan's avatar
johan committed
554 555
						return BZRTP_PARSER_ERROR_INVALIDCONTEXT;
					}
johan's avatar
johan committed
556 557
					confirmMessageKey = zrtpChannelContext->zrtpkeyr;
					confirmMessageMacKey = zrtpChannelContext->mackeyr;
johan's avatar
johan committed
558 559 560 561 562 563 564 565 566 567 568 569 570 571
				}
				
				/* allocate a confirm message structure */
				messageData = (bzrtpConfirmMessage_t *)malloc(sizeof(bzrtpConfirmMessage_t));

				/* get the mac and the IV */
				memcpy(messageData->confirm_mac, messageContent, 8);
				messageContent +=8;
				memcpy(messageData->CFBIV, messageContent, 16);
				messageContent +=16;


				
				/* get the cipher text length */
572
				cipherTextLength = zrtpPacket->messageLength - ZRTP_MESSAGE_HEADER_LENGTH - 24; /* confirm message is header, confirm_mac(8 bytes), CFB IV(16 bytes), encrypted part */
johan's avatar
johan committed
573 574

				/* validate the mac over the cipher text */
johan's avatar
johan committed
575 576
				zrtpChannelContext->hmacFunction(confirmMessageMacKey, zrtpChannelContext->hashLength, messageContent, cipherTextLength, 8, computedHmac);
				
johan's avatar
johan committed
577 578 579 580 581 582
				if (memcmp(computedHmac, messageData->confirm_mac, 8) != 0) { /* confirm_mac doesn't match */
					free(messageData);
					return BZRTP_PARSER_ERROR_UNMATCHINGCONFIRMMAC;
				}

				/* get plain message */
583
				confirmPlainMessageBuffer = (uint8_t *)malloc(cipherTextLength*sizeof(uint8_t));
584
				zrtpChannelContext->cipherDecryptionFunction(confirmMessageKey, messageData->CFBIV, messageContent, cipherTextLength, confirmPlainMessageBuffer);
585
				confirmPlainMessage = confirmPlainMessageBuffer; /* point into the allocated buffer */
johan's avatar
johan committed
586 587 588 589

				/* parse it */
				memcpy(messageData->H0, confirmPlainMessage, 32);
				confirmPlainMessage +=33; /* +33 because next 8 bits are unused */
johan's avatar
johan committed
590 591 592 593 594

				/* Hash chain checking: if we are in multichannel or shared mode, we had not DHPart and then no H1 */
				if (zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh || zrtpChannelContext->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult) {
					/* compute the H1=SHA256(H0) we never received */
					uint8_t checkH1[32];
jehan's avatar
jehan committed
595
					bctbx_sha256(messageData->H0, 32, 32, checkH1);
johan's avatar
johan committed
596 597

					/* if we are responder, we received a commit packet with H2 then check that H2=SHA256(H1) and that the commit message MAC keyed with H1 match */
johan's avatar
johan committed
598
					if ( zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) {
johan's avatar
johan committed
599 600
						uint8_t checkH2[32];
						uint8_t checkMAC[32];
601 602
						bzrtpCommitMessage_t *peerCommitMessageData;

johan's avatar
johan committed
603 604 605 606 607
						if (zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID] == NULL) {
							free (messageData);
							/* we have no Commit message in this channel, this Confirm2 shall never have arrived, discard it as invalid */
							return BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE;
						}
608
						peerCommitMessageData = (bzrtpCommitMessage_t *)zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID]->messageData;
johan's avatar
johan committed
609
						/* Check H2 = SHA256(H1) */
jehan's avatar
jehan committed
610
						bctbx_sha256(checkH1, 32, 32, checkH2);
johan's avatar
johan committed
611 612 613 614 615 616
						if (memcmp(checkH2, peerCommitMessageData->H2, 32) != 0) {
							free (messageData);
							return BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN;
						}
						/* Check the Commit MAC message. 
						 * MAC is 8 bytes long and is computed on the message(skip the ZRTP_PACKET_HEADER) and exclude the mac itself (-8 bytes from message Length) */
jehan's avatar
jehan committed
617
						bctbx_hmacSha256(checkH1, 32, zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpChannelContext->peerPackets[COMMIT_MESSAGE_STORE_ID]->messageLength-8, 8, checkMAC);
johan's avatar
johan committed
618 619 620 621 622 623 624 625
						if (memcmp(checkMAC, peerCommitMessageData->MAC, 8) != 0) {
							free (messageData);
							return BZRTP_PARSER_ERROR_UNMATCHINGMAC;
						}
					} else { /* if we are initiator(we didn't received any commit message and then no H2), we must check that H3=SHA256(SHA256(H1)) and the Hello message MAC */
						uint8_t checkH2[32];
						uint8_t checkH3[32];
						uint8_t checkMAC[32];
626 627
						bzrtpHelloMessage_t *peerHelloMessageData;

johan's avatar
johan committed
628 629 630 631 632
						if (zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID] == NULL) {
							free (messageData);
							/* we have no Hello message in this channel, this Confirm1 shall never have arrived, discard it as invalid */
							return BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE;
						}
633
						peerHelloMessageData = (bzrtpHelloMessage_t *)zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageData;
johan's avatar
johan committed
634
						/* Check H3 = SHA256(SHA256(H1)) */
jehan's avatar
jehan committed
635 636
						bctbx_sha256(checkH1, 32, 32, checkH2);
						bctbx_sha256(checkH2, 32, 32, checkH3);
johan's avatar
johan committed
637 638 639 640 641 642
						if (memcmp(checkH3, peerHelloMessageData->H3, 32) != 0) {
							free (messageData);
							return BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN;
						}
						/* Check the hello MAC message. 
						 * MAC is 8 bytes long and is computed on the message(skip the ZRTP_PACKET_HEADER) and exclude the mac itself (-8 bytes from message Length) */
jehan's avatar
jehan committed
643
						bctbx_hmacSha256(checkH2, 32, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength-8, 8, checkMAC);
johan's avatar
johan committed
644 645 646 647 648 649 650 651 652 653
						if (memcmp(checkMAC, peerHelloMessageData->MAC, 8) != 0) {
							free (messageData);
							return BZRTP_PARSER_ERROR_UNMATCHINGMAC;
						}
	
					}
				} else { /* we are in DHM mode */
					/* We have now H0, check it matches the H1 we had in the DHPart message H1=SHA256(H0) and that the DHPart message MAC is correct */
					uint8_t checkH1[32];
					uint8_t checkMAC[32];
654 655
					bzrtpDHPartMessage_t *peerDHPartMessageData;

johan's avatar
johan committed
656 657 658 659 660
					if (zrtpChannelContext->peerPackets[DHPART_MESSAGE_STORE_ID] == NULL) {
						free (messageData);
						/* we have no DHPART message in this channel, this confirm shall never have arrived, discard it as invalid */
						return BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE;
					}
661
					peerDHPartMessageData = (bzrtpDHPartMessage_t *)zrtpChannelContext->peerPackets[DHPART_MESSAGE_STORE_ID]->messageData;
johan's avatar
johan committed
662
					/* Check H1 = SHA256(H0) */
jehan's avatar
jehan committed
663
					bctbx_sha256(messageData->H0, 32, 32, checkH1);
johan's avatar
johan committed
664 665 666 667 668 669
					if (memcmp(checkH1, peerDHPartMessageData->H1, 32) != 0) {
						free (messageData);
						return BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN;
					}
					/* Check the DHPart message. 
					 * MAC is 8 bytes long and is computed on the message(skip the ZRTP_PACKET_HEADER) and exclude the mac itself (-8 bytes from message Length) */
jehan's avatar
jehan committed
670
					bctbx_hmacSha256(messageData->H0, 32, zrtpChannelContext->peerPackets[DHPART_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpChannelContext->peerPackets[DHPART_MESSAGE_STORE_ID]->messageLength-8, 8, checkMAC);
johan's avatar
johan committed
671 672 673 674 675 676
					if (memcmp(checkMAC, peerDHPartMessageData->MAC, 8) != 0) {
						free (messageData);
						return BZRTP_PARSER_ERROR_UNMATCHINGMAC;
					}
				}

johan's avatar
johan committed
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
				messageData->sig_len = ((uint16_t)(confirmPlainMessage[0]&0x01))<<8 | (((uint16_t)confirmPlainMessage[1])&0x00FF);
				confirmPlainMessage += 2;
				messageData->E = ((*confirmPlainMessage)&0x08)>>3;
				messageData->V = ((*confirmPlainMessage)&0x04)>>2;
				messageData->A = ((*confirmPlainMessage)&0x02)>>1;
				messageData->D = (*confirmPlainMessage)&0x01;
				confirmPlainMessage += 1;

				messageData->cacheExpirationInterval = (((uint32_t)confirmPlainMessage[0])<<24) | (((uint32_t)confirmPlainMessage[1])<<16) | (((uint32_t)confirmPlainMessage[2])<<8) | ((uint32_t)confirmPlainMessage[3]);
				confirmPlainMessage += 4;


				/* if sig_len indicate a signature, parse it */
				if (messageData->sig_len>0) {
					memcpy(messageData->signatureBlockType, confirmPlainMessage, 4);
					confirmPlainMessage += 4;
					/* allocate memory for the signature block, sig_len is in words(32 bits) and includes the signature block type word */
					messageData->signatureBlock = (uint8_t *)malloc(4*(messageData->sig_len-1)*sizeof(uint8_t));
					memcpy(messageData->signatureBlock, confirmPlainMessage, 4*(messageData->sig_len-1));
				} else {
					messageData->signatureBlock  = NULL;
				}

700 701 702
				/* free plain buffer */
				free(confirmPlainMessageBuffer);

703 704 705 706
				/* the parsed commit packet must be saved as it is used to check correct packet repetition */
				zrtpPacket->packetString = (uint8_t *)malloc(inputLength*sizeof(uint8_t));
				memcpy(zrtpPacket->packetString, input, inputLength); /* store the whole packet even if we may use the message only */

johan's avatar
johan committed
707 708 709 710
				/* attach the message structure to the packet one */
				zrtpPacket->messageData = (void *)messageData;
			}
			break; /* MSGTYPE_CONFIRM1 and MSGTYPE_CONFIRM2 */
711

johan's avatar
johan committed
712 713 714
		case MSGTYPE_CONF2ACK:
			/* nothing to do for this one */
			break; /* MSGTYPE_CONF2ACK */
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
		
		case MSGTYPE_PING:
			{
				/* allocate a ping message structure */
				bzrtpPingMessage_t *messageData;
				messageData = (bzrtpPingMessage_t *)malloc(sizeof(bzrtpPingMessage_t));

				/* fill the structure */
				memcpy(messageData->version, messageContent, 4);
				messageContent +=4;
				memcpy(messageData->endpointHash, messageContent, 8);

				/* attach the message structure to the packet one */
				zrtpPacket->messageData = (void *)messageData;
			}
			break; /* MSGTYPE_PING */

johan's avatar
johan committed
732 733 734 735 736 737
	}

	return 0;
}

/* Create the packet string from the messageData contained into the zrtp Packet structure */
johan's avatar
johan committed
738
int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, bzrtpPacket_t *zrtpPacket, uint16_t sequenceNumber) {
johan's avatar
johan committed
739 740
	
	int i;
741 742 743 744 745 746
	uint8_t *messageTypeString;
	uint8_t *messageString = NULL; /* will point directly to the begining of the message within the packetString buffer */
	uint8_t *MACbuffer = NULL; /* if needed this will point to the beginin of the MAC in the packetString buffer */
	/*uint8_t *MACMessageData = NULL; */ /* if needed this will point to the MAC field in the message Data structure */
	uint8_t *MACkey = NULL;

johan's avatar
johan committed
747 748 749 750 751 752
	/* checks */
	if (zrtpPacket==NULL) {
		return BZRTP_BUILDER_ERROR_INVALIDPACKET;
	}

	/* get the message type (and check it is valid) */
753
	messageTypeString = messageTypeInttoString(zrtpPacket->messageType);
johan's avatar
johan committed
754 755 756 757 758 759 760 761
	if (messageTypeString == NULL) {
		return BZRTP_BUILDER_ERROR_INVALIDMESSAGETYPE;
	}

	/* create first the message. Header and CRC will be added afterward */
	switch (zrtpPacket->messageType) {
		case MSGTYPE_HELLO : 
			{
762 763
				bzrtpHelloMessage_t *messageData;

johan's avatar
johan committed
764 765 766 767
				/* get the Hello message structure */
				if (zrtpPacket->messageData == NULL) {
					return BZRTP_BUILDER_ERROR_INVALIDMESSAGE;
				}
768
				messageData = (bzrtpHelloMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798

				/* compute the message length in bytes : fixed length and optionnal algorithms parts */
				zrtpPacket->messageLength = ZRTP_HELLOMESSAGE_FIXED_LENGTH + 4*((uint16_t)(messageData->hc)+(uint16_t)(messageData->cc)+(uint16_t)(messageData->ac)+(uint16_t)(messageData->kc)+(uint16_t)(messageData->sc));

				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+zrtpPacket->messageLength+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
				/* have the messageString pointer to the begining of message(after the message header wich is computed for all messages after the switch)
				 * within the packetString buffer*/
				messageString = zrtpPacket->packetString + ZRTP_PACKET_HEADER_LENGTH + ZRTP_MESSAGE_HEADER_LENGTH;

				/* set the version (shall be 1.10), Client identifier, H3, ZID, S,M,P flags and  hc,cc,ac,kc,sc */
				memcpy(messageString, messageData->version, 4);
				messageString += 4;
				memcpy(messageString, messageData->clientIdentifier, 16);
				messageString += 16;
				memcpy(messageString, messageData->H3, 32);
				messageString += 32;
				memcpy(messageString, messageData->ZID, 12);
				messageString += 12;
				*messageString = ((((messageData->S)&0x01)<<6) | (((messageData->M)&0x01)<<5) | (((messageData->P)&0x01)<<4))&0x70;
				messageString += 1;
				*messageString = (messageData->hc)&0x0F;
				messageString += 1;
				*messageString = (((messageData->cc)<<4)&0xF0) | ((messageData->ac)&0x0F) ;
				messageString += 1;
				*messageString = (((messageData->kc)<<4)&0xF0) | ((messageData->sc)&0x0F) ;
				messageString += 1;

				/* now set optionnal supported algorithms */
				for (i=0; i<messageData->hc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
799
					bzrtp_cryptoAlgoTypeIntToString(messageData->supportedHash[i], messageString);
johan's avatar
johan committed
800 801 802
					messageString +=4;
				}
				for (i=0; i<messageData->cc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
803
					bzrtp_cryptoAlgoTypeIntToString(messageData->supportedCipher[i], messageString);
johan's avatar
johan committed
804 805 806
					messageString +=4;
				}
				for (i=0; i<messageData->ac; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
807
					bzrtp_cryptoAlgoTypeIntToString(messageData->supportedAuthTag[i], messageString);
johan's avatar
johan committed
808 809 810
					messageString +=4;
				}
				for (i=0; i<messageData->kc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
811
					bzrtp_cryptoAlgoTypeIntToString(messageData->supportedKeyAgreement[i], messageString);
johan's avatar
johan committed
812 813 814
					messageString +=4;
				}
				for (i=0; i<messageData->sc; i++) {
Ghislain MARY's avatar
Ghislain MARY committed
815
					bzrtp_cryptoAlgoTypeIntToString(messageData->supportedSas[i], messageString);
johan's avatar
johan committed
816 817 818 819 820
					messageString +=4;
				}

				/* there is a MAC to compute, set the pointers to the key and MAC output buffer */
				MACbuffer = messageString;
johan's avatar
johan committed
821
				MACkey = zrtpChannelContext->selfH[2]; /* HMAC of Hello packet is keyed by H2 which have been set at context initialising */
johan's avatar
johan committed
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837

			}
			break; /* MSGTYPE_HELLO */

		case MSGTYPE_HELLOACK : 
			{
				/* the message length is fixed */
				zrtpPacket->messageLength = ZRTP_HELLOACKMESSAGE_FIXED_LENGTH;

				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+ZRTP_HELLOACKMESSAGE_FIXED_LENGTH+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
			}
			break; /* MSGTYPE_HELLOACK */

		case MSGTYPE_COMMIT :
			{
838 839 840
				bzrtpCommitMessage_t *messageData;
				uint16_t variableLength = 0;

johan's avatar
johan committed
841 842 843 844 845
				/* get the Commit message structure */
				if (zrtpPacket->messageData == NULL) {
					return BZRTP_BUILDER_ERROR_INVALIDMESSAGE;
				}

846
				messageData = (bzrtpCommitMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
847 848 849 850 851

				/* compute message length */
				switch(messageData->keyAgreementAlgo) {
					case ZRTP_KEYAGREEMENT_DH2k :
					case ZRTP_KEYAGREEMENT_EC25 :
852 853
					case ZRTP_KEYAGREEMENT_X255 :
					case ZRTP_KEYAGREEMENT_X448 :
johan's avatar
johan committed
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
					case ZRTP_KEYAGREEMENT_DH3k :
					case ZRTP_KEYAGREEMENT_EC38 :
					case ZRTP_KEYAGREEMENT_EC52 :
						variableLength = 32; /* hvi is 32 bytes length in DH Commit message format */
						break;
					case ZRTP_KEYAGREEMENT_Prsh :
						variableLength = 24; /* nonce (16 bytes) and keyID(8 bytes) are 24 bytes length in preshared Commit message format */
						break;
					case ZRTP_KEYAGREEMENT_Mult :
						variableLength = 16; /* nonce is 24 bytes length in multistream Commit message format */
						break;
					default:
						return BZRTP_BUILDER_ERROR_INVALIDMESSAGE;
				}
				zrtpPacket->messageLength = ZRTP_COMMITMESSAGE_FIXED_LENGTH + variableLength;
				
				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+zrtpPacket->messageLength+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
				/* have the messageString pointer to the begining of message(after the message header wich is computed for all messages after the switch)
				 * within the packetString buffer*/
				messageString = zrtpPacket->packetString + ZRTP_PACKET_HEADER_LENGTH + ZRTP_MESSAGE_HEADER_LENGTH;

				/* now insert the different message parts into the packetString */
				memcpy(messageString, messageData->H2, 32);
				messageString += 32;
				memcpy(messageString, messageData->ZID, 12);
				messageString += 12;
Ghislain MARY's avatar
Ghislain MARY committed
881
				bzrtp_cryptoAlgoTypeIntToString(messageData->hashAlgo, messageString);
johan's avatar
johan committed
882
				messageString += 4;
Ghislain MARY's avatar
Ghislain MARY committed
883
				bzrtp_cryptoAlgoTypeIntToString(messageData->cipherAlgo, messageString);
johan's avatar
johan committed
884
				messageString += 4;
Ghislain MARY's avatar
Ghislain MARY committed
885
				bzrtp_cryptoAlgoTypeIntToString(messageData->authTagAlgo, messageString);
johan's avatar
johan committed
886
				messageString += 4;
Ghislain MARY's avatar
Ghislain MARY committed
887
				bzrtp_cryptoAlgoTypeIntToString(messageData->keyAgreementAlgo, messageString);
johan's avatar
johan committed
888
				messageString += 4;
Ghislain MARY's avatar
Ghislain MARY committed
889
				bzrtp_cryptoAlgoTypeIntToString(messageData->sasAlgo, messageString);
johan's avatar
johan committed
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
				messageString += 4;

				/* if it is a multistream or preshared commit insert the 16 bytes nonce */
				if ((messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) || (messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult)) {
						memcpy(messageString, messageData->nonce, 16);
						messageString += 16;

					/* and the keyID for preshared commit only */
					if (messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) {
						memcpy(messageString, messageData->keyID, 8);
						messageString +=8;
					}
				} else { /* it's a DH commit message, set the hvi */
					memcpy(messageString, messageData->hvi, 32);
					messageString +=32;
				}
			
				/* there is a MAC to compute, set the pointers to the key and MAC output buffer */
				MACbuffer = messageString;
johan's avatar
johan committed
909
				MACkey = zrtpChannelContext->selfH[1]; /* HMAC of Hello packet is keyed by H1 which have been set at context initialising */
johan's avatar
johan committed
910 911 912 913 914
			}
			break; /*MSGTYPE_COMMIT */

		case MSGTYPE_DHPART1 :
		case MSGTYPE_DHPART2 :
915
			{
916 917 918
				bzrtpDHPartMessage_t *messageData;
				uint16_t pvLength;

johan's avatar
johan committed
919 920 921 922 923
				/* get the DHPart message structure */
				if (zrtpPacket->messageData == NULL) {
					return BZRTP_BUILDER_ERROR_INVALIDMESSAGE;
				}

924
				messageData = (bzrtpDHPartMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
925 926

				/* compute message length */
927
				pvLength = computeKeyAgreementPrivateValueLength(zrtpChannelContext->keyAgreementAlgo);
johan's avatar
johan committed
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
				if (pvLength==0) {
					return BZRTP_BUILDER_ERROR_INVALIDCONTEXT;
				}
				zrtpPacket->messageLength = ZRTP_DHPARTMESSAGE_FIXED_LENGTH + pvLength;
				
				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+zrtpPacket->messageLength+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
				/* have the messageString pointer to the begining of message(after the message header wich is computed for all messages after the switch)
				 * within the packetString buffer*/
				messageString = zrtpPacket->packetString + ZRTP_PACKET_HEADER_LENGTH + ZRTP_MESSAGE_HEADER_LENGTH;

				/* now insert the different message parts into the packetString */
				memcpy(messageString, messageData->H1, 32);
				messageString += 32;
				memcpy(messageString, messageData->rs1ID, 8);
				messageString += 8;
				memcpy(messageString, messageData->rs2ID, 8);
				messageString += 8;
				memcpy(messageString, messageData->auxsecretID, 8);
				messageString += 8;
				memcpy(messageString, messageData->pbxsecretID, 8);
				messageString += 8;
				memcpy(messageString, messageData->pv, pvLength);
				messageString += pvLength;

				/* there is a MAC to compute, set the pointers to the key and MAC output buffer */
				MACbuffer = messageString;
johan's avatar
johan committed
955
				MACkey = zrtpChannelContext->selfH[0]; /* HMAC of Hello packet is keyed by H0 which have been set at context initialising */
956
			}
johan's avatar
johan committed
957 958 959 960 961 962 963
			break; /* MSGTYPE_DHPART1 and 2 */
		
		case MSGTYPE_CONFIRM1:
		case MSGTYPE_CONFIRM2:
			{
				uint8_t *confirmMessageKey = NULL;
				uint8_t *confirmMessageMacKey = NULL;
964 965 966 967 968
				bzrtpConfirmMessage_t *messageData;
				uint16_t encryptedPartLength;
				uint8_t *plainMessageString;
				uint16_t plainMessageStringIndex = 0;

johan's avatar
johan committed
969
				/* we will have to encrypt and validate the message, check we have the keys to do it */
johan's avatar
johan committed
970
				if (zrtpChannelContext->role == BZRTP_ROLE_INITIATOR) {
johan's avatar
johan committed
971
					if ((zrtpChannelContext->zrtpkeyi == NULL) || (zrtpChannelContext->mackeyi == NULL)) {
johan's avatar
johan committed
972 973
						return BZRTP_BUILDER_ERROR_INVALIDCONTEXT;
					}
johan's avatar
johan committed
974 975
					confirmMessageKey = zrtpChannelContext->zrtpkeyi;
					confirmMessageMacKey = zrtpChannelContext->mackeyi;
johan's avatar
johan committed
976 977
				}

johan's avatar
johan committed
978
				if (zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) {
johan's avatar
johan committed
979
					if ((zrtpChannelContext->zrtpkeyr == NULL) || (zrtpChannelContext->mackeyr == NULL)) {
johan's avatar
johan committed
980 981
						return BZRTP_BUILDER_ERROR_INVALIDCONTEXT;
					}
johan's avatar
johan committed
982 983
					confirmMessageKey = zrtpChannelContext->zrtpkeyr;
					confirmMessageMacKey = zrtpChannelContext->mackeyr;
johan's avatar
johan committed
984 985 986 987 988 989 990
				}
				
				/* get the Confirm message structure */
				if (zrtpPacket->messageData == NULL) {
					return BZRTP_BUILDER_ERROR_INVALIDMESSAGE;
				}

991
				messageData = (bzrtpConfirmMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
992 993 994 995 996 997 998 999 1000 1001 1002

				/* compute message length */
				zrtpPacket->messageLength = ZRTP_CONFIRMMESSAGE_FIXED_LENGTH + messageData->sig_len*4; /* sig_len is in word of 4 bytes */
				
				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+zrtpPacket->messageLength+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
				/* have the messageString pointer to the begining of message(after the message header wich is computed for all messages after the switch)
				 * within the packetString buffer*/
				messageString = zrtpPacket->packetString + ZRTP_PACKET_HEADER_LENGTH + ZRTP_MESSAGE_HEADER_LENGTH;

				/* allocate a temporary buffer to store the plain text */
1003 1004
				encryptedPartLength = zrtpPacket->messageLength - ZRTP_MESSAGE_HEADER_LENGTH - 24; /* message header, confirm_mac(8 bytes) and CFB IV(16 bytes) are not encrypted */
				plainMessageString = (uint8_t *)malloc(encryptedPartLength*sizeof(uint8_t)); 
johan's avatar
johan committed
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026

				/* fill the plain message buffer with data from the message structure */
				memcpy(plainMessageString, messageData->H0, 32);
				plainMessageStringIndex += 32;
				plainMessageString[plainMessageStringIndex++] = 0x00;
				plainMessageString[plainMessageStringIndex++] = (uint8_t)(((messageData->sig_len)>>8)&0x0001);
				plainMessageString[plainMessageStringIndex++] = (uint8_t)((messageData->sig_len)&0x00FF);
				plainMessageString[plainMessageStringIndex++] = (uint8_t)((messageData->E&0x01)<<3) | (uint8_t)((messageData->V&0x01)<<2) | (uint8_t)((messageData->A&0x01)<<1) | (uint8_t)(messageData->D&0x01) ;
				/* cache expiration in a 32 bits unsigned int */
				plainMessageString[plainMessageStringIndex++] = (uint8_t)((messageData->cacheExpirationInterval>>24)&0xFF);
				plainMessageString[plainMessageStringIndex++] = (uint8_t)((messageData->cacheExpirationInterval>>16)&0xFF);
				plainMessageString[plainMessageStringIndex++] = (uint8_t)((messageData->cacheExpirationInterval>>8)&0xFF);
				plainMessageString[plainMessageStringIndex++] = (uint8_t)((messageData->cacheExpirationInterval)&0xFF);

				if (messageData->sig_len>0) {
					memcpy(plainMessageString+plainMessageStringIndex, messageData->signatureBlockType, 4);
					plainMessageStringIndex += 4;
					/* sig_len is in 4 bytes words and include the 1 word of signature block type */
					memcpy(plainMessageString+plainMessageStringIndex, messageData->signatureBlock, (messageData->sig_len-1)*4);
				}

				/* encrypt the buffer, set the output directly in the messageString buffer at the correct position(+24 after message header) */
johan's avatar
johan committed
1027
				zrtpChannelContext->cipherEncryptionFunction(confirmMessageKey, messageData->CFBIV, plainMessageString, encryptedPartLength, messageString+24);
johan's avatar
johan committed
1028 1029 1030
				free(plainMessageString); /* free the plain message string temporary buffer */

				/* compute the mac over the encrypted part of the message and set the result in the messageString */
johan's avatar
johan committed
1031
				zrtpChannelContext->hmacFunction(confirmMessageMacKey, zrtpChannelContext->hashLength, messageString+24, encryptedPartLength, 8, messageString);
johan's avatar
johan committed
1032 1033 1034 1035 1036
				messageString += 8;
				/* add the CFB IV */
				memcpy(messageString, messageData->CFBIV, 16);
			}
			break; /* MSGTYPE_CONFIRM1 and MSGTYPE_CONFIRM2 */
1037

johan's avatar
johan committed
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
		case MSGTYPE_CONF2ACK:
			{
				/* the message length is fixed */
				zrtpPacket->messageLength = ZRTP_CONF2ACKMESSAGE_FIXED_LENGTH;

				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+ZRTP_CONF2ACKMESSAGE_FIXED_LENGTH+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
			}
			break; /* MSGTYPE_CONF2ACK */

1048 1049
		case MSGTYPE_PINGACK:
			{
1050 1051
				bzrtpPingAckMessage_t *messageData;

1052 1053 1054 1055 1056 1057 1058 1059
				/* the message length is fixed */
				zrtpPacket->messageLength = ZRTP_PINGACKMESSAGE_FIXED_LENGTH;

				/* allocate the packetString buffer : packet is header+message+crc */
				zrtpPacket->packetString = (uint8_t *)malloc((ZRTP_PACKET_HEADER_LENGTH+ZRTP_PINGACKMESSAGE_FIXED_LENGTH+ZRTP_PACKET_CRC_LENGTH)*sizeof(uint8_t));
				messageString = zrtpPacket->packetString + ZRTP_PACKET_HEADER_LENGTH + ZRTP_MESSAGE_HEADER_LENGTH;

				/* now insert the different message parts into the packetString */
1060
				messageData = (bzrtpPingAckMessage_t *)zrtpPacket->messageData;
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074

				memcpy(messageString, messageData->version, 4);
				messageString += 4;
				memcpy(messageString, messageData->endpointHash, 8);
				messageString += 8;
				memcpy(messageString, messageData->endpointHashReceived, 8);
				messageString += 8;
				*messageString++ = (uint8_t)((messageData->SSRC>>24)&0xFF);
				*messageString++ = (uint8_t)((messageData->SSRC>>16)&0xFF);
				*messageString++ = (uint8_t)((messageData->SSRC>>8)&0xFF);
				*messageString++ = (uint8_t)(messageData->SSRC&0xFF);
			}
			break; /* MSGTYPE_PINGACK */

johan's avatar
johan committed
1075 1076 1077
	}

	/* write headers only if we have a packet string */
1078 1079 1080 1081
	if (zrtpPacket->packetString != NULL) {
		uint32_t CRC;
		uint8_t *CRCbuffer;

johan's avatar
johan committed
1082 1083 1084 1085 1086 1087
		zrtpMessageSetHeader(zrtpPacket->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpPacket->messageLength, messageTypeString);

		/* Do we have a MAC to compute on the message ? */
		if (MACbuffer != NULL) {
			/* compute the MAC(64 bits only) using the implicit HMAC function for ZRTP v1.10: HMAC-SHA256 */
			/* HMAC is computed on the whole message except the MAC itself so a length of zrtpPacket->messageLength-8 */
jehan's avatar
jehan committed
1088
			bctbx_hmacSha256(MACkey, 32, zrtpPacket->packetString+ZRTP_PACKET_HEADER_LENGTH, zrtpPacket->messageLength-8, 8, MACbuffer);
johan's avatar
johan committed
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
		}
	
		/* set packet header and CRC */
		/* preambule */
		zrtpPacket->packetString[0] = 0x10;
		zrtpPacket->packetString[1] = 0x00;
		/* Sequence number */
		zrtpPacket->packetString[2] = (uint8_t)((sequenceNumber>>8)&0x00FF);
		zrtpPacket->packetString[3] = (uint8_t)(sequenceNumber&0x00FF);
		/* ZRTP magic cookie */
		zrtpPacket->packetString[4] = (uint8_t)((ZRTP_MAGIC_COOKIE>>24)&0xFF);
		zrtpPacket->packetString[5] = (uint8_t)((ZRTP_MAGIC_COOKIE>>16)&0xFF);
		zrtpPacket->packetString[6] = (uint8_t)((ZRTP_MAGIC_COOKIE>>8)&0xFF);
		zrtpPacket->packetString[7] = (uint8_t)(ZRTP_MAGIC_COOKIE&0xFF);
		/* Source Identifier */
		zrtpPacket->packetString[8] = (uint8_t)(((zrtpPacket->sourceIdentifier)>>24)&0xFF);
		zrtpPacket->packetString[9] = (uint8_t)(((zrtpPacket->sourceIdentifier)>>16)&0xFF);
		zrtpPacket->packetString[10] = (uint8_t)(((zrtpPacket->sourceIdentifier)>>8)&0xFF);
		zrtpPacket->packetString[11] = (uint8_t)((zrtpPacket->sourceIdentifier)&0xFF);
		/* CRC */
1109 1110
		CRC = bzrtp_CRC32(zrtpPacket->packetString, zrtpPacket->messageLength+ZRTP_PACKET_HEADER_LENGTH);
		CRCbuffer = (zrtpPacket->packetString)+(zrtpPacket->messageLength)+ZRTP_PACKET_HEADER_LENGTH;
johan's avatar
johan committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
		*CRCbuffer = (uint8_t)((CRC>>24)&0xFF);
		CRCbuffer++;
		*CRCbuffer = (uint8_t)((CRC>>16)&0xFF);
		CRCbuffer++;
		*CRCbuffer = (uint8_t)((CRC>>8)&0xFF);
		CRCbuffer++;
		*CRCbuffer = (uint8_t)(CRC&0xFF);
	
		return 0;
	} else { /* no packetString allocated something wen't wrong but we shall never arrive here */
		return BZRTP_BUILDER_ERROR_UNKNOWN;
	}
}

/* create a zrtpPacket and initialise it's structures */
johan's avatar
johan committed
1126
bzrtpPacket_t *bzrtp_createZrtpPacket(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpChannelContext, uint32_t messageType, int *exitCode) {
johan's avatar
johan committed
1127 1128
	/* allocate packet */
	bzrtpPacket_t *zrtpPacket = (bzrtpPacket_t *)malloc(sizeof(bzrtpPacket_t));
1129 1130 1131
	memset(zrtpPacket, 0, sizeof(bzrtpPacket_t));
	zrtpPacket->messageData = NULL;
	zrtpPacket->packetString = NULL;
johan's avatar
johan committed
1132 1133 1134 1135 1136

	/* initialise it */
	switch(messageType) {
		case MSGTYPE_HELLO:
			{
1137
				int i;
johan's avatar
johan committed
1138 1139 1140 1141
				bzrtpHelloMessage_t *zrtpHelloMessage = (bzrtpHelloMessage_t *)malloc(sizeof(bzrtpHelloMessage_t));
				memset(zrtpHelloMessage, 0, sizeof(bzrtpHelloMessage_t));
				/* initialise some fields using zrtp context data */
				memcpy(zrtpHelloMessage->version, ZRTP_VERSION, 4);
1142
				strncpy((char*)zrtpHelloMessage->clientIdentifier, ZRTP_CLIENT_IDENTIFIER, 16);
johan's avatar
johan committed
1143
				zrtpHelloMessage->clientIdentifier[16]='\0'; /* be sure the clientIdentifier filed is a NULL terminated string */
johan's avatar
johan committed
1144
				memcpy(zrtpHelloMessage->H3, zrtpChannelContext->selfH[3], 32);
johan's avatar
johan committed
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
				memcpy(zrtpHelloMessage->ZID, zrtpContext->selfZID, 12);
				/* set all S,M,P flags to zero as we're not able to verify signatures, we're not a PBX(TODO: implement?), we're not passive */
				zrtpHelloMessage->S = 0;
				zrtpHelloMessage->M = 0;
				zrtpHelloMessage->P = 0;

				/* get the algorithm availabilities from the context */
				zrtpHelloMessage->hc = zrtpContext->hc;
				zrtpHelloMessage->cc = zrtpContext->cc;
				zrtpHelloMessage->ac = zrtpContext->ac;
				zrtpHelloMessage->kc = zrtpContext->kc;
				zrtpHelloMessage->sc = zrtpContext->sc;
1157

johan's avatar
johan committed
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
				for (i=0; i<zrtpContext->hc; i++) {
					zrtpHelloMessage->supportedHash[i] = zrtpContext->supportedHash[i];
				}
				for (i=0; i<zrtpContext->cc; i++) {
					zrtpHelloMessage->supportedCipher[i] = zrtpContext->supportedCipher[i];
				}
				for (i=0; i<zrtpContext->ac; i++) {
					zrtpHelloMessage->supportedAuthTag[i] = zrtpContext->supportedAuthTag[i];
				}
				for (i=0; i<zrtpContext->kc; i++) {
					zrtpHelloMessage->supportedKeyAgreement[i] = zrtpContext->supportedKeyAgreement[i];
				}
				for (i=0; i<zrtpContext->sc; i++) {
					zrtpHelloMessage->supportedSas[i] = zrtpContext->supportedSas[i];
				}

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpHelloMessage;
			}
			break; /* MSGTYPE_HELLO */

		case MSGTYPE_HELLOACK :
			{
				/* nothing to do for the Hello ACK packet as it just contains it's type */
			}
			break; /* MSGTYPE_HELLOACK */
		/* In case of DH commit, this one must be called after the DHPart build and the self DH message and peer Hello message are stored in the context */
		case MSGTYPE_COMMIT :
			{
				bzrtpCommitMessage_t *zrtpCommitMessage = (bzrtpCommitMessage_t *)malloc(sizeof(bzrtpCommitMessage_t));
				memset(zrtpCommitMessage, 0, sizeof(bzrtpCommitMessage_t));
				
				/* initialise some fields using zrtp context data */
johan's avatar
johan committed
1191
				memcpy(zrtpCommitMessage->H2, zrtpChannelContext->selfH[2], 32);
johan's avatar
johan committed
1192
				memcpy(zrtpCommitMessage->ZID, zrtpContext->selfZID, 12);
johan's avatar
johan committed
1193 1194 1195 1196 1197
				zrtpCommitMessage->hashAlgo = zrtpChannelContext->hashAlgo;
				zrtpCommitMessage->cipherAlgo = zrtpChannelContext->cipherAlgo;
				zrtpCommitMessage->authTagAlgo = zrtpChannelContext->authTagAlgo;
				zrtpCommitMessage->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo;
				zrtpCommitMessage->sasAlgo = zrtpChannelContext->sasAlgo;
johan's avatar
johan committed
1198 1199 1200

				/* if it is a multistream or preshared commit create a 16 random bytes nonce */
				if ((zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) || (zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult)) {
jehan's avatar
jehan committed
1201
					bctbx_rng_get(zrtpContext->RNGContext, zrtpCommitMessage->nonce, 16);
johan's avatar
johan committed
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212

					/* and the keyID for preshared commit only */
					if (zrtpCommitMessage->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) {
						/* TODO at this point we must first compute the preShared key - make sure at least rs1 is present */
						/* preshared_key = hash(len(rs1) || rs1 || len(auxsecret) || auxsecret ||
                       len(pbxsecret) || pbxsecret) using the agreed hash and store it into the env */
						/* and then the keyID : MAC(preshared_key, "Prsh") truncated to 64 bits using the agreed MAC */
					}
				} else { /* it's a DH commit message, set the hvi */
					/* hvi = hash(initiator's DHPart2 message || responder's Hello message) using the agreed hash function truncated to 256 bits */
					/* create a string with the messages concatenated */
johan's avatar
johan committed
1213 1214
					uint16_t DHPartMessageLength = zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID]->messageLength;
					uint16_t HelloMessageLength = zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->messageLength;
johan's avatar
johan committed
1215 1216 1217 1218
					uint16_t DHPartHelloMessageStringLength = DHPartMessageLength + HelloMessageLength;

					uint8_t *DHPartHelloMessageString = (uint8_t *)malloc(DHPartHelloMessageStringLength*sizeof(uint8_t));
					
johan's avatar
johan committed
1219 1220
					memcpy(DHPartHelloMessageString, zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, DHPartMessageLength);
					memcpy(DHPartHelloMessageString+DHPartMessageLength, zrtpChannelContext->peerPackets[HELLO_MESSAGE_STORE_ID]->packetString+ZRTP_PACKET_HEADER_LENGTH, HelloMessageLength);
johan's avatar
johan committed
1221

johan's avatar
johan committed
1222
					zrtpChannelContext->hashFunction(DHPartHelloMessageString, DHPartHelloMessageStringLength, 32, zrtpCommitMessage->hvi);
johan's avatar
johan committed
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235

					free(DHPartHelloMessageString);
				}

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpCommitMessage;
			}
			break; /* MSGTYPE_COMMIT */

		/* this one is called after the exchange of Hello messages when the crypto algo agreement have been performed */
		case MSGTYPE_DHPART1 :
		case MSGTYPE_DHPART2 :
			{
1236
				uint8_t secretLength; /* is in bytes */
jehan's avatar
jehan committed
1237
				uint8_t bctbx_keyAgreementAlgo = BCTBX_DHM_UNSET;
johan's avatar
johan committed
1238 1239 1240
				bzrtpDHPartMessage_t *zrtpDHPartMessage = (bzrtpDHPartMessage_t *)malloc(sizeof(bzrtpDHPartMessage_t));
				memset(zrtpDHPartMessage, 0, sizeof(bzrtpDHPartMessage_t));
				/* initialise some fields using zrtp context data */
johan's avatar
johan committed
1241
				memcpy(zrtpDHPartMessage->H1, zrtpChannelContext->selfH[1], 32);
johan's avatar
johan committed
1242 1243 1244 1245
				/* get the retained secret from context, we anyway create a DHPart2 packet that we may turn into a DHPart1 packet if we end to 
				 * 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);
1246
				memcpy(zrtpDHPartMessage->auxsecretID, zrtpChannelContext->initiatorAuxsecretID, 8);
johan's avatar
johan committed
1247 1248 1249 1250
				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 */
				/* initialise the dhm context, secret length shall be twice the size of cipher block key length - rfc section 5.1.5 */
johan's avatar
johan committed
1251
				switch (zrtpChannelContext->cipherAlgo) {
johan's avatar
johan committed
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
					case ZRTP_CIPHER_AES3:
					case ZRTP_CIPHER_2FS3:
						secretLength = 64;
						break;
					case ZRTP_CIPHER_AES2:
					case ZRTP_CIPHER_2FS2:
						secretLength = 48;
						break;
					case ZRTP_CIPHER_AES1:
					case ZRTP_CIPHER_2FS1:
					default:
						secretLength = 32;
						break;
				}
1266 1267 1268 1269

				switch (zrtpChannelContext->keyAgreementAlgo) {
					case ZRTP_KEYAGREEMENT_DH2k:
					case ZRTP_KEYAGREEMENT_DH3k:
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
						{
							bctbx_DHMContext_t *DHMContext = NULL;
							if (zrtpChannelContext->keyAgreementAlgo==ZRTP_KEYAGREEMENT_DH2k) {
								bctbx_keyAgreementAlgo = BCTBX_DHM_2048;
							} else {
								bctbx_keyAgreementAlgo = BCTBX_DHM_3072;
							}
							/* create DHM context */
							DHMContext = (void *)bctbx_CreateDHMContext(bctbx_keyAgreementAlgo, secretLength);
							if (DHMContext == NULL) {
								free(zrtpPacket);
								free(zrtpDHPartMessage);
								*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
								return NULL;
							}

							/* create private key and compute the public value */
							bctbx_DHMCreatePublic(DHMContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, zrtpContext->RNGContext);
							zrtpDHPartMessage->pv = (uint8_t *)malloc((zrtpChannelContext->keyAgreementLength)*sizeof(uint8_t));
							memcpy(zrtpDHPartMessage->pv, DHMContext->self, zrtpChannelContext->keyAgreementLength);
							zrtpContext->keyAgreementContext = (void *)DHMContext; /* save DHM context in zrtp Context */
							zrtpContext->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo; /* store algo in global context to be able to destroy it correctly*/
						}
1293
						break;
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321

					case ZRTP_KEYAGREEMENT_X255:
					case ZRTP_KEYAGREEMENT_X448:
						{
							bctbx_ECDHContext_t *ECDHContext = NULL;
							if (zrtpChannelContext->keyAgreementAlgo==ZRTP_KEYAGREEMENT_X255) {
								bctbx_keyAgreementAlgo = BCTBX_ECDH_X25519;
							} else {
							bctbx_keyAgreementAlgo = BCTBX_ECDH_X448;
							}

							/* Create the ECDH context */
							ECDHContext = (void *)bctbx_CreateECDHContext(bctbx_keyAgreementAlgo);
							if (ECDHContext == NULL) {
								free(zrtpPacket);
								free(zrtpDHPartMessage);
								*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
								return NULL;
							}
							/* create private key and compute the public value */
							bctbx_ECDHCreateKeyPair(ECDHContext, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, zrtpContext->RNGContext);
							zrtpDHPartMessage->pv = (uint8_t *)malloc((zrtpChannelContext->keyAgreementLength)*sizeof(uint8_t));
							memcpy(zrtpDHPartMessage->pv, ECDHContext->selfPublic, zrtpChannelContext->keyAgreementLength);
							zrtpContext->keyAgreementContext = (void *)ECDHContext; /* save ECDH context in zrtp Context */
							zrtpContext->keyAgreementAlgo = zrtpChannelContext->keyAgreementAlgo; /* store algo in global context to be able to destroy it correctly*/
						}
						break;

1322 1323 1324 1325 1326 1327 1328
					default:
						free(zrtpPacket);
						free(zrtpDHPartMessage);
						*exitCode = BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT;
						return NULL;
						break;
				}
1329
								/* attach the message data to the packet */
johan's avatar
johan committed
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
				zrtpPacket->messageData = zrtpDHPartMessage;
			}
			break; /* MSGTYPE_DHPART1 and MSGTYPE_DHPART2 */

		case MSGTYPE_CONFIRM1:
		case MSGTYPE_CONFIRM2:
			{
				bzrtpConfirmMessage_t *zrtpConfirmMessage = (bzrtpConfirmMessage_t *)malloc(sizeof(bzrtpConfirmMessage_t));
				memset(zrtpConfirmMessage, 0, sizeof(bzrtpConfirmMessage_t));
				/* initialise some fields using zrtp context data */
johan's avatar
johan committed
1340
				memcpy(zrtpConfirmMessage->H0, zrtpChannelContext->selfH[0], 32);
johan's avatar
johan committed
1341 1342 1343
				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->E = 0; /* we are not a PBX and then will never signal an enrollment - rfc section 7.3.1 */
johan's avatar
johan committed
1344
				zrtpConfirmMessage->V = zrtpContext->cachedSecret.previouslyVerifiedSas;
johan's avatar
johan committed
1345 1346 1347 1348
				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 */

				/* generate a random CFB IV */
jehan's avatar
jehan committed
1349
				bctbx_rng_get(zrtpContext->RNGContext, zrtpConfirmMessage->CFBIV, 16);
johan's avatar
johan committed
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpConfirmMessage;
			}
			break; /* MSGTYPE_CONFIRM1 and MSGTYPE_CONFIRM2 */

		case MSGTYPE_CONF2ACK :
			{
				/* nothing to do for the conf2ACK packet as it just contains it's type */
			}
			break; /* MSGTYPE_CONF2ACK */
1361 1362
		case MSGTYPE_PINGACK:
			{
1363 1364 1365
				bzrtpPingMessage_t *pingMessage;
				bzrtpPingAckMessage_t *zrtpPingAckMessage;

1366 1367 1368 1369 1370 1371
				/* to create a pingACK we must have a ping packet in the channel context, check it */
				bzrtpPacket_t *pingPacket = zrtpChannelContext->pingPacket;
				if (pingPacket == NULL) {
					*exitCode = BZRTP_CREATE_ERROR_INVALIDCONTEXT;
					return NULL;
				}
1372
				pingMessage = (bzrtpPingMessage_t *)pingPacket->messageData;
1373 1374

				/* create the message */
1375
				zrtpPingAckMessage = (bzrtpPingAckMessage_t *)malloc(sizeof(bzrtpPingAckMessage_t));
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
				memset(zrtpPingAckMessage, 0, sizeof(bzrtpPingAckMessage_t));

				/* initialise all fields using zrtp context data and the received ping message */
				memcpy(zrtpPingAckMessage->version,ZRTP_VERSION , 4); /* we support version 1.10 only, so no need to even check what was sent in the ping */
				memcpy(zrtpPingAckMessage->endpointHash, zrtpContext->selfZID, 8); /* as suggested in rfc section 5.16, use the truncated ZID as endPoint hash */
				memcpy(zrtpPingAckMessage->endpointHashReceived, pingMessage->endpointHash, 8);
				zrtpPingAckMessage->SSRC = pingPacket->sourceIdentifier;

				/* attach the message data to the packet */
				zrtpPacket->messageData = zrtpPingAckMessage;
			} /* MSGTYPE_PINGACK */
			break;
johan's avatar
johan committed
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398

		default:
			free(zrtpPacket);
			*exitCode = BZRTP_CREATE_ERROR_INVALIDMESSAGETYPE;
			return NULL;
			break;
	}

	zrtpPacket->sequenceNumber = 0; /* this field is not used buy the packet creator, sequence number is given as a parameter when converting
	the message to a packet string(packet build). Used only when parsing a string into a packet struct */
	zrtpPacket->messageType = messageType;
johan's avatar
johan committed
1399
	zrtpPacket->sourceIdentifier = zrtpChannelContext->selfSSRC;
johan's avatar
johan committed
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
	zrtpPacket->messageLength = 0; /* length will be computed at packet build */
	zrtpPacket->packetString = NULL;

	*exitCode=0;
	return zrtpPacket;
}

void bzrtp_freeZrtpPacket(bzrtpPacket_t *zrtpPacket) {
	if (zrtpPacket != NULL) {
		/* some messages have fields to be freed */
		if (zrtpPacket->messageData != NULL) {
			switch(zrtpPacket->messageType) {
				case MSGTYPE_DHPART1 :
				case MSGTYPE_DHPART2 :
					{
						bzrtpDHPartMessage_t *typedMessageData = (bzrtpDHPartMessage_t *)(zrtpPacket->messageData);
						if (typedMessageData != NULL) {
							free(typedMessageData->pv);
						}
					}
					break;
				case MSGTYPE_CONFIRM1:
				case MSGTYPE_CONFIRM2:
					{
						bzrtpConfirmMessage_t *typedMessageData = (bzrtpConfirmMessage_t *)(zrtpPacket->messageData);
						if (typedMessageData != NULL) {
							free(typedMessageData->signatureBlock);
						}
					}
					break;
			}
		}
		free(zrtpPacket->messageData);
		free(zrtpPacket->packetString);
		free(zrtpPacket);
	}
}

/**
 * @brief Modify the current sequence number of the packet in the packetString and sequenceNumber fields
 * The CRC at the end of packetString is also updated
 * 
 * param[in/out]	zrtpPacket		The zrtpPacket to modify, the packetString must have been generated by
 * 									a call to bzrtp_packetBuild on this packet
 * param[in]		sequenceNumber	The new sequence number to insert in the packetString
 * 
 * return		0 on succes, error code otherwise
 */
int bzrtp_packetUpdateSequenceNumber(bzrtpPacket_t *zrtpPacket, uint16_t sequenceNumber) {
1449 1450 1451
	uint32_t CRC;
	uint8_t *CRCbuffer;

johan's avatar
johan committed
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
	if (zrtpPacket == NULL) {
		return BZRTP_BUILDER_ERROR_INVALIDPACKET;
	}

	if (zrtpPacket->packetString == NULL) {
		return BZRTP_BUILDER_ERROR_INVALIDPACKET;
	}
	/* update the sequence number field (even if it is probably useless as this function is called just before sending the DHPart2 packet only)*/
	zrtpPacket->sequenceNumber = sequenceNumber;

	/* update hte sequence number in the packetString */
	*(zrtpPacket->packetString+2)= (uint8_t)((sequenceNumber>>8)&0x00FF);
	*(zrtpPacket->packetString+3)= (uint8_t)(sequenceNumber&0x00FF);


	/* update the CRC */
1468 1469
	CRC = bzrtp_CRC32(zrtpPacket->packetString, zrtpPacket->messageLength+ZRTP_PACKET_HEADER_LENGTH);
	CRCbuffer = (zrtpPacket->packetString)+(zrtpPacket->messageLength)+ZRTP_PACKET_HEADER_LENGTH;
johan's avatar
johan committed
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
	*CRCbuffer = (uint8_t)((CRC>>24)&0xFF);
	CRCbuffer++;
	*CRCbuffer = (uint8_t)((CRC>>16)&0xFF);
	CRCbuffer++;
	*CRCbuffer = (uint8_t)((CRC>>8)&0xFF);
	CRCbuffer++;
	*CRCbuffer = (uint8_t)(CRC&0xFF);

	return 0;
}


/*** Local functions implementation ***/

uint8_t *messageTypeInttoString(uint32_t messageType) {

	switch(messageType) {
		case MSGTYPE_HELLO : 
			return (uint8_t *)"Hello   ";
			break;
		case MSGTYPE_HELLOACK : 
			return (uint8_t *)"HelloACK";
			break;
		case MSGTYPE_COMMIT : 
			return (uint8_t *)"Commit  ";
			break;
		case MSGTYPE_DHPART1 : 
			return (uint8_t *)"DHPart1 ";
			break;
		case MSGTYPE_DHPART2 : 
			return (uint8_t *)"DHPart2 ";
			break;
		case MSGTYPE_CONFIRM1 : 
			return (uint8_t *)"Confirm1";
			break;
		case MSGTYPE_CONFIRM2 : 
			return (uint8_t *)"Confirm2";
			break;
		case MSGTYPE_CONF2ACK : 
			return (uint8_t *)"Conf2ACK";
			break;
		case MSGTYPE_ERROR : 
			return (uint8_t *)"Error   ";
			break;
		case MSGTYPE_ERRORACK : 
			return (uint8_t *)"ErrorACK";
			break;
		case MSGTYPE_GOCLEAR : 
			return (uint8_t *)"GoClear ";
			break;
		case MSGTYPE_CLEARACK : 
			return (uint8_t *)"ClearACK";
			break;
		case MSGTYPE_SASRELAY : 
			return (uint8_t *)"SASrelay";
			break;
		case MSGTYPE_RELAYACK : 
			return (uint8_t *)"RelayACK";
			break;
		case MSGTYPE_PING : 
			return (uint8_t *)"Ping    ";
			break;
		case MSGTYPE_PINGACK : 
			return (uint8_t *)"PingACK ";
			break;
	}
	return NULL;
}

/*
 * @brief Map the 8 char string value message type to an int32_t
 *
 * @param[in] messageTypeString		an 8 bytes string matching a zrtp message type
 *
 * @return	a 32-bits unsigned integer mapping the message type
 */
int32_t messageTypeStringtoInt(uint8_t messageTypeString[8]) {
	if (memcmp(messageTypeString, "Hello   ", 8) == 0) {
		return MSGTYPE_HELLO;
	} else if (memcmp(messageTypeString, "HelloACK", 8) == 0) {
		return MSGTYPE_HELLOACK;
	} else if (memcmp(messageTypeString, "Commit  ", 8) == 0) {
		return MSGTYPE_COMMIT;
	} else if (memcmp(messageTypeString, "DHPart1 ", 8) == 0) {
		return MSGTYPE_DHPART1;
	} else if (memcmp(messageTypeString, "DHPart2 ", 8) == 0) {
		return MSGTYPE_DHPART2;
	} else if (memcmp(messageTypeString, "Confirm1", 8) == 0) {
		return MSGTYPE_CONFIRM1;
	} else if (memcmp(messageTypeString, "Confirm2", 8) == 0) {
		return MSGTYPE_CONFIRM2;
	} else if (memcmp(messageTypeString, "Conf2ACK", 8) == 0) {
		return MSGTYPE_CONF2ACK;
	} else if (memcmp(messageTypeString, "Error   ", 8) == 0) {
		return MSGTYPE_ERROR;
	} else if (memcmp(messageTypeString, "ErrorACK", 8) == 0) {
		return MSGTYPE_ERRORACK;
	} else if (memcmp(messageTypeString, "GoClear ", 8) == 0) {
		return MSGTYPE_GOCLEAR;
	} else if (memcmp(messageTypeString, "ClearACK", 8) == 0) {
		return MSGTYPE_CLEARACK;
	} else if (memcmp(messageTypeString, "SASrelay", 8) == 0) {
		return MSGTYPE_SASRELAY;
	} else if (memcmp(messageTypeString, "RelayACK", 8) == 0) {
		return MSGTYPE_RELAYACK;
	} else if (memcmp(messageTypeString, "Ping    ", 8) == 0) {
		return MSGTYPE_PING;
	} else if (memcmp(messageTypeString, "PingACK ", 8) == 0) {
		return MSGTYPE_PINGACK;
	} else {
		return MSGTYPE_INVALID;
	}
}

/*
 * @brief Write the message header(preambule, length, message type) into the given output buffer
 *
 * @param[out]	outputBuffer		Message starts at the begining of this buffer
 * @param[in]	messageLength		Message length in bytes! To be converted into 32bits words before being inserted in the message header
 * @param[in]	messageType			An 8 chars string for the message type (validity is not checked by this function)
 *
 */
void zrtpMessageSetHeader(uint8_t *outputBuffer, uint16_t messageLength, uint8_t messageType[8]) {
	/* insert the preambule */
	outputBuffer[0] = 0x50;
	outputBuffer[1] = 0x5a;

	/* then the length in 32 bits words (param is in bytes, so >> 2) */
	outputBuffer[2] = (uint8_t)((messageLength>>10)&0x00FF);
	outputBuffer[3] = (uint8_t)((messageLength>>2)&0x00FF);

	/* the message type */
	memcpy(outputBuffer+4, messageType, 8);
}

/*
 * Return the variable private value length in bytes according to given key agreement algorythm
 *
 * @param[in]	keyAgreementAlgo	The key agreement algo mapped to an integer as defined in cryptoWrapper.h
 *
 * @return		the private value length in bytes
 *
 */
uint16_t computeKeyAgreementPrivateValueLength(uint8_t keyAgreementAlgo) {

	uint16_t pvLength = 0;
	switch (keyAgreementAlgo) {
		case ZRTP_KEYAGREEMENT_DH3k	:
			pvLength = 384;
			break;
		case ZRTP_KEYAGREEMENT_DH2k :
			pvLength = 256;
			break;
1623 1624 1625 1626 1627 1628
		case ZRTP_KEYAGREEMENT_X255	:
			pvLength = 32;
			break;
		case ZRTP_KEYAGREEMENT_X448	:
			pvLength = 56;
			break;
johan's avatar
johan committed
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
		case ZRTP_KEYAGREEMENT_EC25	:
			pvLength = 64;
			break;
		case ZRTP_KEYAGREEMENT_EC38	:
			pvLength = 96;
			break;
		case ZRTP_KEYAGREEMENT_EC52 :
			pvLength = 132;
			break;
		default :
			pvLength = 0;
			break;
	}

	return pvLength;
}