zrtp.c 38 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
  mediastreamer2 library - modular sound and video processing and streaming
  Copyright (C) 2014 Belledonne Communications

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "mediastreamer2/zrtp.h"
#include "mediastreamer2/mediastream.h"

23
#ifdef _WIN32
24 25 26
#include <malloc.h>
#endif

27
#ifdef HAVE_ZRTP
28 29 30 31 32 33 34
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include <bzrtp/bzrtp.h>

struct _MSZrtpContext{
35 36 37 38
	MSMediaStreamSessions *stream_sessions; /**< a retro link to the stream session as we need it to configure srtp sessions */
	uint32_t self_ssrc; /**< store the sender ssrc as it is needed by zrtp to manage channels(and we may destroy stream_sessions before destroying zrtp's one) */
	RtpTransportModifier *rtp_modifier; /**< transport modifier needed to be able to inject the ZRTP packet for sending */
	bzrtpContext_t *zrtpContext; /**< the opaque zrtp context from libbzrtp */
johan's avatar
johan committed
39 40 41
	/* cache related data */
	uint32_t limeKeyTimeSpan; /**< amount in seconds of the lime key life span */
	void *cacheDB; /**< pointer to an already open sqlite db holding the zid cache */
42
	bctbx_mutex_t *cacheDBMutex; /**< pointer to a mutex used to lock cache access */
43 44
};

45 46 47
/***********************************************/
/***** LOCAL FUNCTIONS                     *****/
/***********************************************/
48

49 50
/********************/
/* Helper functions */
51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/* trace functions: bzrtp algo code to string */
static 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";
	}
}

static 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's avatar
johan committed
72 73
		case(ZRTP_KEYAGREEMENT_X255): return "ECDH-255";
		case(ZRTP_KEYAGREEMENT_X448): return "ECDH-448";
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 107 108 109 110 111
		case(ZRTP_KEYAGREEMENT_Prsh): return "PreShared";
		case(ZRTP_KEYAGREEMENT_Mult): return "MultiStream";
		default: return "Unknown Algo";
	}
}

static 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";
	}
}

static 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";
	}
}

static 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";
	}
}
112
/*****************************************/
113 114
/* ZRTP library Callbacks implementation */

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/**
 * @brief collect messages from the bzrtp lib, log them and pass some through ORTP_EVENTS to liblinphone
 *
 * @param[in]	clientData	Pointer to our ZrtpContext structure
 * @param[in]	messageLevel	One of  BZRTP_MESSAGE_ERROR, BZRTP_MESSAGE_WARNING, BZRTP_MESSAGE_LOG, BZRTP_MESSAGE_DEBUG
 * @param[in]	messageId	Message code mapped to an int as defined in bzrtp.h
 * @param[in]	messageString	Can be NULL or a NULL terminated string
 *
 * @return	0 on success
 */
static int ms_zrtp_statusMessage(void *clientData, const uint8_t messageLevel, const uint8_t messageId, const char *messageString) {
	MSZrtpContext *userData = (MSZrtpContext *)clientData;
	OrtpEventData *eventData;
	OrtpEvent *ev;

	switch (messageId) {
		case BZRTP_MESSAGE_CACHEMISMATCH:
			ev=ortp_event_new(ORTP_EVENT_ZRTP_CACHE_MISMATCH);
			eventData=ortp_event_get_data(ev);
134
			eventData->info.zrtp_info.cache_mismatch=1;
135 136 137 138 139 140 141
			rtp_session_dispatch_event(userData->stream_sessions->rtp_session, ev);
			ms_warning("Zrtp Event dispatched : cache mismatch"); /* log it as a warning */
			break;
		case BZRTP_MESSAGE_PEERVERSIONOBSOLETE:
			ev=ortp_event_new(ORTP_EVENT_ZRTP_PEER_VERSION_OBSOLETE);
			eventData=ortp_event_get_data(ev);
			rtp_session_dispatch_event(userData->stream_sessions->rtp_session, ev);
johan's avatar
johan committed
142 143 144 145 146
			ms_message("Zrtp Event dispatched : Peer ZRTP engine version is obsolete and may not allow LIME to work correctly, peer ZRTP engine identifies itself as %.16s", messageString==NULL?"NULL":messageString);
			break;
		case BZRTP_MESSAGE_PEERNOTBZRTP:
			/* Do not forward this message upward, just log it, shall we use this to prevent LIME keys creation as it is unlikely peer implement LIME? */
			ms_warning("Peer ZRTP engine version is not BZRTP and would not allow LIME to work correctly, peer ZRTP engine identifies itself as %.16s", messageString==NULL?"NULL":messageString);
147 148 149 150 151 152 153 154 155 156
			break;
		default:
			/* unexepected message, do nothing, just log it as a warning */
			ms_warning("Zrtp Message Unknown : Level %d Id %d message %s", messageLevel, messageId, messageString==NULL?"NULL":messageString);
			break;
	}

	return 0;
}

157
/**
158
* @brief Send a ZRTP packet via RTP transport modifiers.
159 160 161
*
* ZRTP calls this method to send a ZRTP packet via the RTP session.
*
162 163 164 165
* @param[in]	clientData	Pointer to our ZrtpContext structure used to retrieve RTP session
* @param[in]	data		Points to ZRTP message to send.
* @param[in]	length		The length in bytes of the data
* @return	0 on success
166
*/
Simon Morlat's avatar
Simon Morlat committed
167
static int32_t ms_zrtp_sendDataZRTP (void *clientData, const uint8_t* data, uint16_t length ){
168
	MSZrtpContext *userData = (MSZrtpContext *)clientData;
169
	RtpSession *session = userData->stream_sessions->rtp_session;
170 171 172
	RtpTransport *rtpt=NULL;
	mblk_t *msg;

173
	ms_message("ZRTP Send packet type %.8s on rtp session [%p]", data+16, session);
174 175 176 177 178 179 180

	/* get RTP transport from session */
	rtp_session_get_transports(session,&rtpt,NULL);

	/* generate message from raw data */
 	msg = rtp_session_create_packet_raw(data, length);

181
	meta_rtp_transport_modifier_inject_packet_to_send(rtpt, userData->rtp_modifier, msg , 0);
182

183 184
	freemsg(msg);

185 186 187 188
	return 0;
}

