CVE-2016-6271 (C, published 2017-01-18T22:59Z)
Description: value: The Bzrtp library (aka libbzrtp) 1.0.x before 1.0.4 allows man-in-the-middle attackers to conduct spoofing attacks by leveraging a missing HVI check on DHPart2 packet reception.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-254 \u2014 7PK - Security Features
Software security is not security software. Here we're concerned with topics like authentication, access control, confidentiality, cryptography, and privilege management.
Repository: https://github.com/BelledonneCommunications/bzrtp
Files changed:
include/packetParser.h
src/packetParser.c
test/bzrtpParserTest.c
test/bzrtpParserTest.h
test/bzrtpTest.c
Commit message: Add ZRTP Commit packet hvi check on DHPart2 packet reception


Vulnerable code:
				/* the parsed commit packet must be saved as it is used to generate the total_hash */
void test_parser(void) {
		/*printf("parsing Ret val is %x index is %d\n", retval, i);*/

Fixed code:
#define		BZRTP_PARSER_ERROR_UNMATCHINGHVI		0xa400

					/* 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;
						}
					}

				/* the parsed packet must be saved as it is used to generate the total_hash */

void test_parser_param(uint8_t hvi_trick) {
		if (hvi_trick==0) {
			CU_ASSERT_EQUAL_FATAL(retval,0);
		} else { /* when hvi trick is enable, the DH2 parsing shall fail and return BZRTP_PARSER_ERROR_UNMATCHINGHVI */
			if (zrtpPacket->messageType==MSGTYPE_DHPART2) {
				CU_ASSERT_EQUAL_FATAL(retval, BZRTP_PARSER_ERROR_UNMATCHINGHVI);
				/* We shall then anyway skip the end of the test */
				/* reset pointers to selfHello packet in order to avoid double free */
				context87654321->channelContext[0]->selfPackets[HELLO_MESSAGE_STORE_ID] = NULL;
				context12345678->channelContext[0]->selfPackets[HELLO_MESSAGE_STORE_ID] = NULL;

				bzrtp_destroyBzrtpContext(context87654321, 0x87654321);
				bzrtp_destroyBzrtpContext(context12345678, 0x12345678);

				return;

			} else {
				CU_ASSERT_EQUAL_FATAL(retval,0);
			}
		}
			bzrtp_message("parsing Ret val is %x index is %d\n", retval, i);
				context87654321->channelContext[0]->selfPackets[HELLO_MESSAGE_STORE_ID] = zrtpPacket;
				context12345678->channelContext[0]->selfPackets[HELLO_MESSAGE_STORE_ID] = zrtpPacket;

		/* modify the hvi stored in the peerPackets, this shall result in parsing failure on DH2 packet */
		if (hvi_trick == 1) {
			if (zrtpPacket->messageType==MSGTYPE_COMMIT) {
				if (patternZRTPMetaData[i][2]==0x87654321) {
					bzrtpCommitMessage_t *peerCommitMessageData;
					peerCommitMessageData = (bzrtpCommitMessage_t *)zrtpPacket->messageData;
					peerCommitMessageData->hvi[0]=0xFF;
				}
			}
		}

	/* reset pointers to selfHello packet in order to avoid double free */
	context87654321->channelContext[0]->selfPackets[HELLO_MESSAGE_STORE_ID] = NULL;
	context12345678->channelContext[0]->selfPackets[HELLO_MESSAGE_STORE_ID] = NULL;


void test_parser(void) {
	test_parser_param(0);
}

void test_parser_hvi(void) {
	test_parser_param(1);
}

void test_parser_hvi(void);
	CU_add_test(parserTestSuite, "Parse hvi check fail", test_parser_hvi);