testUtils.c 13.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
/**
 @file testUtils.c

 @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
20
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
johan's avatar
johan committed
21 22 23 24 25 26 27 28 29
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "testUtils.h"
#include "cryptoUtils.h"
johan's avatar
johan committed
30

Johan Pascal's avatar
Johan Pascal committed
31 32
#include "bzrtpTest.h"

johan's avatar
johan committed
33 34 35 36 37 38 39 40 41 42
#ifndef _WIN32
#if !defined(__QNXNTO__) && !(defined(__ANDROID__) && defined(__LP64__))
#include <ctype.h>
#include <string.h>
#endif
#else
#include <Windows.h>
#endif


johan's avatar
johan committed
43 44
int verbose = 0;

johan's avatar
johan committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
/* trace functions: bzrtp algo code to string */
const char *bzrtp_hash_toString(uint8_t hashAlgo) {
	switch(hashAlgo) {
		case(ZRTP_UNSET_ALGO): return "unset";
		case(ZRTP_HASH_S256): return "SHA-256";
		case(ZRTP_HASH_S384): return "SHA-384";
		case(ZRTP_HASH_N256): return "SHA3-256";
		case(ZRTP_HASH_N384): return "SHA3-384";
		default: return "Unknown Algo";
	}
}

const char *bzrtp_keyAgreement_toString(uint8_t keyAgreementAlgo) {
	switch(keyAgreementAlgo) {
		case(ZRTP_UNSET_ALGO): return "unset";
		case(ZRTP_KEYAGREEMENT_DH2k): return "DHM-2048";
		case(ZRTP_KEYAGREEMENT_EC25): return "ECDH-256";
		case(ZRTP_KEYAGREEMENT_DH3k): return "DHM-3072";
		case(ZRTP_KEYAGREEMENT_EC38): return "ECDH-384";
		case(ZRTP_KEYAGREEMENT_EC52): return "ECDH-521";
Johan Pascal's avatar
Johan Pascal committed
65 66
		case(ZRTP_KEYAGREEMENT_X255): return "X25519";
		case(ZRTP_KEYAGREEMENT_X448): return "X448";
johan's avatar
johan committed
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
		case(ZRTP_KEYAGREEMENT_Prsh): return "PreShared";
		case(ZRTP_KEYAGREEMENT_Mult): return "MultiStream";
		default: return "Unknown Algo";
	}
}

const char *bzrtp_cipher_toString(uint8_t cipherAlgo) {
	switch(cipherAlgo) {
		case(ZRTP_UNSET_ALGO): return "unset";
		case(ZRTP_CIPHER_AES1): return "AES-128";
		case(ZRTP_CIPHER_AES2): return "AES-192";
		case(ZRTP_CIPHER_AES3): return "AES-256";
		case(ZRTP_CIPHER_2FS1): return "TwoFish-128";
		case(ZRTP_CIPHER_2FS2): return "TwoFish-192";
		case(ZRTP_CIPHER_2FS3): return "TwoFish-256";
		default: return "Unknown Algo";
	}
}

const char *bzrtp_authtag_toString(uint8_t authtagAlgo) {
	switch(authtagAlgo) {
		case(ZRTP_UNSET_ALGO): return "unset";
		case(ZRTP_AUTHTAG_HS32): return "HMAC-SHA1-32";
		case(ZRTP_AUTHTAG_HS80): return "HMAC-SHA1-80";
		case(ZRTP_AUTHTAG_SK32): return "Skein-32";
		case(ZRTP_AUTHTAG_SK64): return "Skein-64";
		default: return "Unknown Algo";
	}
}

const char *bzrtp_sas_toString(uint8_t sasAlgo) {
	switch(sasAlgo) {
		case(ZRTP_UNSET_ALGO): return "unset";
		case(ZRTP_SAS_B32): return "Base32";
		case(ZRTP_SAS_B256): return "PGP-WordList";
		default: return "Unknown Algo";
		}
}

johan's avatar
johan committed
106
void printHex(char *title, uint8_t *data, uint32_t length) {
johan's avatar
johan committed
107
	if (verbose) {
108
		uint32_t i;
johan's avatar
johan committed
109 110 111 112 113
		printf ("%s : ", title);
		for (i=0; i<length; i++) {
			printf ("0x%02x, ", data[i]);
		}
		printf ("\n");
114
		fflush(NULL);
johan's avatar
johan committed
115 116 117 118
	}
}