/**
189
 * @briefThis function is called by ZRTP engine as soon as SRTP secrets are ready to be used
190 191
 * Depending on which role we assume in the ZRTP protocol (Initiator or Responder, randomly selected)
 * both secrets may not be available at the same time, the part argument is either
192 193 194 195 196 197 198
 * ZRTP_SRTP_SECRETS_FOR_SENDER or ZRTP_SRTP_SECRETS_FOR_RECEIVER.
 * Secrets are used to set up SRTP sessions
 *
 * @param[in]	clientData	Pointer to our ZrtpContext structure used to retrieve stream sessions structure needed to setup SRTP sessions
 * @param[in]	secrets		The SRTP keys and algorithm setup
 * @param[in]	part		for receiver or for sender in order to determine which SRTP stream the secret apply to
 * @return 	0 on success
199
 */
200
static int32_t ms_zrtp_srtpSecretsAvailable(void* clientData, const bzrtpSrtpSecrets_t *secrets, uint8_t part) {
201 202 203 204 205 206 207 208
	MSZrtpContext *userData = (MSZrtpContext *)clientData;


	// Get authentication and cipher algorithms in srtp format
	if ((secrets->authTagAlgo != ZRTP_AUTHTAG_HS32) && ((secrets->authTagAlgo != ZRTP_AUTHTAG_HS80))) {
		ms_fatal("unsupported authentication algorithm by srtp");
	}

209
	if ((secrets->cipherAlgo != ZRTP_CIPHER_AES1) && (secrets->cipherAlgo != ZRTP_CIPHER_AES3)) {
210 211 212
		ms_fatal("unsupported cipher algorithm by srtp");
	}

213
	ms_message("ZRTP secrets are ready for %s; auth tag algo is %s and cipher algo is %s", (part==ZRTP_SRTP_SECRETS_FOR_SENDER)?"sender":"receiver", bzrtp_authtag_toString(secrets->authTagAlgo), bzrtp_cipher_toString(secrets->cipherAlgo));
214 215 216 217 218 219 220 221


	if (part==ZRTP_SRTP_SECRETS_FOR_RECEIVER) {
		uint8_t *key = (uint8_t *)ms_malloc0((secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength+16)*sizeof(uint8_t));
		memcpy(key, secrets->peerSrtpKey, secrets->peerSrtpKeyLength);
		memcpy(key + secrets->peerSrtpKeyLength, secrets->peerSrtpSalt, secrets->peerSrtpSaltLength);

		if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS32){
222
			if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){
223
				ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_256_SHA1_32, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS);
224
			}else{
225
				ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_128_SHA1_32, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS);
226
			}
227
		}else if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS80){
228
			if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){
229
				ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_256_SHA1_80, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS);
230
			}else{
231
				ms_media_stream_sessions_set_srtp_recv_key(userData->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, (secrets->peerSrtpKeyLength+secrets->peerSrtpSaltLength), MSSRTP_ALL_STREAMS);
232
			}
233 234 235 236 237 238 239 240 241 242 243 244
		}else{
			ms_fatal("unsupported auth tag");
		}
		ms_free(key);
	}

	if (part==ZRTP_SRTP_SECRETS_FOR_SENDER) {
		uint8_t *key = (uint8_t *)ms_malloc0((secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength+16)*sizeof(uint8_t));
		memcpy(key, secrets->selfSrtpKey, secrets->selfSrtpKeyLength);
		memcpy(key + secrets->selfSrtpKeyLength, secrets->selfSrtpSalt, secrets->selfSrtpSaltLength);

		if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS32){
245
			if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){
246
				ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_256_SHA1_32, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS);
247
			}else{
248
				ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_128_SHA1_32, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS);
249
			}
250
		}else if (secrets->authTagAlgo == ZRTP_AUTHTAG_HS80){
251
			if (secrets->cipherAlgo == ZRTP_CIPHER_AES3){
252
				ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_256_SHA1_80, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS);
253
			}else{
254
				ms_media_stream_sessions_set_srtp_send_key(userData->stream_sessions, MS_AES_128_SHA1_80, (const char *)key, (secrets->selfSrtpKeyLength+secrets->selfSrtpSaltLength), MSSRTP_ALL_STREAMS);
255
			}
256 257 258 259 260 261 262 263 264 265
		}else{
			ms_fatal("unsupported auth tag");
		}
		ms_free(key);
	}

	return 0;
}

/**
266
 * @brief Switch on the security.
267
 *
268 269
 * ZRTP calls this method after it has computed the SAS and checked
 * if it was verified in the past.
270 271
 *
 * This method must enable SRTP processing if it was not enabled
272
 * during setSecretsReady().
273
 *
274
 * This call will trigger an event which shall be catched by linphone_call_handle_stream_events
275
 *
276
 * @param[in]	clientData	Pointer to our ZrtpContext structure used to retrieve RTP session
277
 * @param[in]	secrets 	A structure containing the SAS string(null terminated, variable length according to SAS rendering algo choosen) and informations about the crypto algorithms used by ZRTP during negotiation
278
 * @param[in]	verified	if <code>verified</code> is true then SAS was verified by both parties during a previous call.
279
 */
