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;
}
zrtp_status_t zrtp_defaults_atl(zrtp_global_t* global_ctx)
{
    zrtp_auth_tag_length_t* atl32 = zrtp_sys_alloc(sizeof(zrtp_auth_tag_length_t));
    zrtp_auth_tag_length_t* atl80 = zrtp_sys_alloc(sizeof(zrtp_auth_tag_length_t));

	if (!atl32 || !atl80) {
		if(atl32) zrtp_sys_free(atl32);
		if(atl80) zrtp_sys_free(atl80);
		return zrtp_status_alloc_fail;
	}
    
    zrtp_memset(atl32, 0, sizeof(zrtp_auth_tag_length_t));
    zrtp_memcpy(atl32->base.type, ZRTP_HS32, ZRTP_COMP_TYPE_SIZE);
	atl32->base.id			= ZRTP_ATL_HS32;
    atl32->base.zrtp	= global_ctx;
    atl32->tag_length		= 4;
        
    zrtp_memset(atl80, 0, sizeof(zrtp_auth_tag_length_t));
    zrtp_memcpy(atl80->base.type, ZRTP_HS80, ZRTP_COMP_TYPE_SIZE);
	atl80->base.id			= ZRTP_ATL_HS80;
	atl80->base.zrtp	= global_ctx;
    atl80->tag_length		= 10;
    
    zrtp_comp_register(ZRTP_CC_ATL, atl32, global_ctx);
    zrtp_comp_register(ZRTP_CC_ATL, atl80, global_ctx);
    
    return zrtp_status_ok;
}
Example #3
0
/*----------------------------------------------------------------------------*/
zrtp_status_t zrtp_down(zrtp_global_t* zrtp)
{
	ZRTP_LOG(3, (_ZTU_,"DESTROYING LIBZRTP...\n"));
	
    if (!zrtp) {
		return zrtp_status_bad_param;
    }

    zrtp_comp_done(ZRTP_CC_HASH, zrtp);
    zrtp_comp_done(ZRTP_CC_SAS, zrtp);
    zrtp_comp_done(ZRTP_CC_CIPHER, zrtp);
    zrtp_comp_done(ZRTP_CC_PKT, zrtp);
    zrtp_comp_done(ZRTP_CC_ATL, zrtp);
    zrtp_done_pkt(zrtp);
    
    zrtp_mutex_destroy(zrtp->sessions_protector);	
	
	zrtp_srtp_down(zrtp);
	
	if (zrtp->cb.cache_cb.on_down) {
		zrtp->cb.cache_cb.on_down();
	}
	if (zrtp->cb.sched_cb.on_down) {
		zrtp->cb.sched_cb.on_down();
	}
	
	zrtp_down_rng(zrtp);

	zrtp_sys_free(zrtp);
	
	ZRTP_LOG(3, (_ZTU_,"DESTROYING LIBZRTP - DONE\n"));

    return zrtp_status_ok;
}
Example #4
0
/*----------------------------------------------------------------------------*/
static void clear_crypto_sources(zrtp_stream_t* stream)
{
	zrtp_protocol_t* proto = stream->protocol;
	if (proto && proto->cc) {
		zrtp_memset(proto->cc, 0, sizeof(zrtp_proto_crypto_t));
		zrtp_sys_free(proto->cc);
		proto->cc = 0;
	}
}
Example #5
0
/*----------------------------------------------------------------------------*/
void zrtp_session_down(zrtp_session_t *session)
{
	int i =0;
	
    if (!session) {
		return;
	}		

	/* Stop ZRTP engine and clear all crypto sources for every stream in the session. */
	zrtp_mutex_lock(session->streams_protector);
	for(i=0; i<ZRTP_MAX_STREAMS_PER_SESSION; i++) {
		zrtp_stream_t *the_stream = &session->streams[i]; 		
		zrtp_stream_stop(the_stream);
	}
	zrtp_mutex_unlock(session->streams_protector);

	/* Release memory allocated on initialization */
	if (session->secrets.rs1) {
		zrtp_sys_free(session->secrets.rs1);
	}
	if (session->secrets.rs2) {
		zrtp_sys_free(session->secrets.rs2);
	}
	if (session->secrets.auxs) {
		zrtp_sys_free(session->secrets.auxs);
	}
	if (session->secrets.pbxs) {
		zrtp_sys_free(session->secrets.pbxs);
	}

	/* We don't need the session key anymore - clear it */
	zrtp_wipe_zstring(ZSTR_GV(session->zrtpsess));

	/* Removing session from the global list */    
	zrtp_mutex_lock(session->zrtp->sessions_protector);
	mlist_del(&session->_mlist);
	zrtp_mutex_unlock(session->zrtp->sessions_protector);		
	
	zrtp_mutex_destroy(session->streams_protector);
	zrtp_mutex_destroy(session->init_protector);
	
	zrtp_sys_free(session);
}
Example #6
0
void _zrtp_protocol_destroy(zrtp_protocol_t *proto)
{
	/* Clear protocol crypto values, destroy SRTP unit, clear and release memory. */
	if (proto) {
		/* if protocol is being destroyed by exception, ->context may be NULL */
		if (proto->context) {
			_zrtp_cancel_send_packet_later(proto->context, ZRTP_NONE);
			if (proto->_srtp) {
				zrtp_srtp_destroy(proto->context->zrtp->srtp_global, proto->_srtp);
			}
		}

		clear_crypto_sources(proto->context);
		zrtp_memset(proto, 0, sizeof(zrtp_protocol_t));
		zrtp_sys_free(proto);
	}
}
Example #7
0
void
lbnMemFree(void *ptr, unsigned bytes)
{
	lbnMemWipe(ptr, bytes);
	zrtp_sys_free(ptr);
}
Example #8
0
/*----------------------------------------------------------------------------*/
zrtp_status_t zrtp_session_init( zrtp_global_t* zrtp,
								zrtp_profile_t* profile,
								zrtp_zid_t zid,
								zrtp_signaling_role_t role,
								zrtp_session_t **session)
{
    uint32_t i = 0;
	zrtp_status_t s = zrtp_status_fail;
	zrtp_session_t* new_session = NULL;
        
    if (!zrtp) {
    	return zrtp_status_bad_param;
    }
	
	new_session = zrtp_sys_alloc(sizeof(zrtp_session_t));
	if (!new_session) {
		return zrtp_status_alloc_fail;		
	}
    
    zrtp_memset(new_session, 0, sizeof(zrtp_session_t));
	new_session->id = zrtp->sessions_count++;
	
	{
		zrtp_uchar32_t buff;
		ZRTP_LOG(3, (_ZTU_,"START SESSION INITIALIZATION. sID=%u.\n", new_session->id));
		ZRTP_LOG(3, (_ZTU_,"ZID=%s.\n", hex2str((const char*)zid, sizeof(zrtp_uchar12_t), (char*)buff, sizeof(buff)) ));
	}
	
	do {	
	/*
	 * Apply profile for the stream context: set flags and prepare Hello packet.
	 * If profile structure isn't provided, generate default.
	 */	 
    if (!profile) {
		ZRTP_LOG(1, (_ZTU_,"Profile in NULL - loading default one.\n"));
		zrtp_profile_defaults(&new_session->profile, zrtp);		
    } else {
		ZRTP_LOG(1, (_ZTU_,"Loading User's profile:\n"));
		if (zrtp_status_ok != zrtp_profile_check(profile, zrtp)) {
			ZRTP_LOG(1, (_ZTU_,"ERROR! Can't apply wrong profile to the session sID=%u.\n", new_session->id));
			break;
		}
		
		/* Adjust user's settings: force SHA-384 hash for ECDH-384P */
		if (zrtp_profile_find(profile, ZRTP_CC_PKT, ZRTP_PKTYPE_EC384P) > 0) {
			ZRTP_LOG(3, (_ZTU_,"User wants ECDH384 - auto-adjust profile to use SHA-384.\n"));
			profile->hash_schemes[0] = ZRTP_HASH_SHA384;
			profile->hash_schemes[1] = ZRTP_HASH_SHA256;
			profile->hash_schemes[2] = 0;
		}		
		
		zrtp_memcpy(&new_session->profile, profile, sizeof(zrtp_profile_t));
		
		{
		int i;
		ZRTP_LOG(3, (_ZTU_,"   allowclear: %s\n", profile->allowclear?"ON":"OFF"));
		ZRTP_LOG(3, (_ZTU_,"   autosecure: %s\n", profile->autosecure?"ON":"OFF"));
		ZRTP_LOG(3, (_ZTU_," disclose_bit: %s\n", profile->disclose_bit?"ON":"OFF"));
		ZRTP_LOG(3, (_ZTU_," signal. role: %s\n", zrtp_log_sign_role2str(role)));	
		ZRTP_LOG(3, (_ZTU_,"          TTL: %u\n", profile->cache_ttl));
				
		ZRTP_LOG(3, (_ZTU_,"  SAS schemes: "));
		i=0;
		while (profile->sas_schemes[i]) {
			ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_SAS, profile->sas_schemes[i++])));
		}
		ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_,"     Ciphers: "));
		i=0;
		while (profile->cipher_types[i]) {
			ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_CIPHER, profile->cipher_types[i++])));
		}
		ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_,"   PK schemes: "));
		i=0;
		while (profile->pk_schemes[i]) {
			ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_PKT, profile->pk_schemes[i++])));
		}
		ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_,"          ATL: "));
		i=0;
		while (profile->auth_tag_lens[i]) {
			ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_ATL, profile->auth_tag_lens[i++])));
		}
		ZRTP_LOGC(3, ("\n")); ZRTP_LOG(1, (_ZTU_,"      Hashes: "));
		i=0;
		while (profile->hash_schemes[i]) {
			ZRTP_LOGC(3, ("%.4s ", zrtp_comp_id2type(ZRTP_CC_HASH, profile->hash_schemes[i++])));
		}
		ZRTP_LOGC(3, ("\n"));
		}
	}

	/* Set ZIDs */
	ZSTR_SET_EMPTY(new_session->zid);
    ZSTR_SET_EMPTY(new_session->peer_zid);
	zrtp_zstrncpyc(ZSTR_GV(new_session->zid), (const char*)zid, sizeof(zrtp_zid_t));	

	new_session->zrtp = zrtp;
	new_session->signaling_role = role;
	new_session->mitm_alert_detected = 0;

	/*
	 * Allocate memory for holding secrets and initialize with random values.
	 * Actual values will be written from the cache at the beginning of the protocol.
	 */
	new_session->secrets.rs1 = _zrtp_alloc_shared_secret(new_session);
	new_session->secrets.rs2 = _zrtp_alloc_shared_secret(new_session);	
	new_session->secrets.auxs = _zrtp_alloc_shared_secret(new_session);
	new_session->secrets.pbxs = _zrtp_alloc_shared_secret(new_session);

	if ( !new_session->secrets.rs1 || !new_session->secrets.rs2 ||
		 !new_session->secrets.auxs || !new_session->secrets.pbxs) {
		ZRTP_LOG(1, (_ZTU_,"ERROR! Can't allocate shared secrets sID=%u\n.", new_session->id));
		s = zrtp_status_alloc_fail;
		break;
	}

	/* Initialize SAS values */	
	ZSTR_SET_EMPTY(new_session->sas1);
	ZSTR_SET_EMPTY(new_session->sas2);
	ZSTR_SET_EMPTY(new_session->sasbin);
	ZSTR_SET_EMPTY(new_session->zrtpsess);
    
    /* Clear all stream structures */
    for (i=0; i<ZRTP_MAX_STREAMS_PER_SESSION ; i++) {
		new_session->streams[i].state		= ZRTP_STATE_NONE;
		new_session->streams[i].prev_state	= ZRTP_STATE_NONE;
		new_session->streams[i].mode		= ZRTP_STREAM_MODE_UNKN;
    }
        
    /* Initialize synchronization objects */
	s = zrtp_mutex_init(&new_session->streams_protector);
    if (zrtp_status_ok != s) {
		ZRTP_LOG(1, (_ZTU_,"ERROR! can't initialize Stream protector. sID=%u.\n", new_session->id));
		break;
	}	
	s = zrtp_mutex_init(&new_session->init_protector);
    if (zrtp_status_ok != s) {
		ZRTP_LOG(1, (_ZTU_,"ERROR! can't initialize Init protector. sID=%u.\n", new_session->id));
		break;
	}		
	
	s = zrtp_status_ok;
	} while (0);
	
	if (zrtp_status_ok != s) {
		zrtp_sys_free(new_session);
		return s;
	}

    /* Add new session to the global list */    
    zrtp_mutex_lock(zrtp->sessions_protector);
    mlist_add(&zrtp->sessions_head, &new_session->_mlist);
    zrtp_mutex_unlock(zrtp->sessions_protector);
    
	*session = new_session;
	
    ZRTP_LOG(3, (_ZTU_,"Session initialization - DONE. sID=%u.\n\n", new_session->id));

    return zrtp_status_ok;
}
Example #9
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;
}
Example #10
0
zrtp_status_t _zrtp_protocol_init(zrtp_stream_t *stream, uint8_t is_initiator, zrtp_protocol_t **protocol)
{
	zrtp_protocol_t	*new_proto = NULL;
	zrtp_status_t s = zrtp_status_ok;

	ZRTP_LOG(3,(_ZTU_,"\tInit %s Protocol ID=%u mode=%s...\n",
				is_initiator ? "INITIATOR's" : "RESPONDER's", stream->id, zrtp_log_mode2str(stream->mode)));

	/* Destroy previous protocol structure (Responder or Preshared) */
    if (*protocol) {
		_zrtp_protocol_destroy(*protocol);
		*protocol = NULL;
    }

	/* Allocate memory for all branching structures */
	do
	{
		new_proto = zrtp_sys_alloc(sizeof(zrtp_protocol_t));
		if (!new_proto) {
			s = zrtp_status_alloc_fail;
			break;
		}
		zrtp_memset(new_proto, 0, sizeof(zrtp_protocol_t));

		new_proto->cc = zrtp_sys_alloc(sizeof(zrtp_proto_crypto_t));
		if (!new_proto->cc) {
			s = zrtp_status_alloc_fail;
			break;
		}
		zrtp_memset(new_proto->cc, 0, sizeof(zrtp_proto_crypto_t));

		/* Create and Initialize DH crypto context	(for DH streams only) */
		if (ZRTP_IS_STREAM_DH(stream)) {
			if (stream->dh_cc.initialized_with != stream->pubkeyscheme->base.id) {				
				stream->pubkeyscheme->initialize(stream->pubkeyscheme, &stream->dh_cc);
				stream->dh_cc.initialized_with = stream->pubkeyscheme->base.id;
			}
		}

		/* Initialize main structure at first: functions pointers and generate nonce */
		new_proto->type		= is_initiator ? ZRTP_STATEMACHINE_INITIATOR : ZRTP_STATEMACHINE_RESPONDER;
		new_proto->context = stream;

		/* Initialize protocol crypto context and prepare it for further usage */
		ZSTR_SET_EMPTY(new_proto->cc->kdf_context);
		ZSTR_SET_EMPTY(new_proto->cc->s0);
		ZSTR_SET_EMPTY(new_proto->cc->mes_hash);
		ZSTR_SET_EMPTY(new_proto->cc->hv);
		ZSTR_SET_EMPTY(new_proto->cc->peer_hv);

		if (ZRTP_IS_STREAM_DH(stream)) {
			_attach_secret(stream->session, &new_proto->cc->rs1, stream->session->secrets.rs1, is_initiator);
			_attach_secret(stream->session, &new_proto->cc->rs2, stream->session->secrets.rs2, is_initiator);		
			_attach_secret(stream->session, &new_proto->cc->auxs, stream->session->secrets.auxs, is_initiator);
			_attach_secret(stream->session, &new_proto->cc->pbxs, stream->session->secrets.pbxs, is_initiator);
		}
		
		s = zrtp_status_ok;
		*protocol = new_proto;
	} while (0);

	if (s != zrtp_status_ok) {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! _zrtp_protocol_attach() with code %s.\n", zrtp_log_status2str(s)));
		if (new_proto && new_proto->cc) {
			zrtp_sys_free(new_proto->cc);
		}
		if (new_proto) {
			zrtp_sys_free(new_proto);
		}
		*protocol = NULL;
	}

    return s;
}
Example #11
0
/*---------------------------------------------------------------------------*/
static zrtp_status_t _derive_s0(zrtp_stream_t* stream, int is_initiator)
{
	static const zrtp_string32_t zrtp_kdf_label	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_KDF_STR);
	static const zrtp_string32_t zrtp_sess_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_SESS_STR);
	static const zrtp_string32_t zrtp_multi_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_MULTI_STR);
	static const zrtp_string32_t zrtp_presh_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_PRESH_STR);
	
	zrtp_session_t *session = stream->session;
	zrtp_secrets_t* secrets  = &session->secrets;
	zrtp_proto_crypto_t* cc  = stream->protocol->cc;
	void* hash_ctx = NULL;
	char print_buff[256];

	switch (stream->mode)
	{
	/*
	 * S0 computing for FULL DH exchange	 
	 * S0 computing.  s0 is the master shared secret used for all
	 * cryptographic operations.  In particular, note the inclusion
	 * of "total_hash", a hash of all packets exchanged up to this
	 * point.  This belatedly detects any tampering with earlier
	 * packets, e.g. bid-down attacks.
	 *
	 * s0 = hash( 1 | DHResult | "ZRTP-HMAC-KDF" | ZIDi | ZIDr |
	 *                        total_hash | len(s1) | s1 | len(s2) | s2 | len(s3) | s3 )
	 * The constant 1 and all lengths are 32 bits big-endian values.
	 * The fields without length prefixes are fixed-witdh:
	 * - DHresult is fixed to the width of the DH prime.
	 * - The hash type string and ZIDs are fixed width.
	 * - total_hash is fixed by the hash negotiation.
	 * The constant 1 is per NIST SP 800-56A section 5.8.1, and is
	 * a counter which can be incremented to generate more than 256
	 * bits of key material.
	 * ========================================================================
	 */
	case ZRTP_STREAM_MODE_DH:
	{
		zrtp_proto_secret_t *C[3] = { 0, 0, 0};
		int i = 0;
		uint32_t comp_length = 0;
		zrtp_stringn_t *zidi = NULL, *zidr = NULL;
		struct BigNum dhresult;
#if (defined(ZRTP_USE_STACK_MINIM) && (ZRTP_USE_STACK_MINIM == 1))
		zrtp_uchar1024_t* buffer = zrtp_sys_alloc( sizeof(zrtp_uchar1024_t) );
		if (!buffer) {
			return zrtp_status_alloc_fail;
		}
#else
		zrtp_uchar1024_t holder;
		zrtp_uchar1024_t* buffer = &holder;
#endif

		ZRTP_LOG(3,(_ZTU_,"\tDERIVE S0 from DH exchange and RS secrets...\n"));
		ZRTP_LOG(3,(_ZTU_,"\t       my rs1ID:%s\n", hex2str(cc->rs1.id.buffer, cc->rs1.id.length, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t      his rs1ID:%s\n", hex2str((const char*)stream->messages.peer_dhpart.rs1ID, ZRTP_RSID_SIZE, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t his rs1ID comp:%s\n", hex2str(cc->rs1.peer_id.buffer, cc->rs1.peer_id.length, print_buff, sizeof(print_buff))));

		ZRTP_LOG(3,(_ZTU_,"\t       my rs2ID:%s\n", hex2str(cc->rs2.id.buffer, cc->rs2.id.length, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t      his rs2ID:%s\n", hex2str((const char*)stream->messages.peer_dhpart.rs2ID, ZRTP_RSID_SIZE, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t his rs2ID comp:%s\n", hex2str(cc->rs2.peer_id.buffer, cc->rs2.peer_id.length, print_buff, sizeof(print_buff))));

		ZRTP_LOG(3,(_ZTU_,"\t      my pbxsID:%s\n", hex2str(cc->pbxs.id.buffer, cc->pbxs.id.length, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t     his pbxsID:%s\n", hex2str((const char*)stream->messages.peer_dhpart.pbxsID, ZRTP_RSID_SIZE, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\this pbxsID comp:%s\n", hex2str(cc->pbxs.peer_id.buffer, cc->pbxs.peer_id.length, print_buff, sizeof(print_buff))));

		hash_ctx = session->hash->hash_begin(session->hash);
		if (0 == hash_ctx) {
			ZRTP_LOG(1,(_ZTU_, "\tERROR! can't start hash calculation for S0 computing. ID=%u.\n", stream->id));
			return zrtp_status_fail;
		}

		/*
		 * NIST requires a 32-bit big-endian integer counter to be included
		 * in the hash each time the hash is computed, which we have set to
		 * the fixed value of 1, because we only compute the hash once.
		 */
		comp_length = zrtp_hton32(1L);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&comp_length, 4);

		
		switch (stream->pubkeyscheme->base.id) {
			case ZRTP_PKTYPE_DH2048:
			case ZRTP_PKTYPE_DH3072:
			case ZRTP_PKTYPE_DH4096:
				comp_length = stream->pubkeyscheme->pv_length;
				ZRTP_LOG(3,(_ZTU_,"DH comp_length=%u\n", comp_length));
				break;
			case ZRTP_PKTYPE_EC256P:
			case ZRTP_PKTYPE_EC384P:
			case ZRTP_PKTYPE_EC521P:
				comp_length = stream->pubkeyscheme->pv_length/2;
				ZRTP_LOG(3,(_ZTU_,"ECDH comp_length=%u\n", comp_length));
				break;
			default:
				break;
		}
		
		bnBegin(&dhresult);
		stream->pubkeyscheme->compute(stream->pubkeyscheme,
									  &stream->dh_cc,
									  &dhresult,
									  &stream->dh_cc.peer_pv);
				
		bnExtractBigBytes(&dhresult, (uint8_t *)buffer, 0, comp_length);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)buffer, comp_length);
		bnEnd(&dhresult);

#if (defined(ZRTP_USE_STACK_MINIM) && (ZRTP_USE_STACK_MINIM == 1))
		zrtp_sys_free(buffer);
#endif
		
		/* Add "ZRTP-HMAC-KDF" to the S0 hash */		
		session->hash->hash_update( session->hash, hash_ctx,
									(const int8_t*)&zrtp_kdf_label.buffer,
									zrtp_kdf_label.length);

		/* Then Initiator's and Responder's ZIDs */
		if (stream->protocol->type == ZRTP_STATEMACHINE_INITIATOR) {
			zidi = ZSTR_GV(stream->session->zrtp->zid);
			zidr = ZSTR_GV(stream->session->peer_zid);
		} else {
			zidr = ZSTR_GV(stream->session->zrtp->zid);
			zidi = ZSTR_GV(stream->session->peer_zid);
		}
		
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&zidi->buffer, zidi->length);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&zidr->buffer, zidr->length);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&cc->mes_hash.buffer, cc->mes_hash.length);

		/* If everything is OK - RS1 should much */
		if (!zrtp_memcmp(cc->rs1.peer_id.buffer, stream->messages.peer_dhpart.rs1ID, ZRTP_RSID_SIZE))
		{
			C[0] = &cc->rs1;
			secrets->matches |= ZRTP_BIT_RS1;
		}
		/* If we have lost our RS1 - remote party should use backup (RS2) instead */
		else if (!zrtp_memcmp(cc->rs1.peer_id.buffer, stream->messages.peer_dhpart.rs2ID, ZRTP_RSID_SIZE))
		{
			C[0] = &cc->rs1;
			secrets->matches |= ZRTP_BIT_RS1;
			ZRTP_LOG(2,(_ZTU_,"\tINFO! We have lost our RS1 from previous broken exchange"
						" - remote party will use RS2 backup. ID=%u\n", stream->id));
		}
		/* If remote party lost it's secret - we will use backup */
		else if (!zrtp_memcmp(cc->rs2.peer_id.buffer, stream->messages.peer_dhpart.rs1ID, ZRTP_RSID_SIZE))
		{
			C[0] = &cc->rs2;
			cc->rs1 = cc->rs2;
			secrets->matches |= ZRTP_BIT_RS1;
			secrets->cached  |= ZRTP_BIT_RS1;
			ZRTP_LOG(2,(_ZTU_,"\tINFO! Remote party has lost it's RS1 - use RS2 backup. ID=%u\n", stream->id));
		}
		else
		{			
			secrets->matches &= ~ZRTP_BIT_RS1;

			zrtp_cache_set_verified(session->zrtp->cache, ZSTR_GV(session->peer_zid), 0);
			zrtp_cache_reset_secure_since(session->zrtp->cache, ZSTR_GV(session->peer_zid));

			ZRTP_LOG(2,(_ZTU_,"\tINFO! Our RS1 doesn't equal to other-side's one %s. ID=%u\n",
						cc->rs1.secret->_cachedflag ? " - drop verified!" : "", stream->id));
		}

		if (!zrtp_memcmp(cc->rs2.peer_id.buffer, stream->messages.peer_dhpart.rs2ID, ZRTP_RSID_SIZE)) {
			secrets->matches |= ZRTP_BIT_RS2;
			if (0 == C[0]) {
				C[0] = &cc->rs2;
			}
		}
		

		if (secrets->auxs &&
			(!zrtp_memcmp(stream->messages.peer_dhpart.auxsID, cc->auxs.peer_id.buffer, ZRTP_RSID_SIZE)) ) {
			C[1] =&cc->auxs;
	    	secrets->matches |= ZRTP_BIT_AUX;
		}

		if ( secrets->pbxs &&
			(!zrtp_memcmp(stream->messages.peer_dhpart.pbxsID, cc->pbxs.peer_id.buffer, ZRTP_RSID_SIZE)) ) {	
			C[2] = &cc->pbxs;
			secrets->matches |= ZRTP_BIT_PBX;
		}

		/* Finally hashing matched shared secrets */
		for (i=0; i<3; i++) {
			/*
			 * Some of the shared secrets s1 through s5 may have lengths of zero
			 * if they are null (not shared), and are each preceded by a 4-octet
			 * length field. For example, if s4 is null, len(s4) is 00 00 00 00,
			 * and s4 itself would be absent from the hash calculation, which
			 * means len(s5) would immediately follow len(s4).
			 */
			comp_length = C[i] ? zrtp_hton32(ZRTP_RS_SIZE) : 0;
			session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&comp_length, 4);
			if (C[i]) {
				session->hash->hash_update( session->hash,
											 hash_ctx,
											 (const int8_t*)C[i]->secret->value.buffer,
											 C[i]->secret->value.length );
				ZRTP_LOG(3,(_ZTU_,"\tUse S%d in calculations.\n", i+1));
			}
		}

		session->hash->hash_end(session->hash, hash_ctx, ZSTR_GV(cc->s0));
	} break; /* S0 for for DH and Preshared streams */

	/*
	 * Compute all possible combinations of preshared_key:
	 * hash(len(rs1) | rs1 | len(auxsecret) | auxsecret | len(pbxsecret) | pbxsecret)	 
	 * Find matched preshared_key and derive S0 from it:
	 * s0 = KDF(preshared_key, "ZRTP Stream Key", KDF_Context, negotiated hash length) 
	 *
	 * INFO: Take into account that RS1 and RS2 may be swapped.
	 * If no matched were found - generate DH commit.
	 * ========================================================================
	 */
	case ZRTP_STREAM_MODE_PRESHARED:
	{
		zrtp_status_t s				= zrtp_status_ok;
		zrtp_string32_t presh_key	= ZSTR_INIT_EMPTY(presh_key);		

		ZRTP_LOG(3,(_ZTU_,"\tDERIVE S0 for PRESHARED from cached secret. ID=%u\n", stream->id));

		/* Use the same hash as we used for Commitment */
		if (is_initiator)
		{
			s = _zrtp_compute_preshared_key( session,											 
											 ZSTR_GV(session->secrets.rs1->value),
											 (session->secrets.auxs->_cachedflag) ? ZSTR_GV(session->secrets.auxs->value) : NULL,
											 (session->secrets.pbxs->_cachedflag) ? ZSTR_GV(session->secrets.pbxs->value) : NULL,
											 ZSTR_GV(presh_key),
											 NULL);
			if (zrtp_status_ok != s) {
				return s;
			}
			
			secrets->matches |= ZRTP_BIT_RS1;
			if (session->secrets.auxs->_cachedflag) {				
				secrets->matches |= ZRTP_BIT_AUX;
			}
			if (session->secrets.pbxs->_cachedflag) {			
				secrets->matches |= ZRTP_BIT_PBX;
			}
		}
		/*
		 * Let's find appropriate hv key for Responder:
		 * <RS1, 0, 0>, <RS1, AUX, 0>, <RS1, 0, PBX>, <RS1, AUX, PBX>.
		 */
		else
		{
			int res=-1;
			char* peer_key_id		= (char*)stream->messages.peer_commit.hv+ZRTP_HV_NONCE_SIZE;
			zrtp_string8_t key_id	= ZSTR_INIT_EMPTY(key_id);
			
			do {
				/* RS1 MUST be available at this stage.*/
				s = _zrtp_compute_preshared_key( session,							 
												 ZSTR_GV(secrets->rs1->value),
												 NULL,
												 NULL,
												 ZSTR_GV(presh_key),
												 ZSTR_GV(key_id));
				if (zrtp_status_ok == s) {
					res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
					if (0 == res) {
						secrets->matches |= ZRTP_BIT_RS1;
						break;
					}
				}				
				
				if (session->secrets.pbxs->_cachedflag)
				{
					s = _zrtp_compute_preshared_key( session,											 
													 ZSTR_GV(secrets->rs1->value),
													 NULL,
													 ZSTR_GV(secrets->pbxs->value),
													 ZSTR_GV(presh_key),
													 ZSTR_GV(key_id));
					if (zrtp_status_ok == s) {
						res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
						if (0 == res) {
							secrets->matches |= ZRTP_BIT_PBX;
							break;
						}
					}
				}
				
				if (session->secrets.auxs->_cachedflag)
				{
					s = _zrtp_compute_preshared_key( session,													 
													 ZSTR_GV(secrets->rs1->value),
													 ZSTR_GV(secrets->auxs->value),
													 NULL,
													 ZSTR_GV(presh_key),
													 ZSTR_GV(key_id));
					if (zrtp_status_ok == s) {
						res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
						if (0 == res) {
							secrets->matches |= ZRTP_BIT_AUX;
							break;
						}
					}
				}
				
				if ((session->secrets.pbxs->_cachedflag) && (session->secrets.auxs->_cachedflag))
				{
					s = _zrtp_compute_preshared_key( session,													 
													 ZSTR_GV(secrets->rs1->value),
													 ZSTR_GV(secrets->auxs->value),
													 ZSTR_GV(secrets->pbxs->value),
													 ZSTR_GV(presh_key),
													 ZSTR_GV(key_id));
					if (zrtp_status_ok == s) {
						res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
						if (0 == res) {
							secrets->matches |= ZRTP_BIT_AUX;
							secrets->matches |= ZRTP_BIT_PBX;
							break;
						}
					}
				}
				
			} while (0);
			
			if (0 != res) {
				ZRTP_LOG(3,(_ZTU_,"\tINFO! Matched Key wasn't found - initate DH exchange.\n"));
				secrets->cached = 0;
				secrets->rs1->_cachedflag = 0;
				
				_zrtp_machine_start_initiating_secure(stream);
				return zrtp_status_ok;				
			}
		}
		
		ZRTP_LOG(3,(_ZTU_,"\tUse RS1, %s, %s in calculations.\n", 
					   (session->secrets.matches & ZRTP_BIT_AUX) ? "AUX" : "NULL",
					   (session->secrets.matches & ZRTP_BIT_PBX) ? "PBX" : "NULL"));		
		
		_zrtp_kdf( stream,
				   ZSTR_GV(presh_key),
				   ZSTR_GV(zrtp_presh_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   session->hash->digest_length,
				   ZSTR_GV(cc->s0));
	} break;

		
	/*
	 * For FAST Multistream:
	 * s0n = KDF(ZRTPSess, "ZRTP Multistream Key", KDF_Context, negotiated hash length) 
	 * ========================================================================
	 */
	case ZRTP_STREAM_MODE_MULT:
	{
		ZRTP_LOG(3,(_ZTU_,"\tDERIVE S0 for MULTISTREAM from ZRTP Session key... ID=%u\n", stream->id));
		_zrtp_kdf( stream,
				   ZSTR_GV(session->zrtpsess),
				   ZSTR_GV(zrtp_multi_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   session->hash->digest_length,
				   ZSTR_GV(cc->s0));
	} break;
		
	default: break;
	}
	
	
	/*
	 * Compute ZRTP session key for FULL streams only:
	 * ZRTPSess = KDF(s0, "ZRTP Session Key", KDF_Context, negotiated hash length)
	 */
	if (!ZRTP_IS_STREAM_MULT(stream)) {
		if (session->zrtpsess.length == 0) {
			_zrtp_kdf( stream,
					   ZSTR_GV(cc->s0),
					   ZSTR_GV(zrtp_sess_label),
					   ZSTR_GV(stream->protocol->cc->kdf_context),
					   session->hash->digest_length,
					   ZSTR_GV(session->zrtpsess));
		}
	}
	
	return zrtp_status_ok;
}
Example #12
0
/*----------------------------------------------------------------------------*/
static void zrtp_log(uint8_t is_clean, const char *sender, uint32_t level,  const char *format, va_list marker)
{ 	
#if (defined(ZRTP_USE_STACK_MINIM) && (ZRTP_USE_STACK_MINIM == 1))
	char *log_buffer = zrtp_sys_alloc(ZRTP_LOG_BUFFER_SIZE);
#else
	char log_buffer[ZRTP_LOG_BUFFER_SIZE];
#endif
	char* sline = log_buffer;
	uint32_t offset = 0;
	int len = 0;
	
	if (!sline) {
		return;
	}
	
	if (!is_clean) {
		/* Print sender with left aligment */	
		uint32_t sender_len = strlen(sender);
		*sline++ = ' ';
		*sline++ = '[';
		if (sender_len <= ZRTP_LOG_SENDER_MAX_LEN) {
			while (sender_len < ZRTP_LOG_SENDER_MAX_LEN) {
				*sline++ = ' ', ++sender_len;
			}
			while (*sender) {
				*sline++ = *sender++;
			}
		} else {
			int i = 0;
			for (i=0; i<ZRTP_LOG_SENDER_MAX_LEN; ++i) {
				*sline++ = *sender++;
			}
		}
		
		*sline++ = ']';
		*sline++ = ':';
		offset += 3 + ZRTP_LOG_SENDER_MAX_LEN;
			
		*sline++ = ' ';
		offset += 1; 
	}
	
	/* Print Message itself */
#if (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WIN64) || (ZRTP_PLATFORM == ZP_WINCE)
#	if (_MSC_VER >= 1400) && (ZRTP_PLATFORM != ZP_WINCE)
	len = _vsnprintf_s(sline, ZRTP_LOG_BUFFER_SIZE-offset-1, ZRTP_LOG_BUFFER_SIZE-offset-1, format, marker);
#	else
	len = _vsnprintf(sline, ZRTP_LOG_BUFFER_SIZE-offset, format, marker);
#	endif
#elif (ZRTP_PLATFORM == ZP_WIN32_KERNEL)
	RtlStringCchVPrintfA(sline, ZRTP_LOG_BUFFER_SIZE-offset, format, marker);
#elif (ZRTP_PLATFORM == ZP_LINUX) || (ZRTP_PLATFORM == ZP_DARWIN) || (ZRTP_PLATFORM == ZP_BSD) || (ZRTP_PLATFORM == ZP_ANDROID)
	len = vsnprintf(sline, ZRTP_LOG_BUFFER_SIZE-offset, format, marker);
#elif (ZRTP_PLATFORM == ZP_SYMBIAN)
	len = vsprintf(sline, format, marker);
#endif

	if ((len > 0) && log_writer) {
		(*log_writer)(level, log_buffer, len+offset, offset);
	}

#if (defined(ZRTP_USE_STACK_MINIM) && (ZRTP_USE_STACK_MINIM == 1))
	zrtp_sys_free(log_buffer);
#endif
}
zrtp_status_t zrtp_defaults_pkt(zrtp_global_t* zrtp)
{
	zrtp_pk_scheme_t* presh  = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
	zrtp_pk_scheme_t* dh2048 = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
    zrtp_pk_scheme_t* dh3072 = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
	zrtp_pk_scheme_t* multi  = zrtp_sys_alloc(sizeof(zrtp_pk_scheme_t));
    
	uint8_t P_2048_data[] =
	{
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
	0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
	0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
	0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
	0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
	0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
	0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
	0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
	0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
	0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
	0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
	0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
	0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
	0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
    };
	
    uint8_t P_3072_data[] =
    {		
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
	0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
	0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
	0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
	0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
	0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
	0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
	0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
	0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
	0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
	0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
	0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
	0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
	0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
	0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
	0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
	0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
	0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
	0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
	0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
	0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
	0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
    };

	if (!dh2048 || !dh3072 || !presh || !multi)	{
		if (presh) {
			zrtp_sys_free(presh);
		}
		if (dh2048) {
			zrtp_sys_free(dh2048);
		}
		if (dh3072) {
			zrtp_sys_free(dh3072);
		}
		if (multi) {
			zrtp_sys_free(multi);
		}
		return zrtp_status_alloc_fail;
	}
	    
    zrtp_memset(dh3072, 0, sizeof(zrtp_pk_scheme_t));
    zrtp_memcpy(dh3072->base.type, ZRTP_DH3K, ZRTP_COMP_TYPE_SIZE);
	dh3072->base.id		= ZRTP_PKTYPE_DH3072;
    dh3072->base.zrtp	= zrtp;
    dh3072->sv_length	= 256/8;
    dh3072->pv_length	= 384;
    dh3072->base.init 	= zrtp_dh_init;
    dh3072->base.free	= zrtp_dh_free;
    dh3072->initialize	= zrtp_dh_initialize;
    dh3072->compute		= zrtp_dh_compute;
    dh3072->validate	= zrtp_dh_validate;
	dh3072->self_test	= zrtp_dh_self_test;
	zrtp_memcpy(zrtp->P_3072_data, P_3072_data, sizeof(P_3072_data));
	zrtp_comp_register(ZRTP_CC_PKT, dh3072, zrtp);
		
	zrtp_memset(dh2048, 0, sizeof(zrtp_pk_scheme_t));
	zrtp_memcpy(dh2048->base.type, ZRTP_DH2K, ZRTP_COMP_TYPE_SIZE);
	dh2048->base.id		= ZRTP_PKTYPE_DH2048;
	dh2048->base.zrtp	= zrtp;
	dh2048->sv_length	= 256/8;
	dh2048->pv_length	= 256;
	dh2048->base.init 	= zrtp_dh_init;
	dh2048->base.free	= zrtp_dh_free;
	dh2048->initialize	= zrtp_dh_initialize;
	dh2048->compute		= zrtp_dh_compute;
	dh2048->validate	= zrtp_dh_validate;
	dh2048->self_test	= zrtp_dh_self_test;
	zrtp_memcpy(zrtp->P_2048_data, P_2048_data, sizeof(P_2048_data));
	zrtp_comp_register(ZRTP_CC_PKT, dh2048, zrtp);

	zrtp_memset(multi, 0, sizeof(zrtp_pk_scheme_t));
	zrtp_memcpy(multi->base.type, ZRTP_MULT, ZRTP_COMP_TYPE_SIZE);
	multi->base.id				= ZRTP_PKTYPE_MULT;
	zrtp_comp_register(ZRTP_CC_PKT, multi,  zrtp);

	zrtp_memset(presh, 0, sizeof(zrtp_pk_scheme_t));
	zrtp_memcpy(presh->base.type, ZRTP_PRESHARED, ZRTP_COMP_TYPE_SIZE);
	presh->base.id				= ZRTP_PKTYPE_PRESH;
	zrtp_comp_register(ZRTP_CC_PKT, presh,  zrtp);	
    
#if (defined(ZRTP_ENABLE_EC) && (ZRTP_ENABLE_EC == 1))
		return zrtp_defaults_ec_pkt(zrtp);
#else
		return zrtp_status_ok;
#endif
}
Example #14
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
}
Example #15
0
void *process_incoming(void *param)
#endif
{
	zrtp_endpoint_t *the_endpoint = (zrtp_endpoint_t *)param;

	while (the_endpoint->is_running) {
		zrtp_test_packet_t* packet = NULL;
		zrtp_queue_elem_t* elem = NULL;
		zrtp_status_t s = zrtp_status_fail;
		zrtp_test_stream_t *stream;
		int is_protocol = 0;

		// TODO: use peak to not to block processing if queue for this stream is empty
		elem = zrtp_test_queue_pop(the_endpoint->input_queue);
		if (!elem || elem->size <= 0) {
			if (elem) zrtp_sys_free(elem);
			break;
		}

		packet = (zrtp_test_packet_t*) elem->data;
		zrtp_test_id_t stream_id;
		{
			if (packet->is_rtp) {
				ZRTP_UNALIGNED(zrtp_rtp_hdr_t) *rtp_hdr = (zrtp_rtp_hdr_t*)packet->body;
				stream_id = zrtp_ntoh32(rtp_hdr->ssrc); /* remember, we use stream Id as it's RTP SSRC */
			} else {
				ZRTP_UNALIGNED(zrtp_rtcp_hdr_t) *rtcp_hdr = (zrtp_rtcp_hdr_t*)packet->body;
				stream_id = zrtp_ntoh32(rtcp_hdr->ssrc); /* remember, we use stream Id as it's RTP SSRC */
			}
			stream = zrtp_test_stream_by_peerid(stream_id);
		}

		/*
		 * Process incoming packet by libzrtp. Is this a RTP media packet - copy it to the buffer
		 * to print out later.
		 */
		if (packet->is_rtp) {
			s = zrtp_process_srtp(stream->zrtp, packet->body, &packet->length);
		} else {
			s = zrtp_process_srtcp(stream->zrtp, packet->body, &packet->length);
		}

		if (!is_protocol) {
			char *body;
			if (packet->is_rtp) {
				body = packet->body + sizeof(zrtp_rtp_hdr_t);
				body[packet->length - sizeof(zrtp_rtp_hdr_t)] = 0;
			} else {
				body = packet->body + sizeof(zrtp_rtcp_hdr_t);
				body[packet->length - sizeof(zrtp_rtcp_hdr_t)] = 0;
			}

			switch (s)
			{
			case zrtp_status_ok: {
				ZRTP_LOG(1, (_ZTU_,"Incoming: (%s) [%p:ssrc=%u] OK. <%s> decrypted %d bytes.\n",
						zrtp_log_state2str(stream->zrtp->state), stream->zrtp,  stream->id, body, packet->length));
			} break;

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

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

			default:
				break;
			}
		}

		zrtp_sys_free(elem);

		/*
		 * When zrtp_stream is in the pending clear state and other side wants to send plain
		 * traffic. We have to call zrtp_clear_stream().
		 */
		if (stream->zrtp->state == ZRTP_STATE_PENDINGCLEAR) {
			zrtp_stream_clear(stream->zrtp);
		}
	}
#if   (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WINCE)
	return 0;
#else
	return NULL;
#endif
}