void packetDump(bzrtpPacket_t *zrtpPacket, uint8_t addRawMessage) {
johan's avatar
johan committed
119
	if (verbose) {
johan's avatar
johan committed
120 121 122 123 124 125 126 127 128 129
		int j;
		printf ("SSRC %x - Message Length: %d - ", zrtpPacket->sourceIdentifier, zrtpPacket->messageLength);
		if (zrtpPacket->packetString!=NULL) { /* paquet has been built and we need to get his sequence number in the packetString */
			printf ("Sequence number: %02x%02x", *(zrtpPacket->packetString+2), *(zrtpPacket->packetString+3));
		} else { /* packet has been parsed, so get his sequence number in the structure */
			printf ("Sequence number: %04x", zrtpPacket->sequenceNumber);
		}
		switch (zrtpPacket->messageType) {
			case MSGTYPE_HELLO :
				{
130 131 132
					bzrtpHelloMessage_t *messageData;
					uint8_t algoTypeString[4];

johan's avatar
johan committed
133
					printf(" - Message Type : Hello\n");
134
					messageData = (bzrtpHelloMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
135 136 137 138 139 140
					printf ("Version %.4s\nIdentifier %.16s\n", messageData->version, messageData->clientIdentifier);
					printHex ("H3", messageData->H3, 32);
					printHex ("ZID", messageData->ZID, 12);
					printf ("S : %d - M : %d - P : %d\nhc : %x - cc : %x - ac : %x - kc : %x - sc : %x\n", messageData->S, messageData->M, messageData->P, messageData->hc, messageData->cc, messageData->ac, messageData->kc, messageData->sc);
					printf ("hc ");
					for (j=0; j<messageData->hc; j++) {
Ghislain MARY's avatar
Ghislain MARY committed
141
						bzrtp_cryptoAlgoTypeIntToString(messageData->supportedHash[j], algoTypeString);
johan's avatar
johan committed
142 143 144 145
						printf("%.4s, ", algoTypeString);
					}
					printf ("\ncc ");
					for (j=0; j<messageData->cc; j++) {
Ghislain MARY's avatar
Ghislain MARY committed
146
						bzrtp_cryptoAlgoTypeIntToString(messageData->supportedCipher[j], algoTypeString);
johan's avatar
johan committed
147 148 149 150
						printf("%.4s, ", algoTypeString);
					}
					printf ("\nac ");
					for (j=0; j<messageData->ac; j++) {
Ghislain MARY's avatar
Ghislain MARY committed
151
						bzrtp_cryptoAlgoTypeIntToString(messageData->supportedAuthTag[j], algoTypeString);
johan's avatar
johan committed
152 153 154 155
						printf("%.4s, ", algoTypeString);
					}
					printf ("\nkc ");
					for (j=0; j<messageData->kc; j++) {
Ghislain MARY's avatar
Ghislain MARY committed
156
						bzrtp_cryptoAlgoTypeIntToString(messageData->supportedKeyAgreement[j], algoTypeString);
johan's avatar
johan committed
157 158 159 160
						printf("%.4s, ", algoTypeString);
					}
					printf ("\nsc ");
					for (j=0; j<messageData->sc; j++) {
Ghislain MARY's avatar
Ghislain MARY committed
161
						bzrtp_cryptoAlgoTypeIntToString(messageData->supportedSas[j], algoTypeString);
johan's avatar
johan committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
						printf("%.4s, ", algoTypeString);
					}
					printHex("\nMAC", messageData->MAC, 8);
				}

				break; /* MSGTYPE_HELLO */

			case MSGTYPE_HELLOACK :
				{
					printf(" - Message Type : Hello ACK\n");
				}
				break;

			case MSGTYPE_COMMIT:
				{
					uint8_t algoTypeString[4];
178 179
					bzrtpCommitMessage_t *messageData;

johan's avatar
johan committed
180
					printf(" - Message Type : Commit\n");
181
					messageData = (bzrtpCommitMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
182 183
					printHex("H2", messageData->H2, 32);
					printHex("ZID", messageData->ZID, 12);
Ghislain MARY's avatar
Ghislain MARY committed
184
					bzrtp_cryptoAlgoTypeIntToString(messageData->hashAlgo, algoTypeString);
johan's avatar
johan committed
185
					printf("Hash Algo: %.4s\n", algoTypeString);
Ghislain MARY's avatar
Ghislain MARY committed
186
					bzrtp_cryptoAlgoTypeIntToString(messageData->cipherAlgo, algoTypeString);
johan's avatar
johan committed
187
					printf("Cipher Algo: %.4s\n", algoTypeString);
Ghislain MARY's avatar
Ghislain MARY committed
188
					bzrtp_cryptoAlgoTypeIntToString(messageData->authTagAlgo, algoTypeString);
johan's avatar
johan committed
189
					printf("Auth tag Algo: %.4s\n", algoTypeString);
Ghislain MARY's avatar
Ghislain MARY committed
190
					bzrtp_cryptoAlgoTypeIntToString(messageData->keyAgreementAlgo, algoTypeString);
johan's avatar
johan committed
191
					printf("Key agreement Algo: %.4s\n", algoTypeString);
Ghislain MARY's avatar
Ghislain MARY committed
192
					bzrtp_cryptoAlgoTypeIntToString(messageData->sasAlgo, algoTypeString);
johan's avatar
johan committed
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
					printf("Sas Algo: %.4s\n", algoTypeString);
					/* if it is a multistream or preshared commit, get the 16 bytes nonce */
					if ((messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Prsh) || (messageData->keyAgreementAlgo == ZRTP_KEYAGREEMENT_Mult)) {
						printHex("Nonce", messageData->nonce, 16);

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

					printHex("\nMAC", messageData->MAC, 8);
				}
				break;
			case MSGTYPE_DHPART1:
			case MSGTYPE_DHPART2:
				{
212 213
					bzrtpDHPartMessage_t *messageData;

214 215 216 217 218
					if (zrtpPacket->messageType == MSGTYPE_DHPART1) {
						printf(" - Message Type : DHPart1\n");
					} else {
						printf(" - Message Type : DHPart2\n");
					}
219
					messageData = (bzrtpDHPartMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
					printHex ("H1", messageData->H1, 32);
					printHex ("rs1ID", messageData->rs1ID, 8);
					printHex ("rs2ID", messageData->rs2ID, 8);
					printHex ("auxsecretID", messageData->auxsecretID, 8);
					printHex ("pbxsecretID", messageData->pbxsecretID, 8);
					printHex ("rs1ID", messageData->rs1ID, 8);
					printf("PV length is %d\n", (zrtpPacket->messageLength-84));
					printHex ("PV", messageData->pv, (zrtpPacket->messageLength-84)); /* length of fixed part of the message is 84, rest is the variable length PV */
					printHex("MAC", messageData->MAC, 8);
					
				}
				break;
			case MSGTYPE_CONFIRM1:
			case MSGTYPE_CONFIRM2:
				{
235 236
					bzrtpConfirmMessage_t *messageData;

237 238 239 240 241
					if (zrtpPacket->messageType == MSGTYPE_CONFIRM1) {
						printf(" - Message Type : Confirm1\n");
					} else {
						printf(" - Message Type : Confirm2\n");
					}
242
					messageData = (bzrtpConfirmMessage_t *)zrtpPacket->messageData;
johan's avatar
johan committed
243 244 245 246 247
					printHex("H0", messageData->H0, 32);
					printf("sig_len %d\n", messageData->sig_len);
					printf("E %d V %d A %d D %d\n", messageData->E,  messageData->V, messageData->A, messageData->D);
					printf("Cache expiration Interval %08x\n", messageData->cacheExpirationInterval);
				}
248 249 250 251 252
				break;
			case MSGTYPE_CONF2ACK:
				{
					printf(" - Message Type: Conf2ACK\n");
				}
johan's avatar
johan committed
253 254 255 256 257
		}

		if (addRawMessage) {
			printHex("Data", zrtpPacket->packetString, zrtpPacket->messageLength+16);
		}
258
		fflush(NULL);
johan's avatar
johan committed
259
	}
johan's avatar
johan committed
260 261 262
}

void dumpContext(char *title, bzrtpContext_t *zrtpContext) {
johan's avatar
johan committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
	if (verbose) {
		uint8_t buffer[4];
		int i,j;
		printf("%s context is :\n", title);
		printHex("selfZID", zrtpContext->selfZID, 12);
		printHex("peerZID", zrtpContext->peerZID, 12);

		for (i=0; i<ZRTP_MAX_CHANNEL_NUMBER; i++) {
			if (zrtpContext->channelContext[i] != NULL) {
				bzrtpChannelContext_t *channelContext = zrtpContext->channelContext[i];
				printf("Channel %i\n  self: %08x\n", i, channelContext->selfSSRC);
				printf ("    selfH: ");
				for (j=0; j<4; j++) {
					printHex("      ", channelContext->selfH[j], 32);
				}
				printf ("    peerH: ");
				for (j=0; j<4; j++) {
					printHex("      ", channelContext->peerH[j], 32);
				}		

Ghislain MARY's avatar
Ghislain MARY committed
283
				bzrtp_cryptoAlgoTypeIntToString(channelContext->hashAlgo, buffer);
johan's avatar
johan committed
284
				printf("    Selected algos\n     - Hash: %.4s\n", buffer);
Ghislain MARY's avatar
Ghislain MARY committed
285
				bzrtp_cryptoAlgoTypeIntToString(channelContext->cipherAlgo, buffer);
johan's avatar
johan committed
286
				printf("     - cipher: %.4s\n", buffer);
Ghislain MARY's avatar
Ghislain MARY committed
287
				bzrtp_cryptoAlgoTypeIntToString(channelContext->authTagAlgo, buffer);
johan's avatar
johan committed
288
				printf("     - auth tag: %.4s\n", buffer);
Ghislain MARY's avatar
Ghislain MARY committed
289
				bzrtp_cryptoAlgoTypeIntToString(channelContext->keyAgreementAlgo, buffer);
johan's avatar
johan committed
290
				printf("     - key agreement: %.4s\n", buffer);
Ghislain MARY's avatar
Ghislain MARY committed
291
				bzrtp_cryptoAlgoTypeIntToString(channelContext->sasAlgo, buffer);
johan's avatar
johan committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
				printf("     - sas: %.4s\n", buffer);
				printHex("    initiator auxID", channelContext->initiatorAuxsecretID, 8);
				printHex("    responder auxID", channelContext->responderAuxsecretID, 8);
				if (channelContext->s0 != NULL) {
					printHex("    s0", channelContext->s0, channelContext->hashLength);
				}
				if(channelContext->srtpSecrets.sas != NULL) {
					printf("    sas : %.4s\n", channelContext->srtpSecrets.sas);
				}
				if (channelContext->srtpSecrets.selfSrtpKey != NULL) {
					printHex("    selfsrtp key", channelContext->srtpSecrets.selfSrtpKey, channelContext->srtpSecrets.selfSrtpKeyLength);
					printHex("    selfsrtp salt", channelContext->srtpSecrets.selfSrtpSalt, channelContext->srtpSecrets.selfSrtpSaltLength);
					printHex("    peersrtp key", channelContext->srtpSecrets.peerSrtpKey, channelContext->srtpSecrets.peerSrtpKeyLength);
					printHex("    peersrtp salt", channelContext->srtpSecrets.peerSrtpSalt, channelContext->srtpSecrets.peerSrtpSaltLength);
				}
				if (channelContext->mackeyi!=NULL) {
					printHex("    mackeyi", channelContext->mackeyi, channelContext->hashLength);
				}
				if (channelContext->mackeyr!=NULL) {
					printHex("    mackeyr", channelContext->mackeyr, channelContext->hashLength);
				}
				if (channelContext->zrtpkeyi!=NULL) {
					printHex("    zrtpkeyi", channelContext->zrtpkeyi, channelContext->cipherKeyLength);
				}
				if (channelContext->zrtpkeyr!=NULL) {
					printHex("    zrtpkeyr", channelContext->zrtpkeyr, channelContext->cipherKeyLength);
				}
319
			}
johan's avatar
johan committed
320
		}
johan's avatar
johan committed
321

johan's avatar
johan committed
322 323 324 325
		printf("Initiator Shared Secrets :\n");
		printHex("rs1ID", zrtpContext->initiatorCachedSecretHash.rs1ID, 8);
		printHex("rs2ID", zrtpContext->initiatorCachedSecretHash.rs2ID, 8);
		printHex("pbxID", zrtpContext->initiatorCachedSecretHash.pbxsecretID, 8);
johan's avatar
johan committed
326

johan's avatar
johan committed
327 328 329 330
		printf("Responder Shared Secrets :\n");
		printHex("rs1ID", zrtpContext->responderCachedSecretHash.rs1ID, 8);
		printHex("rs2ID", zrtpContext->responderCachedSecretHash.rs2ID, 8);
		printHex("pbxID", zrtpContext->responderCachedSecretHash.pbxsecretID, 8);
331
		fflush(NULL);
johan's avatar
johan committed
332
	}
johan's avatar
johan committed
333
}
johan's avatar
johan committed
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350


#ifdef ZIDCACHE_ENABLED

#define MAX_PATH_SIZE 1024

int bzrtptester_sqlite3_open(const char *db_file, sqlite3 **db) {
	char* errmsg = NULL;
	int ret;
	int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;

#if TARGET_OS_IPHONE
	/* the secured filesystem of the iPHone doesn't allow writing while the app is in background mode, which is problematic.
	 * We workaround by asking that the open is made with no protection*/
	flags |= SQLITE_OPEN_FILEPROTECTION_NONE;
#endif

jehan's avatar
jehan committed
351
	ret = sqlite3_open_v2(db_file, db, flags, NULL);
johan's avatar
johan committed
352 353 354 355 356 357 358 359 360 361 362 363 364

	if (ret != SQLITE_OK) return ret;
	// Some platforms do not provide a way to create temporary files which are needed
	// for transactions... so we work in memory only
	// see http ://www.sqlite.org/compile.html#temp_store
	ret = sqlite3_exec(*db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errmsg);
	if (ret != SQLITE_OK) {
		sqlite3_free(errmsg);
	}

	return ret;
}
#endif /* ZIDCACHE_ENABLED */