280
static int ms_zrtp_startSrtpSession(void *clientData,  const bzrtpSrtpSecrets_t *secrets, int32_t verified ){
281 282 283 284 285 286 287 288
	MSZrtpContext *userData = (MSZrtpContext *)clientData;

	// srtp processing is enabled in SecretsReady fuction when receiver secrets are ready
	// Indeed, the secrets on is called before both parts are given to secretsReady.

	OrtpEventData *eventData;
	OrtpEvent *ev;

289
	if (secrets->sas != NULL) {
290 291
		ev=ortp_event_new(ORTP_EVENT_ZRTP_SAS_READY);
		eventData=ortp_event_get_data(ev);
292
		// support both b32 and b256 format SAS strings
293 294 295
		snprintf(eventData->info.zrtp_info.sas, sizeof(eventData->info.zrtp_info.sas), "%s", secrets->sas);
		eventData->info.zrtp_info.verified=(verified != 0) ? TRUE : FALSE;
		eventData->info.zrtp_info.cache_mismatch=( secrets->cacheMismatch != 0) ? TRUE : FALSE;
296
		rtp_session_dispatch_event(userData->stream_sessions->rtp_session, ev);
297 298
		ms_message("ZRTP secrets on: SAS is %.32s previously verified %s on session [%p]", secrets->sas, verified == 0 ? "no" : "yes", userData->stream_sessions);
		ms_message("ZRTP algo used during negotiation: Cipher: %s - KeyAgreement: %s - Hash: %s - AuthTag: %s - Sas Rendering: %s", bzrtp_cipher_toString(secrets->cipherAlgo), bzrtp_keyAgreement_toString(secrets->keyAgreementAlgo), bzrtp_hash_toString(secrets->hashAlgo), bzrtp_authtag_toString(secrets->authTagAlgo), bzrtp_sas_toString(secrets->sasAlgo));
299 300 301 302 303
	}

	ev=ortp_event_new(ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED);
	eventData=ortp_event_get_data(ev);
	eventData->info.zrtp_stream_encrypted=1;
304
	rtp_session_dispatch_event(userData->stream_sessions->rtp_session, ev);
305 306 307 308 309 310 311 312
	ms_message("Event dispatched to all: secrets are on");


	return 0;
}

/**
 * @brief This callback is called when context is ready to compute exported keys as in rfc6189 section 4.5.2
313
 * Computed keys are added to zid cache with sip URI of peer(found in client Data) to be used for LIME(IM ciphering)
314
 *
johan's avatar
johan committed
315
 * @param[in]	zidCacheData	Pointer to our ZidCacheContext structure used to retrieve ZID filename
316 317 318
 * @param[in]	clientData	Pointer to our ZrtpContext structure used to retrieve peer SIP URI
 * @param[in]	peerZid		Peer ZID to address correct node in zid cache
 * @param[in]	role		RESPONDER or INITIATOR, needed to compute the pair of keys for IM ciphering
319 320 321
 *
 * @return 	0 on success
 */
johan's avatar
johan committed
322
static int ms_zrtp_addExportedKeysInZidCache(void *clientData, int zuid, uint8_t role) {
323 324
	MSZrtpContext *userData = (MSZrtpContext *)clientData;
	bzrtpContext_t *zrtpContext = userData->zrtpContext;
325
	bctoolboxTimeSpec currentTime;
johan's avatar
johan committed
326
	/* columns to be written in cache */
Ghislain MARY's avatar
Ghislain MARY committed
327
	const char *colNames[] = {"sndKey", "rcvKey", "sndSId", "rcvSId", "sndIndex", "rcvIndex", "valid"};
johan's avatar
johan committed
328 329 330 331 332 333 334
	uint8_t *colValues[7];
	size_t colLength[] = {32, 32, 32, 32, 4, 4, 8}; /* data length: keys and session ID : 32 bytes, Indexes: 4 bytes(uint32_t), validity : 8 bytes(UTC time as int64_t) */
	int i,ret;

	/* allocate colValues */
	for (i=0; i<7; i++) {
		colValues[i] = (uint8_t *)ms_malloc(colLength[i]*sizeof(uint8_t));
335 336
	}

johan's avatar
johan committed
337 338 339 340 341 342 343 344 345 346 347 348
	/* First compute the exported keys */
	bzrtp_exportKey(zrtpContext, ((role==BZRTP_ROLE_RESPONDER)?"ResponderKey":"InitiatorKey"), 12, colValues[0], &colLength[0]); /* sndKey */
	bzrtp_exportKey(zrtpContext, ((role==BZRTP_ROLE_RESPONDER)?"InitiatorKey":"ResponderKey"), 12, colValues[1], &colLength[1]); /* rcvKey */
	bzrtp_exportKey(zrtpContext, ((role==BZRTP_ROLE_RESPONDER)?"ResponderSId":"InitiatorSId"), 12, colValues[2], &colLength[2]); /* snd Session Id*/
	bzrtp_exportKey(zrtpContext, ((role==BZRTP_ROLE_RESPONDER)?"InitiatorSId":"ResponderSId"), 12, colValues[3], &colLength[3]); /* rcv Session Id*/
	bzrtp_exportKey(zrtpContext, ((role==BZRTP_ROLE_RESPONDER)?"ResponderIndex":"InitiatorIndex"), 14, colValues[4], &colLength[4]); /* snd Index */
	bzrtp_exportKey(zrtpContext, ((role==BZRTP_ROLE_RESPONDER)?"InitiatorIndex":"ResponderIndex"), 14, colValues[5], &colLength[5]); /* rcv Index */

	/* insert validity */
	if (userData->limeKeyTimeSpan == 0) { /* time span is 0: key is forever valid, just put 0 in cache */
		memset(colValues[6], 0, 8);
	} else { /* get current time and add time span */
349
		bctbx_get_utc_cur_time(&currentTime);
johan's avatar
johan committed
350 351 352 353 354 355 356 357 358 359
		bctbx_timespec_add(&currentTime, (int64_t)(userData->limeKeyTimeSpan));
		/* store the int64_t in big endian in the cache(cache is not typed, all data seen as blob) */
		colValues[6][0] = (currentTime.tv_sec>>56)&0xFF;
		colValues[6][1] = (currentTime.tv_sec>>48)&0xFF;
		colValues[6][2] = (currentTime.tv_sec>>40)&0xFF;
		colValues[6][3] = (currentTime.tv_sec>>32)&0xFF;
		colValues[6][4] = (currentTime.tv_sec>>24)&0xFF;
		colValues[6][5] = (currentTime.tv_sec>>16)&0xFF;
		colValues[6][6] = (currentTime.tv_sec>>8)&0xFF;
		colValues[6][7] = (currentTime.tv_sec)&0xFF;
360
	}
361

johan's avatar
johan committed
362 363 364 365 366
	/* colValues 4 and 5 hold index(uint32_t as 4 bytes in big endian), make sure the first bit on the MSB is set to 0 to avoid loop in the index */
	colValues[4][0] &= 0x7F;
	colValues[5][0] &= 0x7F;

	/* then insert all in cache */
367
	ret = bzrtp_cache_write_lock(userData->cacheDB, zuid, "lime", colNames, colValues, colLength, 7, userData->cacheDBMutex);
johan's avatar
johan committed
368 369 370 371 372 373

	for (i=0; i<7; i++) {
		ms_free(colValues[i]);
	}

	return ret;
374 375
}

