/*----------------------------------------------------------------------------*/
static zrtp_status_t zrtp_dh_self_test(zrtp_pk_scheme_t *self)
{
	zrtp_status_t s = zrtp_status_ok;
	zrtp_dh_crypto_context_t alice_cc;
	zrtp_dh_crypto_context_t bob_cc;
	struct BigNum alice_k;
	struct BigNum bob_k;
	zrtp_time_t start_ts = zrtp_time_now();
	
	ZRTP_LOG(3, (_ZTU_, "PKS %.4s testing... ", self->base.type));
	
	bnBegin(&alice_k);
	bnBegin(&bob_k);
	
	do {	
		/* Both sides initalise DH schemes and compute secret and public values. */
		s = self->initialize(self, &alice_cc);
		if (zrtp_status_ok != s) {
			break;
		}
		s = self->initialize(self, &bob_cc);
		if (zrtp_status_ok != s) {
			break;
		}
		
		/* Both sides validate public values. (to provide exact performance estimation) */
		s = self->validate(self, &bob_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
		s = self->validate(self, &alice_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
		
		/* Compute secret keys and compare them. */
		s = self->compute(self, &alice_cc, &alice_k, &bob_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
		s= self->compute(self, &bob_cc, &bob_k, &alice_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
				
		s = (0 == bnCmp(&alice_k, &bob_k)) ? zrtp_status_ok : zrtp_status_algo_fail;
	} while (0);

	bnEnd(&alice_k);
	bnEnd(&bob_k);
		
	ZRTP_LOGC(3, ("%s (%llu ms)\n", zrtp_log_status2str(s), (zrtp_time_now()-start_ts)/2));
	
	return s;
}
static zrtp_status_t zrtp_dh_initialize( zrtp_pk_scheme_t *self,
										 zrtp_dh_crypto_context_t *dh_cc)
{
	unsigned char* buffer = zrtp_sys_alloc(sizeof(zrtp_uchar128_t));
	struct BigNum* p = _zrtp_get_p(self);
	zrtp_time_t start_ts = zrtp_time_now();
	
	ZRTP_LOG(1,(_ZTU_,"\tDH TEST: %.4s zrtp_dh_initialize() START. now=%llums.\n", self->base.type, start_ts));
	
	if (!buffer) {
		return zrtp_status_alloc_fail;
	}
	if (!p) {
		zrtp_sys_free(buffer);
		return zrtp_status_bad_param;
	}
	
	if (64 != zrtp_randstr(self->base.zrtp, buffer, 64)) {
		zrtp_sys_free(buffer);
		return zrtp_status_rng_fail;
	}

	bnBegin(&dh_cc->sv);
	bnInsertBigBytes(&dh_cc->sv, (const unsigned char *)buffer, 0, self->sv_length);
	bnBegin(&dh_cc->pv);
	bnExpMod(&dh_cc->pv, &self->base.zrtp->G, &dh_cc->sv, p);
	
	zrtp_sys_free(buffer);
	
	ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_dh_initialize() for %.4s was executed ts=%llums d=%llums.\n", self->base.type, zrtp_time_now(), zrtp_time_now()-start_ts));
	return zrtp_status_ok;
}
/*----------------------------------------------------------------------------*/
static zrtp_status_t zrtp_dh_compute( zrtp_pk_scheme_t *self,					      
									  zrtp_dh_crypto_context_t *dh_cc,
									  struct BigNum *dhresult,
									  struct BigNum *pv)
{
	struct BigNum* p = _zrtp_get_p(self);
	zrtp_time_t start_ts = zrtp_time_now();
	if (!p) {		
		return zrtp_status_bad_param;
	}
	
	ZRTP_LOG(1,(_ZTU_,"\tDH TEST: %.4s zrtp_dh_compute() START. now=%llums.\n", self->base.type, start_ts));
	
    bnExpMod(dhresult, pv, &dh_cc->sv, p);
	ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_dh_compute() for %.4s was executed ts=%llums d=%llums.\n", self->base.type, zrtp_time_now(), zrtp_time_now()-start_ts));
    return zrtp_status_ok;
}
Exemple #4
0
/*---------------------------------------------------------------------------*/
zrtp_status_t zrtp_register_with_trusted_mitm(zrtp_stream_t* stream)
{
	zrtp_session_t *session = stream->session;
	zrtp_status_t s = zrtp_status_bad_param;
	
	if (!stream) {
		return zrtp_status_bad_param;
	}
	
	ZRTP_LOG(3,(_ZTU_,"MARKING this call as REGISTRATION ID=%u\n", stream->id));
	
	if (NULL == stream->zrtp->cb.cache_cb.on_get_mitm) {
		ZRTP_LOG(2,(_ZTU_,"WARNING: Can't use MiTM Functions with no ZRTP Cache.\n"));
		return zrtp_status_notavailable;
	}
	
	if (!stream->protocol) {
		return zrtp_status_bad_param;
	}
	
	/* Passive Client endpoint should NOT generate PBX Secret. */
	if ((stream->mitm_mode == ZRTP_MITM_MODE_REG_CLIENT) &&
		(ZRTP_LICENSE_MODE_PASSIVE == stream->zrtp->lic_mode)) {
		ZRTP_LOG(2,(_ZTU_,"WARNING: Passive Client endpoint should NOT generate PBX Secret.\n"));
		return zrtp_status_bad_param;
	}

	/*
	 * Generate new MitM cache:
	 * pbxsecret = KDF(ZRTPSess, "Trusted MiTM key", (ZIDi | ZIDr), negotiated hash length)
	 */
	if ( (stream->state == ZRTP_STATE_SECURE) &&
		 ((stream->mitm_mode == ZRTP_MITM_MODE_REG_CLIENT) || (stream->mitm_mode == ZRTP_MITM_MODE_REG_SERVER)) )
	{
		zrtp_string32_t kdf_context = ZSTR_INIT_EMPTY(kdf_context);
		static const zrtp_string32_t trusted_mitm_key_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_TRUSTMITMKEY_STR);
		zrtp_string16_t *zidi, *zidr;
		
		if (stream->protocol->type == ZRTP_STATEMACHINE_INITIATOR) {
			zidi = &session->zid;
			zidr = &session->peer_zid;
		} else {
			zidi = &session->peer_zid;
			zidr = &session->zid;
		}
				
		zrtp_zstrcat(ZSTR_GV(kdf_context), ZSTR_GVP(zidi));
		zrtp_zstrcat(ZSTR_GV(kdf_context), ZSTR_GVP(zidr));
		
		_zrtp_kdf( stream,
				   ZSTR_GV(session->zrtpsess),
				   ZSTR_GV(trusted_mitm_key_label),
				   ZSTR_GV(kdf_context),
				   ZRTP_HASH_SIZE,
				   ZSTR_GV(session->secrets.pbxs->value));
		
		session->secrets.pbxs->_cachedflag = 1;
		session->secrets.pbxs->lastused_at = (uint32_t)(zrtp_time_now()/1000);
		session->secrets.cached |= ZRTP_BIT_PBX;
		session->secrets.matches |= ZRTP_BIT_PBX;

		s = zrtp_status_ok;
		if (session->zrtp->cb.cache_cb.on_put_mitm) {		
			s = session->zrtp->cb.cache_cb.on_put_mitm( ZSTR_GV(session->zid),								  
														ZSTR_GV(session->peer_zid),
														session->secrets.pbxs);
		}
		
		ZRTP_LOG(3,(_ZTU_,"Makring this call as REGISTRATION - DONE\n"));
	}

	return s;
}
Exemple #5
0
/*---------------------------------------------------------------------------*/
zrtp_status_t _zrtp_machine_enter_secure(zrtp_stream_t* stream)
{
	/*
     * When switching to SECURE all ZRTP crypto values were already computed by
	 * state-machine. Then we need to have logic to manage SAS value and shared
	 * secrets only. So: we compute SAS, refresh secrets flags and save the
	 * secrets to the cache after RS2 and RS1 swapping.  We don't need any
	 * crypto sources any longer - destroy them.
     */

	zrtp_status_t s				= zrtp_status_ok;
	zrtp_proto_crypto_t* cc		= stream->protocol->cc;
	zrtp_session_t *session		= stream->session;
	zrtp_secrets_t *secrets		= &stream->session->secrets;
	uint8_t was_exp   = 0;
	uint64_t exp_date = 0;

	ZRTP_LOG(3,(_ZTU_,"\tEnter state SECURE (%s).\n", zrtp_log_mode2str(stream->mode)));

	_zrtp_cancel_send_packet_later(stream, ZRTP_NONE);

	/*
	 * Compute the SAS value if it isn't computed yet. If there are several
	 * streams running in parallel - stream with the biggest hvi should
	 * generate the SAS.
	 */
	if (!session->sas1.length) {
		s = session->sasscheme->compute(session->sasscheme, stream, session->hash, 0);
		if (zrtp_status_ok != s) {
			_zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1);
			return s;
		}


		ZRTP_LOG(3,(_ZTU_,"\tThis is the very first stream in sID GENERATING SAS value.\n", session->id));
		ZRTP_LOG(3,(_ZTU_,"\tSAS computed: <%.16s> <%.16s>.\n", session->sas1.buffer, session->sas2.buffer));
	}

	/*
	 * Compute a new value for RS1 and store the prevoious one.
	 * Compute result secrets' flags.
	 */
	if (ZRTP_IS_STREAM_DH(stream))
	{
		ZRTP_LOG(3,(_ZTU_,"\tCheck expiration interval: last_use=%u ttl=%u new_ttl=%u exp=%u now=%u\n",
					secrets->rs1->lastused_at,
					secrets->rs1->ttl,
					stream->cache_ttl,
					(secrets->rs1->lastused_at + secrets->rs1->ttl),
					zrtp_time_now()/1000));
		
		if (secrets->rs1->ttl != 0xFFFFFFFF) {
			exp_date = secrets->rs1->lastused_at;
			exp_date += secrets->rs1->ttl;						
			
			if (ZRTP_IS_STREAM_DH(stream) && (exp_date < zrtp_time_now()/1000)) {
				ZRTP_LOG(3,(_ZTU_,"\tUsing EXPIRED secrets: last_use=%u ttl=%u exp=%u now=%u\n",
								secrets->rs1->lastused_at,
								secrets->rs1->ttl,
								(secrets->rs1->lastused_at + secrets->rs1->ttl),
								zrtp_time_now()/1000));
				was_exp = 1;
			}
		}
		
		if (!was_exp) {
			secrets->wrongs = secrets->matches ^ secrets->cached;
			secrets->wrongs &= ~ZRTP_BIT_RS2;
			secrets->wrongs &= ~ZRTP_BIT_PBX;
		}
	}
	
	/*
	 * We going to update RS1 and change appropriate secrets flags. Let's back-up current values.
	 * Back-upped values could be used in debug purposes and in the GUI to reflect current state of the call
	 */
	if (!ZRTP_IS_STREAM_MULT(stream)) {
		secrets->cached_curr = secrets->cached;
		secrets->matches_curr = secrets->matches;
		secrets->wrongs_curr = secrets->wrongs;
	}
	
	
	ZRTP_LOG(3,(_ZTU_,"\tFlags C=%x M=%x W=%x ID=%u\n",
				secrets->cached, secrets->matches, secrets->wrongs, stream->id));

	_zrtp_change_state(stream, ZRTP_STATE_SECURE);
	/*
	 * Alarm user if the following condition is TRUE for both RS1 and RS2:
	 * "secret is wrong if it has been restored from the cache but hasn't matched
	 * with the remote one".
	 */	
	if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) {
		session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_SECURE);
	}
	if (session->zrtp->cb.event_cb.on_zrtp_secure) {
		session->zrtp->cb.event_cb.on_zrtp_secure(stream);
	}
	
	/* Alarm user if possible MiTM attack detected */
	if (secrets->wrongs) {
		session->mitm_alert_detected = 1;
		
		if (session->zrtp->cb.event_cb.on_zrtp_security_event) {
			session->zrtp->cb.event_cb.on_zrtp_security_event(stream, ZRTP_EVENT_MITM_WARNING);
		}
	}

	/* Check for unenrollemnt first */
	if ((secrets->cached & ZRTP_BIT_PBX) && !(secrets->matches & ZRTP_BIT_PBX)) {
		ZRTP_LOG(2,(_ZTU_,"\tINFO! The user requires new un-enrolment - the nedpint may clear"
					" the cache or perform other action. ID=%u\n", stream->id));

		if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) {
			session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_USER_UNENROLLED);
		}
	}

    /*
	 * Handle PBX registration, if required: If PBX already had a shared secret
	 * for the ZID it leaves the cache entry unmodified. Else, it computes a new
	 * one. If the PBX detects cache entry for the static shared secret, but the
	 * phone does not have a matching cache entry - the PBX generates a new one.
	 */
	if (ZRTP_MITM_MODE_REG_SERVER == stream->mitm_mode)
	{
		if (secrets->matches & ZRTP_BIT_PBX) {
			ZRTP_LOG(2,(_ZTU_,"\tINFO! User have been already registered - skip enrollment ritual. ID=%u\n", stream->id));
			if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) {
				session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_USER_ALREADY_ENROLLED);
			}
		} else {			
			ZRTP_LOG(2,(_ZTU_,"\tINFO! The user requires new enrolment - generate new MiTM secret. ID=%u\n", stream->id));
			zrtp_register_with_trusted_mitm(stream);
			if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) {
				stream->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_NEW_USER_ENROLLED);
			}
			
		}		
	}
	else if (ZRTP_MITM_MODE_REG_CLIENT == stream->mitm_mode)
	{
		if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) {
			session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_CLIENT_ENROLLMENT);
		}
	}	

	/*
	 * Compute new RS for FULL DH streams only. Don't update RS1 if cache TTL is 0
	 */
	if (ZRTP_IS_STREAM_DH(stream))
	{
		static const zrtp_string32_t rss_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_RS_STR);
		
		if (stream->cache_ttl > 0) {			
			/* Replace RS2 with RS1 */
			zrtp_sys_free(secrets->rs2);
			secrets->rs2 = secrets->rs1;

			secrets->rs1 = _zrtp_alloc_shared_secret(session);
			if (!secrets->rs1) {
				_zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1);
				return zrtp_status_fail;
			}

			/*
			 * Compute new RS1 based on previous one and S0:
			 * rs1 = KDF(s0, "retained secret", KDF_Context, negotiated hash length)
			 */
			_zrtp_kdf( stream,
					   ZSTR_GV(cc->s0),
					   ZSTR_GV(rss_label),
					   ZSTR_GV(cc->kdf_context),
					   ZRTP_HASH_SIZE,
					   ZSTR_GV(secrets->rs1->value));

			/*
			 * Mark secrets as cached: RS1 have been just generated and cached;
			 * RS2 is cached if previous secret was cached as well.
			 */
			secrets->rs1->_cachedflag = 1;
			secrets->cached |= ZRTP_BIT_RS1;
			secrets->matches |= ZRTP_BIT_RS1;
			if (secrets->rs2->_cachedflag) {
				secrets->cached |= ZRTP_BIT_RS2;
			}

			/* Let's update the TTL interval for the new secret */
			secrets->rs1->ttl = stream->cache_ttl;
			secrets->rs1->lastused_at = (uint32_t)(zrtp_time_now()/1000);

			/* If possible MiTM attach detected - postpone storing the cache until after the user verify the SAS */
			if (!session->mitm_alert_detected) {
				zrtp_cache_put(session->zrtp->cache, ZSTR_GV(session->peer_zid), secrets->rs1);
			}

			{
			uint32_t verifiedflag = 0;
			char buff[128];
			zrtp_cache_get_verified(session->zrtp->cache, ZSTR_GV(session->peer_zid), &verifiedflag);

			ZRTP_LOG(3,(_ZTU_,"\tNew secret was generated:\n"));
			ZRTP_LOG(3,(_ZTU_,"\t\tRS1 value:<%s>\n",
						hex2str(secrets->rs1->value.buffer, secrets->rs1->value.length, buff, sizeof(buff))));
			ZRTP_LOG(3,(_ZTU_,"\t\tTTL=%u, flags C=%x M=%x W=%x V=%d\n",
						secrets->rs1->ttl, secrets->cached, secrets->matches, secrets->wrongs, verifiedflag));
			}
		} /* for TTL > 0 only */
		else {
			secrets->rs1->ttl = 0;
			zrtp_cache_put(session->zrtp->cache, ZSTR_GV(session->peer_zid), secrets->rs1);
		}
	} /* For DH mode only */

	
	if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) {
		session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_SECURE_DONE);
	}	

	/* We have computed all subkeys from S0 and don't need it any longer. */
	zrtp_wipe_zstring(ZSTR_GV(cc->s0));

	/* Clear DH crypto context */
	if (ZRTP_IS_STREAM_DH(stream)) {
		bnEnd(&stream->dh_cc.peer_pv);
		bnEnd(&stream->dh_cc.pv);
		bnEnd(&stream->dh_cc.sv);
		zrtp_wipe_zstring(ZSTR_GV(stream->dh_cc.dhss));
	}
	
	/*
	 * Now, let's check if the transition to CLEAR was caused by Active/Passive rules.
	 * If local endpoint is a MitM and peer MiTM linked stream is Unlimited, we
	 * could break the rules and send commit to Passive endpoint.
	 */
	if (stream->zrtp->is_mitm && stream->peer_super_flag) {
		if (stream->linked_mitm && stream->linked_mitm->peer_passive) {
			if (stream->linked_mitm->state == ZRTP_STATE_CLEAR) {
				ZRTP_LOG(2,(_ZTU_,"INFO: Linked Peer stream id=%u suspended in CLEAR-state due to"
							" Active/Passive restrictions, but we are running in MiTM mode and "
							"current peer endpoint is Super-Active. Let's Go Secure for the linked stream.\n", stream->id));
				
				/* @note: don't use zrtp_secure_stream() wrapper as it checks for Active/Passive stuff. */
				_zrtp_machine_start_initiating_secure(stream->linked_mitm);
			}
		}
	}
	
	/*
	 * Increase calls counter for Preshared mode and reset it on DH
	 */
	uint32_t calls_counter = 0;
	zrtp_cache_get_presh_counter(session->zrtp->cache, ZSTR_GV(session->peer_zid), &calls_counter);
	if (ZRTP_IS_STREAM_DH(stream)) {
		zrtp_cache_set_presh_counter(session->zrtp->cache, ZSTR_GV(session->peer_zid), 0);
	} else if ZRTP_IS_STREAM_PRESH(stream) {
		zrtp_cache_set_presh_counter(session->zrtp->cache, ZSTR_GV(session->peer_zid), ++calls_counter);
	}
	
	clear_crypto_sources(stream);

	return zrtp_status_ok;
}
Exemple #6
0
void *process_outgoing(void *param)
#endif
{
	unsigned packets_counter = 0;
	zrtp_endpoint_t *the_endpoint = (zrtp_endpoint_t *)param;

	while (the_endpoint->is_running) {
		zrtp_test_stream_t* stream = NULL;
		unsigned i;

		zrtp_status_t s = zrtp_status_fail;
		zrtp_test_packet_t* packet;
		zrtp_queue_elem_t* elem;
		char* word = NULL;

		zrtp_sleep(K_ZRTP_TEST_RTP_RATE);

		/* Get random channel to operate with and select random peer */
		stream = get_stream_to_process_(the_endpoint);
		if (!stream) {
			continue;
		}

		elem = zrtp_sys_alloc(sizeof(zrtp_queue_elem_t));
		if (!elem) {
			break;
		}
		packet = (zrtp_test_packet_t*) elem->data;
		packet->is_rtp = (packets_counter++ % 20); /* Every 20-th packet is RTCP */

		/*
		 * Construct RTP/RTCP Packet
		 */
		if (packet->is_rtp)
		{
			ZRTP_UNALIGNED(zrtp_rtp_hdr_t) *rtp_hdr = (zrtp_rtp_hdr_t*)packet->body;

			/* Fill RTP Header according to the specification */
			zrtp_memset(rtp_hdr, 0, sizeof(zrtp_rtp_hdr_t));
			rtp_hdr->version = 2;			/* Current RTP version 2 */
			rtp_hdr->pt = 0;				/* PCMU padding type */
			rtp_hdr->ssrc = zrtp_hton32(stream->id);		/* Use stream Identifier as it's SSRC */
			if (stream->seq >= 0xFFFF) {
				stream->seq = 0;
			}
			rtp_hdr->seq = zrtp_hton16(stream->seq++);
			rtp_hdr->ts = zrtp_hton32((uint32_t)(zrtp_time_now()/1000));

			/* Get RTP body from PGP words lists */
			word = (char*)(i ? hash_word_list_odd[packets_counter % 256] : hash_word_list_even[packets_counter % 256]);

			zrtp_memcpy(packet->body + sizeof(zrtp_rtp_hdr_t), word, (uint32_t)strlen(word));
			packet->length = sizeof(zrtp_rtp_hdr_t) + (uint32_t)strlen(word);

			/* Process RTP media with libzrtp */
			s = zrtp_process_rtp(stream->zrtp, packet->body, &packet->length);
		}
		else {
			ZRTP_UNALIGNED(zrtp_rtcp_hdr_t) *rtcp_hdr = (zrtp_rtcp_hdr_t*)packet->body;

			/* Fill RTCP Header according to the specification */
			rtcp_hdr->rc = 0;
			rtcp_hdr->version = 2;
			rtcp_hdr->ssrc = stream->id;

			/* Get RTP body from PGP words lists. Put RTCP marker at the beginning */
			zrtp_memcpy(packet->body + sizeof(zrtp_rtcp_hdr_t), "RTCP", 4);
			word = (char*)( i ? hash_word_list_odd[packets_counter % 256] : hash_word_list_even[packets_counter % 256]);

			zrtp_memcpy(packet->body + sizeof(zrtp_rtcp_hdr_t) + 4, word, (uint32_t)strlen(word));
			packet->length = sizeof(zrtp_rtcp_hdr_t) + (uint32_t)strlen(word) + 4;
			/* RTCP packets sould be 32 byes aligned */
			packet->length += (packet->length % 4) ? (4 - packet->length % 4) : 0;

			/* Process RTCP control with libzrtp */
			s = zrtp_process_rtcp(stream->zrtp, packet->body, &packet->length);
		}

		elem->size = packet->length;

		/* Handle zrtp_process_xxx() instructions */
		switch (s) {
		/* Put the packet to the queue ==> send packet to the other side pear */
		case zrtp_status_ok: {
			ZRTP_LOG(3, (_ZTU_,"Outgoing: (%s) [%p:ssrc=%u] OK. <%s%s> encrypted %d bytes.\n",
					zrtp_log_state2str(stream->zrtp->state), stream->zrtp, stream->id, packet->is_rtp ? "" : "RTCP", word, packet->length));
			zrtp_test_queue_push(stream->output, elem);
		} break;

		case zrtp_status_drop: {
			ZRTP_LOG(1, (_ZTU_,"Outgoing: (%s) [%p:ssrc=%u] DROPPED.\n",
					zrtp_log_state2str(stream->zrtp->state), stream->zrtp, stream->id));
		} break;

		case zrtp_status_fail: {
			ZRTP_LOG(1, (_ZTU_,"Outgoing: (%s) [%p:ssrc=%u] ENCRYPT FAILED.\n",
					zrtp_log_state2str(stream->zrtp->state), stream->zrtp, stream->id));
		}	break;

		default:
			break;
		}

		if (zrtp_status_ok != s) {
			zrtp_sys_free(packet);
		}
	}
#if   (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WINCE)
	return 0;
#else
	return NULL;
#endif
}