376
/*************************************************/
377 378
/*** end of Callback functions implementations ***/

379 380 381 382

/*******************************************************/
/**** Transport Modifier Sender/Receiver functions  ****/

383
static int ms_zrtp_rtp_process_on_send(RtpTransportModifier *t, mblk_t *msg){
384
	return (int)msgdsize(msg);
385
}
386
static int ms_zrtp_rtcp_process_on_send(RtpTransportModifier *t, mblk_t *msg)  {
387
	return (int)msgdsize(msg);
388 389
}

390 391 392 393 394 395 396 397
static void ms_zrtp_rtp_on_schedule(RtpTransportModifier *t){
	MSZrtpContext *userData = (MSZrtpContext*) t->data;
	bzrtpContext_t *zrtpContext = userData->zrtpContext;
	// send a timer tick to the zrtp engine
	bzrtp_iterate(zrtpContext, userData->self_ssrc, bctbx_get_cur_time_ms());
}

static int ms_zrtp_rtp_process_on_receive(RtpTransportModifier *t, mblk_t *msg){
398 399 400 401 402 403
	uint32_t *magicField;

	MSZrtpContext *userData = (MSZrtpContext*) t->data;
	bzrtpContext_t *zrtpContext = userData->zrtpContext;
	uint8_t* rtp;
	int rtpVersion;
404
	int msgLength = (int)msgdsize(msg);
405

406
	
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422

	// check incoming message length
	if (msgLength<RTP_FIXED_HEADER_SIZE) {
		return msgLength;
	}

	rtp=msg->b_rptr;
	rtpVersion = ((rtp_header_t*)rtp)->version;
	magicField=(uint32_t *)(rtp + 4);

	// Check if there is a ZRTP packet to receive
	if (rtpVersion!=0 || ntohl(*magicField) != ZRTP_MAGIC_COOKIE) {
		return msgLength;
	}

	// display received message
423
	ms_message("ZRTP Receive packet type %.8s on rtp session [%p]", rtp+16, t->session);
424

425 426 427 428 429
	// check if the ZRTP channel is started, if not(ZRTP not set on our side but incoming zrtp packets), start it
	if (bzrtp_getChannelStatus(zrtpContext, userData->self_ssrc) == BZRTP_CHANNEL_INITIALISED) {
		bzrtp_startChannelEngine(zrtpContext, userData->self_ssrc);
	}

430
	// send ZRTP packet to engine
431
	bzrtp_processMessage(zrtpContext, userData->self_ssrc, rtp, msgLength);
432 433 434 435
	return 0;
}

/* Nothing to do on rtcp packets, just return packet length */
436
static int ms_zrtp_rtcp_process_on_receive(RtpTransportModifier *t, mblk_t *msg)  {
437
	return (int)msgdsize(msg);
438 439 440
}


441 442 443 444
/**************************************/
/**** session management functions ****/
static void ms_zrtp_transport_modifier_destroy(RtpTransportModifier *tp)  {
	ms_free(tp);
445 446
}

447
static int ms_zrtp_transport_modifier_new(MSZrtpContext* ctx, RtpTransportModifier **rtpt, RtpTransportModifier **rtcpt ) {
448 449
	if (rtpt){
		*rtpt=ms_new0(RtpTransportModifier,1);
johan's avatar
johan committed
450
		(*rtpt)->data=ctx; /* back link to get access to the other fields of the OrtpZrtpContext from the RtpTransportModifier structure */
451 452 453
		(*rtpt)->t_process_on_send=ms_zrtp_rtp_process_on_send;
		(*rtpt)->t_process_on_receive=ms_zrtp_rtp_process_on_receive;
		(*rtpt)->t_destroy=ms_zrtp_transport_modifier_destroy;
454
		(*rtpt)->t_process_on_schedule = ms_zrtp_rtp_on_schedule;
455 456 457
	}
	if (rtcpt){
		*rtcpt=ms_new0(RtpTransportModifier,1);
johan's avatar
johan committed
458
		(*rtcpt)->data=ctx; /* back link to get access to the other fields of the OrtpZrtpContext from the RtpTransportModifier structure */
459 460 461 462 463 464 465
		(*rtcpt)->t_process_on_send=ms_zrtp_rtcp_process_on_send;
		(*rtcpt)->t_process_on_receive=ms_zrtp_rtcp_process_on_receive;
		(*rtcpt)->t_destroy=ms_zrtp_transport_modifier_destroy;
	}
	return 0;
}

466
static MSZrtpContext* ms_zrtp_configure_context(MSZrtpContext *userData, RtpSession *s) {
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
	RtpTransport *rtpt=NULL,*rtcpt=NULL;
	RtpTransportModifier *rtp_modifier, *rtcp_modifier;

	rtp_session_get_transports(s,&rtpt,&rtcpt);

	ms_zrtp_transport_modifier_new(userData, &rtp_modifier,&rtcp_modifier);
	meta_rtp_transport_append_modifier(rtpt, rtp_modifier);
	meta_rtp_transport_append_modifier(rtcpt, rtcp_modifier);

	/* save transport modifier into context, needed to inject packets generated by ZRTP */
	userData->rtp_modifier = rtp_modifier;

	return userData;
}

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
static void set_hash_suites(bzrtpContext_t *ctx, const MSZrtpHash *hashes, const MsZrtpCryptoTypesCount count) {
	int i;
	uint8_t bzrtpCount = 0;
	uint8_t bzrtpHashes[7];

	for (i=0; i < count; i++) {
		switch (hashes[i]) {
			case MS_ZRTP_HASH_INVALID: break;
			case MS_ZRTP_HASH_S256: bzrtpHashes[bzrtpCount++] = ZRTP_HASH_S256; break;
			case MS_ZRTP_HASH_S384: bzrtpHashes[bzrtpCount++] = ZRTP_HASH_S384; break;
			case MS_ZRTP_HASH_N256: bzrtpHashes[bzrtpCount++] = ZRTP_HASH_N256; break;
			case MS_ZRTP_HASH_N384: bzrtpHashes[bzrtpCount++] = ZRTP_HASH_N384; break;
		}
	}

	bzrtp_setSupportedCryptoTypes(ctx, ZRTP_HASH_TYPE, bzrtpHashes, bzrtpCount);
}

static void set_cipher_suites(bzrtpContext_t *ctx, const MSZrtpCipher *ciphers, const MsZrtpCryptoTypesCount count) {
	int i;
	uint8_t bzrtpCount = 0;
	uint8_t bzrtpCiphers[7];

	for (i=0; i < count; i++) {
		switch (ciphers[i]) {
			case MS_ZRTP_CIPHER_INVALID: break;
			case MS_ZRTP_CIPHER_AES1:    bzrtpCiphers[bzrtpCount++] = ZRTP_CIPHER_AES1; break;
			case MS_ZRTP_CIPHER_AES2:    bzrtpCiphers[bzrtpCount++] = ZRTP_CIPHER_AES2; break;
			case MS_ZRTP_CIPHER_AES3:    bzrtpCiphers[bzrtpCount++] = ZRTP_CIPHER_AES3; break;
			case MS_ZRTP_CIPHER_2FS1:    bzrtpCiphers[bzrtpCount++] = ZRTP_CIPHER_2FS1; break;
			case MS_ZRTP_CIPHER_2FS2:    bzrtpCiphers[bzrtpCount++] = ZRTP_CIPHER_2FS2; break;
			case MS_ZRTP_CIPHER_2FS3:    bzrtpCiphers[bzrtpCount++] = ZRTP_CIPHER_2FS3; break;
		}
	}

	bzrtp_setSupportedCryptoTypes(ctx, ZRTP_CIPHERBLOCK_TYPE, bzrtpCiphers, bzrtpCount);
}

static void set_auth_tag_suites(bzrtpContext_t *ctx, const MSZrtpAuthTag *authTags, const MsZrtpCryptoTypesCount count) {
	int i;
	uint8_t bzrtpCount = 0;
	uint8_t bzrtpAuthTags[7];

	for (i=0; i < count; i++) {
		switch (authTags[i]) {
			case MS_ZRTP_AUTHTAG_INVALID: break;
			case MS_ZRTP_AUTHTAG_HS32:    bzrtpAuthTags[bzrtpCount++] = ZRTP_AUTHTAG_HS32; break;
			case MS_ZRTP_AUTHTAG_HS80:    bzrtpAuthTags[bzrtpCount++] = ZRTP_AUTHTAG_HS80; break;
			case MS_ZRTP_AUTHTAG_SK32:    bzrtpAuthTags[bzrtpCount++] = ZRTP_AUTHTAG_SK32; break;
			case MS_ZRTP_AUTHTAG_SK64:    bzrtpAuthTags[bzrtpCount++] = ZRTP_AUTHTAG_SK64; break;
		}
	}

	bzrtp_setSupportedCryptoTypes(ctx, ZRTP_AUTHTAG_TYPE, bzrtpAuthTags, bzrtpCount);
}

static void set_key_agreement_suites(bzrtpContext_t *ctx, const MSZrtpKeyAgreement *keyAgreements, const MsZrtpCryptoTypesCount count) {
	int i;
	uint8_t bzrtpCount = 0;
	uint8_t bzrtpKeyAgreements[7];

	for (i=0; i < count; i++) {
		switch (keyAgreements[i]) {
			case MS_ZRTP_KEY_AGREEMENT_INVALID: break;
			case MS_ZRTP_KEY_AGREEMENT_DH2K:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_DH2k; break;
			case MS_ZRTP_KEY_AGREEMENT_DH3K:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_DH3k; break;
			case MS_ZRTP_KEY_AGREEMENT_EC25:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_EC25; break;
			case MS_ZRTP_KEY_AGREEMENT_EC38:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_EC38; break;
			case MS_ZRTP_KEY_AGREEMENT_EC52:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_EC52; break;
johan's avatar
johan committed
551 552
			case MS_ZRTP_KEY_AGREEMENT_X255:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_X255; break;
			case MS_ZRTP_KEY_AGREEMENT_X448:    bzrtpKeyAgreements[bzrtpCount++] = ZRTP_KEYAGREEMENT_X448; break;
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
		}
	}

	bzrtp_setSupportedCryptoTypes(ctx, ZRTP_KEYAGREEMENT_TYPE, bzrtpKeyAgreements, bzrtpCount);
}

static void set_sas_suites(bzrtpContext_t *ctx, const MSZrtpSasType *sasTypes, const MsZrtpCryptoTypesCount count) {
	int i;
	uint8_t bzrtpCount = 0;
	uint8_t bzrtpSasTypes[7];

	for (i=0; i < count; i++) {
		switch (sasTypes[i]) {
			case MS_ZRTP_SAS_INVALID: break;
			case MS_ZRTP_SAS_B32:     bzrtpSasTypes[bzrtpCount++] = ZRTP_SAS_B32; break;
			case MS_ZRTP_SAS_B256:    bzrtpSasTypes[bzrtpCount++] = ZRTP_SAS_B256; break;
		}
	}

	bzrtp_setSupportedCryptoTypes(ctx, ZRTP_SAS_TYPE, bzrtpSasTypes, bzrtpCount);
}

575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
/***********************************************/
/***** EXPORTED FUNCTIONS                  *****/
/***********************************************/
/**** Private to mediastreamer2 functions ****/
/* header declared in voip/private.h */
void ms_zrtp_set_stream_sessions(MSZrtpContext *zrtp_context, MSMediaStreamSessions *stream_sessions) {
	if (zrtp_context!=NULL) {
		zrtp_context->stream_sessions = stream_sessions;
	}
}

/**** Public functions ****/
/* header declared in include/mediastreamer2/zrtp.h */
bool_t ms_zrtp_available(){return TRUE;}

MSZrtpContext* ms_zrtp_context_new(MSMediaStreamSessions *sessions, MSZrtpParams *params) {
591 592
	MSZrtpContext *userData;
	bzrtpContext_t *context;
Simon Morlat's avatar
Simon Morlat committed
593
	bzrtpCallbacks_t cbs={0};
594

johan's avatar
johan committed
595 596 597
	ms_message("Creating ZRTP engine on rtp session [%p] ssrc 0x%x",sessions->rtp_session, sessions->rtp_session->snd.ssrc);
	context = bzrtp_createBzrtpContext();

johan's avatar
johan committed
598
	if (params->zidCacheDB != NULL && params->selfUri != NULL && params->peerUri) { /* to enable cache we need a self and peer uri and a pointer to the sqlite cache DB */
599
		/*enabling cache*/
600
		bzrtp_setZIDCache_lock(context, params->zidCacheDB, params->selfUri, params->peerUri, params->zidCacheDBMutex);
johan's avatar
johan committed
601
		cbs.bzrtp_contextReadyForExportedKeys=ms_zrtp_addExportedKeysInZidCache;
602 603
	}

johan's avatar
johan committed
604 605 606 607
	/* set other callback functions */
	cbs.bzrtp_sendData=ms_zrtp_sendDataZRTP;
	cbs.bzrtp_srtpSecretsAvailable=ms_zrtp_srtpSecretsAvailable;
	cbs.bzrtp_startSrtpSession=ms_zrtp_startSrtpSession;
608 609
	cbs.bzrtp_statusMessage=ms_zrtp_statusMessage;
	cbs.bzrtp_messageLevel=BZRTP_MESSAGE_LOG; /* get log, warnings and error messages from bzrtp lib */
johan's avatar
johan committed
610 611

	bzrtp_setCallbacks(context, &cbs);
612

613 614 615 616 617 618 619
	/* set crypto params */
	set_hash_suites(context, params->hashes, params->hashesCount);
	set_cipher_suites(context, params->ciphers, params->ciphersCount);
	set_auth_tag_suites(context, params->authTags, params->authTagsCount);
	set_key_agreement_suites(context, params->keyAgreements, params->keyAgreementsCount);
	set_sas_suites(context, params->sasTypes, params->sasTypesCount);

johan's avatar
johan committed
620 621 622 623 624 625 626 627
	/* complete the initialisation of zrtp context, this will also create the main channel context with the given SSRC */
	bzrtp_initBzrtpContext(context, sessions->rtp_session->snd.ssrc); /* init is performed only when creating the main channel context */

	/* create and link main channel user data */
	userData=ms_new0(MSZrtpContext,1);
	userData->zrtpContext=context;
	userData->stream_sessions=sessions;
	userData->self_ssrc = sessions->rtp_session->snd.ssrc;
johan's avatar
johan committed
628 629

	userData->limeKeyTimeSpan = params->limeKeyTimeSpan;
630 631
	userData->cacheDB = params->zidCacheDB; /* add a link to the ZidCache and mutex to be able to access it from callbacks */
	userData->cacheDBMutex = params->zidCacheDBMutex;
johan's avatar
johan committed
632 633 634

	bzrtp_setClientData(context, sessions->rtp_session->snd.ssrc, (void *)userData);

635
	return ms_zrtp_configure_context(userData, sessions->rtp_session);
636 637
}

johan's avatar
johan committed
638
MSZrtpContext* ms_zrtp_multistream_new(MSMediaStreamSessions *sessions, MSZrtpContext* activeContext) {
639 640
	int retval;
	MSZrtpContext *userData;
641
	if ((retval = bzrtp_addChannel(activeContext->zrtpContext, sessions->rtp_session->snd.ssrc)) != 0) {
johan's avatar
johan committed
642
		ms_warning("ZRTP could't add stream, returns %x", retval);
643 644
	}

johan's avatar
johan committed
645 646 647
	ms_message("Initializing multistream ZRTP context on rtp session [%p] ssrc 0x%x",sessions->rtp_session, sessions->rtp_session->snd.ssrc);
	userData=ms_new0(MSZrtpContext,1);
	userData->zrtpContext=activeContext->zrtpContext;
648 649
	userData->stream_sessions = sessions;
	userData->self_ssrc = sessions->rtp_session->snd.ssrc;
johan's avatar
johan committed
650
	/* no cache related information here as it is not needed for multistream channel */
651
	bzrtp_setClientData(activeContext->zrtpContext, sessions->rtp_session->snd.ssrc, (void *)userData);
652

653
	return ms_zrtp_configure_context(userData, sessions->rtp_session);
654 655
}

johan's avatar
johan committed
656 657 658 659 660
int ms_zrtp_channel_start(MSZrtpContext *ctx) {
	int retval;
	ms_message("Starting ZRTP engine on rtp session [%p] ssrc 0x%x",ctx->stream_sessions->rtp_session, ctx->self_ssrc);
	if ((retval = bzrtp_startChannelEngine(ctx->zrtpContext, ctx->self_ssrc)) != 0) {
		/* remap some error code */
661 662 663 664 665 666
		if (retval == BZRTP_ERROR_CHANNELALREADYSTARTED) {
			ms_message("ZRTP channel already started");
			return MSZRTP_ERROR_CHANNEL_ALREADY_STARTED;
		} else {
			ms_message("Unable to start ZRTP channel, error code %x", retval);
		}
johan's avatar
johan committed
667 668 669
	}
	return retval;
}
670

johan's avatar
johan committed
671 672

void ms_zrtp_context_destroy(MSZrtpContext *ctx) {
673
	ms_message("Stopping ZRTP context on session [%p]", ctx->stream_sessions ? ctx->stream_sessions->rtp_session : NULL);
johan's avatar
johan committed
674
	bzrtp_destroyBzrtpContext(ctx->zrtpContext, ctx->self_ssrc);
johan's avatar
johan committed
675 676
	ms_free(ctx);
	ms_message("ZRTP context destroyed");
677 678
}

679 680
void ms_zrtp_reset_transmition_timer(MSZrtpContext* ctx) {
	bzrtp_resetRetransmissionTimer(ctx->zrtpContext, ctx->self_ssrc);
681 682
}

683 684 685
void ms_zrtp_sas_verified(MSZrtpContext* ctx){
	bzrtp_SASVerified(ctx->zrtpContext);
}
686

687 688 689 690
uint8_t ms_zrtp_getAuxiliarySharedSecretMismatch(MSZrtpContext *ctx) {
	return bzrtp_getAuxiliarySharedSecretMismatch(ctx->zrtpContext);
}

691 692
void ms_zrtp_sas_reset_verified(MSZrtpContext* ctx){
	bzrtp_resetSASVerified(ctx->zrtpContext);
693 694
}

695 696
MSZrtpPeerStatus ms_zrtp_get_peer_status(void *db, const char *peerUri, bctbx_mutex_t *dbMutex){
	int status = bzrtp_cache_getPeerStatus_lock(db, peerUri, dbMutex);
697 698 699 700 701 702 703 704 705 706
	switch (status) {
		case BZRTP_CACHE_PEER_STATUS_UNKNOWN:
			return MS_ZRTP_PEER_STATUS_UNKNOWN;
		case BZRTP_CACHE_PEER_STATUS_INVALID:
			return MS_ZRTP_PEER_STATUS_INVALID;
		case BZRTP_CACHE_PEER_STATUS_VALID:
			return MS_ZRTP_PEER_STATUS_VALID;
		default:
			return MS_ZRTP_PEER_STATUS_UNKNOWN;
	}
707 708
}

johan's avatar
johan committed
709 710 711 712
int ms_zrtp_getHelloHash(MSZrtpContext* ctx, uint8_t *output, size_t outputLength) {
	return bzrtp_getSelfHelloHash(ctx->zrtpContext, ctx->self_ssrc, output, outputLength);
}

713 714 715 716
int ms_zrtp_setAuxiliarySharedSecret(MSZrtpContext *ctx, const uint8_t *auxSharedSecret, size_t auxSharedSecretLength) {
	return bzrtp_setAuxiliarySharedSecret(ctx->zrtpContext, auxSharedSecret, auxSharedSecretLength);
}

johan's avatar
johan committed
717 718 719
int ms_zrtp_setPeerHelloHash(MSZrtpContext *ctx, uint8_t *peerHelloHashHexString, size_t peerHelloHashHexStringLength) {
	return bzrtp_setPeerHelloHash(ctx->zrtpContext, ctx->self_ssrc, peerHelloHashHexString, peerHelloHashHexStringLength);
}
720

721 722 723 724 725
/**
 * @brief Check the given sqlite3 DB and create requested tables if needed
 * 	Also manage DB schema upgrade
 * @param[in/out]	db	Pointer to the sqlite3 db open connection
 * 				Use a void * to keep this API when building cacheless
726
 * @param[in]		dbMutex	a mutex to synchronise zrtp cache database operation. Ignored if NULL
727 728 729
 *
 * @return 0 on succes, MSZRTP_CACHE_SETUP if cache was empty, MSZRTP_CACHE_UPDATE if db structure was updated error code otherwise
 */
730 731
int ms_zrtp_initCache(void *db, bctbx_mutex_t *dbMutex) {
	int ret = bzrtp_initCache_lock(db, dbMutex);
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
	switch (ret) {
		case BZRTP_CACHE_SETUP:
			return MSZRTP_CACHE_SETUP;
		case BZRTP_CACHE_UPDATE:
			return MSZRTP_CACHE_UPDATE;
		case 0:
			return 0;
		default:
			ms_warning("bzrtp_initCache function returned a non zero code %x, something went probably wrong", ret);
			return MSZRTP_CACHE_ERROR;
	}
}

/**
 * @brief Perform migration from xml version to sqlite3 version of cache
 *	Warning: new version of cache associate a ZID to each local URI, the old one did not
 *		the migration function will associate any data in the cache to the sip URI given in parameter which shall be the default URI
 * @param[in]		cacheXml	a pointer to an xmlDocPtr structure containing the old cache to be migrated
 * @param[in/out]	cacheSqlite	a pointer to an sqlite3 structure containing a cache initialised using ms_zrtp_cache_init function
 * @param[in]		selfURI		default sip URI for this end point, NULL terminated char
 *
 * @return	0 on success, MSZRTP_ERROR_CACHEDISABLED when bzrtp was not compiled with cache enabled, MSZRTP_ERROR_CACHEMIGRATIONFAILED on error during migration
 */
int ms_zrtp_cache_migration(void *cacheXmlPtr, void *cacheSqlite, const char *selfURI) {
	int ret = bzrtp_cache_migration(cacheXmlPtr, cacheSqlite, selfURI);
	switch (ret) {
		case BZRTP_ERROR_CACHEDISABLED:
			return MSZRTP_ERROR_CACHEDISABLED;
		case BZRTP_ERROR_CACHEMIGRATIONFAILED:
			return MSZRTP_ERROR_CACHEMIGRATIONFAILED;
		case 0:
			return 0;
		default:
			ms_warning("bzrtp_cache_migration function returned a non zero code %x, something went probably wrong", ret);
			return MSZRTP_CACHE_ERROR;
	}
}

770
#else /* HAVE_ZRTP */
771 772 773

MSZrtpContext* ms_zrtp_context_new(MSMediaStreamSessions *sessions, MSZrtpParams *params){
	ms_message("ZRTP is disabled");
774 775 776
	return NULL;
}

777
MSZrtpContext* ms_zrtp_multistream_new(MSMediaStreamSessions *sessions, MSZrtpContext* activeContext) {
778
	ms_message("ZRTP is disabled - not adding stream");
779 780 781
	return NULL;
}

782
int ms_zrtp_channel_start(MSZrtpContext *ctx) { return 0;}
783 784 785
bool_t ms_zrtp_available(){return FALSE;}
void ms_zrtp_sas_verified(MSZrtpContext* ctx){}
void ms_zrtp_sas_reset_verified(MSZrtpContext* ctx){}
786
MSZrtpPeerStatus ms_zrtp_get_peer_status(void *db, const char *peerUri, bctbx_mutex_t *dbMutex) {return MS_ZRTP_PEER_STATUS_UNKNOWN;}
787
void ms_zrtp_context_destroy(MSZrtpContext *ctx){}
788
void ms_zrtp_reset_transmition_timer(MSZrtpContext* ctx) {};
789 790
int ms_zrtp_transport_modifier_new(MSZrtpContext* ctx, RtpTransportModifier **rtpt, RtpTransportModifier **rtcpt ) {return 0;}
void ms_zrtp_transport_modifier_destroy(RtpTransportModifier *tp)  {}
791
void ms_zrtp_set_stream_sessions(MSZrtpContext *zrtp_context, MSMediaStreamSessions *stream_sessions) {}
792 793
int ms_zrtp_getHelloHash(MSZrtpContext* ctx, uint8_t *output, size_t outputLength) {return 0;}
int ms_zrtp_setPeerHelloHash(MSZrtpContext *ctx, uint8_t *peerHelloHashHexString, size_t peerHelloHashHexStringLength) {return 0;}
794
int ms_zrtp_initCache(void *db, bctbx_mutex_t *dbMutex){return 0;}
795
int ms_zrtp_cache_migration(void *cacheXmlPtr, void *cacheSqlite, const char *selfURI) {return 0;}
796
#endif /* HAVE_ZRTP */
797

798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
#define STRING_COMPARE_RETURN(string, value)\
	if (strcmp(string,#value) == 0) return value

#define CASE_RETURN_STRING(value)\
	case value: return #value;

#define SWITCH_CRYPTO_ALGO(value, cases)\
	switch(value) {\
		cases\
	}\
	return "<NULL>";

MS2_PUBLIC MSZrtpHash ms_zrtp_hash_from_string(const char* str) {
	STRING_COMPARE_RETURN(str, MS_ZRTP_HASH_S256);
	STRING_COMPARE_RETURN(str, MS_ZRTP_HASH_S384);
	STRING_COMPARE_RETURN(str, MS_ZRTP_HASH_N256);
	STRING_COMPARE_RETURN(str, MS_ZRTP_HASH_N384);
	return MS_ZRTP_HASH_INVALID;
}
817

818 819 820 821 822 823 824 825 826
MS2_PUBLIC const char* ms_zrtp_hash_to_string(const MSZrtpHash hash) {
	SWITCH_CRYPTO_ALGO(hash,\
		CASE_RETURN_STRING(MS_ZRTP_HASH_INVALID);\
		CASE_RETURN_STRING(MS_ZRTP_HASH_S256);\
		CASE_RETURN_STRING(MS_ZRTP_HASH_S384);\
		CASE_RETURN_STRING(MS_ZRTP_HASH_N256);\
		CASE_RETURN_STRING(MS_ZRTP_HASH_N384);\
	);
}
827

828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
MS2_PUBLIC MSZrtpCipher ms_zrtp_cipher_from_string(const char* str) {
	STRING_COMPARE_RETURN(str, MS_ZRTP_CIPHER_AES1);
	STRING_COMPARE_RETURN(str, MS_ZRTP_CIPHER_AES2);
	STRING_COMPARE_RETURN(str, MS_ZRTP_CIPHER_AES3);
	STRING_COMPARE_RETURN(str, MS_ZRTP_CIPHER_2FS1);
	STRING_COMPARE_RETURN(str, MS_ZRTP_CIPHER_2FS2);
	STRING_COMPARE_RETURN(str, MS_ZRTP_CIPHER_2FS3);
	return MS_ZRTP_CIPHER_INVALID;
}

MS2_PUBLIC const char* ms_zrtp_cipher_to_string(const MSZrtpCipher cipher) {
	SWITCH_CRYPTO_ALGO(cipher,\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_INVALID);\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_AES1);\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_AES2);\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_AES3);\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_2FS1);\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_2FS2);\
		CASE_RETURN_STRING(MS_ZRTP_CIPHER_2FS3);\
	);
}
849

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874

MS2_PUBLIC MSZrtpAuthTag ms_zrtp_auth_tag_from_string(const char* str) {
	STRING_COMPARE_RETURN(str, MS_ZRTP_AUTHTAG_HS32);
	STRING_COMPARE_RETURN(str, MS_ZRTP_AUTHTAG_HS80);
	STRING_COMPARE_RETURN(str, MS_ZRTP_AUTHTAG_SK32);
	STRING_COMPARE_RETURN(str, MS_ZRTP_AUTHTAG_SK64);
	return MS_ZRTP_AUTHTAG_INVALID;
}

MS2_PUBLIC const char* ms_zrtp_auth_tag_to_string(const MSZrtpAuthTag authTag) {
	SWITCH_CRYPTO_ALGO(authTag,\
		CASE_RETURN_STRING(MS_ZRTP_AUTHTAG_INVALID);\
		CASE_RETURN_STRING(MS_ZRTP_AUTHTAG_HS32);\
		CASE_RETURN_STRING(MS_ZRTP_AUTHTAG_HS80);\
		CASE_RETURN_STRING(MS_ZRTP_AUTHTAG_SK32);\
		CASE_RETURN_STRING(MS_ZRTP_AUTHTAG_SK64);\
	);
}

MSZrtpKeyAgreement ms_zrtp_key_agreement_from_string(const char* str) {
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_DH2K);
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_DH3K);
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_EC25);
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_EC38);
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_EC52);
johan's avatar
johan committed
875 876
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_X255);
	STRING_COMPARE_RETURN(str, MS_ZRTP_KEY_AGREEMENT_X448);
877 878 879 880 881 882 883 884 885 886 887
	return MS_ZRTP_KEY_AGREEMENT_INVALID;
}

const char* ms_zrtp_key_agreement_to_string(const MSZrtpKeyAgreement keyAgreement) {
	SWITCH_CRYPTO_ALGO(keyAgreement,\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_INVALID);\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_DH2K);\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_DH3K);\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_EC25);\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_EC38);\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_EC52);\
johan's avatar
johan committed
888 889
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_X255);\
		CASE_RETURN_STRING(MS_ZRTP_KEY_AGREEMENT_X448);\
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
	);
}

MS2_PUBLIC MSZrtpSasType ms_zrtp_sas_type_from_string(const char* str) {
	STRING_COMPARE_RETURN(str, MS_ZRTP_SAS_B32);
	STRING_COMPARE_RETURN(str, MS_ZRTP_SAS_B256);
	return MS_ZRTP_SAS_INVALID;
}

MS2_PUBLIC const char* ms_zrtp_sas_type_to_string(const MSZrtpSasType sasType) {
	SWITCH_CRYPTO_ALGO(sasType,\
		CASE_RETURN_STRING(MS_ZRTP_SAS_INVALID);\
		CASE_RETURN_STRING(MS_ZRTP_SAS_B32);\
		CASE_RETURN_STRING(MS_ZRTP_SAS_B256);\
	);
}