Exemple #1
0
/*----------------------------------------------------------------------------*/
zrtp_status_t _zrtp_protocol_decrypt( zrtp_protocol_t *proto,
									  zrtp_rtp_info_t *packet,
									  uint8_t is_rtp)
{
	zrtp_status_t s = zrtp_status_ok;

	if (is_rtp) {
		s = zrtp_srtp_unprotect(proto->context->zrtp->srtp_global, proto->_srtp, packet);
	} else {
		s = zrtp_srtp_unprotect_rtcp(proto->context->zrtp->srtp_global, proto->_srtp, packet);
	}

	if (zrtp_status_ok != s) {
		ZRTP_UNALIGNED(zrtp_rtp_hdr_t) *hdr = (zrtp_rtp_hdr_t*) packet->packet;
		ZRTP_LOG(2,(_ZTU_,"ERROR! Decrypt failed. ID=%u:%s s=%s (%s size=%d ssrc=%u seq=%u/%u pt=%d)\n",
					    proto->context->id,
						zrtp_log_mode2str(proto->context->mode),
						zrtp_log_status2str(s),
						is_rtp ? "RTP" : "RTCP",
						*packet->length,
						zrtp_ntoh32(hdr->ssrc),
						zrtp_ntoh16(hdr->seq),
						packet->seq,
						hdr->pt));
    }

	return s;
}
/*----------------------------------------------------------------------------*/
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;
}
Exemple #3
0
static bool udp_helper_send(int *err, struct sa *dst,
			    struct mbuf *mb, void *arg)
{
	struct menc_media *st = arg;
	unsigned int length;
	zrtp_status_t s;
	const char *proto_name = "rtp";
	enum pkt_type ptype = get_packet_type(mb);

	if (drop_packets(st))
		return true;

	length = (unsigned int)mbuf_get_left(mb);

	/* only RTP/RTCP packets should be processed */
	if (ptype == PKT_TYPE_RTCP) {
		proto_name = "rtcp";
		s = zrtp_process_rtcp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else if (ptype == PKT_TYPE_RTP) {
		s = zrtp_process_rtp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else
		return false;

	if (s != zrtp_status_ok) {

		if (s == zrtp_status_drop)
			return true;

		warning("zrtp: send(port=%d): zrtp_process_%s failed"
			" (status = %d '%s')\n",
			sa_port(dst), proto_name, s, zrtp_log_status2str(s));
		return false;
	}

	/* make sure target buffer is large enough */
	if (length > mbuf_get_space(mb)) {
		warning("zrtp: zrtp_process_%s: length > space (%u > %u)\n",
			proto_name, length, mbuf_get_space(mb));
		*err = ENOMEM;
	}

	mb->end = mb->pos + length;

	return false;
}
Exemple #4
0
static bool udp_helper_recv(struct sa *src, struct mbuf *mb, void *arg)
{
	struct menc_media *st = arg;
	unsigned int length;
	zrtp_status_t s;
	const char *proto_name = "srtp";
	enum pkt_type ptype = get_packet_type(mb);

	if (drop_packets(st))
		return true;

	length = (unsigned int)mbuf_get_left(mb);

	if (ptype == PKT_TYPE_RTCP) {
		proto_name = "srtcp";
		s = zrtp_process_srtcp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else if (ptype == PKT_TYPE_RTP || ptype == PKT_TYPE_ZRTP) {
		s = zrtp_process_srtp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else
		return false;

	if (s != zrtp_status_ok) {

		if (s == zrtp_status_drop)
			return true;

		warning("zrtp: recv(port=%d): zrtp_process_%s: %d '%s'\n",
			sa_port(src), proto_name, s, zrtp_log_status2str(s));
		return false;
	}

	mb->end = mb->pos + length;

	return false;
}
Exemple #5
0
zrtp_status_t zrtp_init(zrtp_config_t* config, zrtp_global_t** zrtp)
{
    zrtp_global_t* new_zrtp;
    zrtp_status_t s = zrtp_status_ok;
	
	ZRTP_LOG(3, (_ZTU_,"INITIALIZING LIBZRTP...\n"));
	
	/* Print out configuration setting */
	zrtp_print_env_settings(config);
	
	new_zrtp = zrtp_sys_alloc(sizeof(zrtp_global_t));
	if (!new_zrtp) {
		return zrtp_status_alloc_fail;
    }	
	zrtp_memset(new_zrtp, 0, sizeof(zrtp_global_t));
		
	/*
	 * Apply configuration according to the config
	 */		
	new_zrtp->lic_mode = config->lic_mode;	
	new_zrtp->is_mitm = config->is_mitm;
	ZSTR_SET_EMPTY(new_zrtp->def_cache_path);
	zrtp_zstrcpy(ZSTR_GV(new_zrtp->def_cache_path), ZSTR_GV(config->def_cache_path));
	zrtp_memcpy(&new_zrtp->cb, &config->cb, sizeof(zrtp_callback_t));
	new_zrtp->cache_auto_store = config->cache_auto_store;
        
	ZSTR_SET_EMPTY(new_zrtp->client_id);
	zrtp_memset(new_zrtp->client_id.buffer, ' ', sizeof(zrtp_client_id_t));
	zrtp_zstrncpyc( ZSTR_GV(new_zrtp->client_id),
					(const char*)config->client_id,
					sizeof(zrtp_client_id_t));
	
    /*
	 * General Initialization
	 */
	init_mlist(&new_zrtp->sessions_head);
	
    zrtp_mutex_init(&new_zrtp->sessions_protector);   
	
    init_mlist(&new_zrtp->hash_head);
    init_mlist(&new_zrtp->cipher_head);
    init_mlist(&new_zrtp->atl_head);
    init_mlist(&new_zrtp->pktype_head);
    init_mlist(&new_zrtp->sas_head);

    /* Init RNG context */	
	s = zrtp_init_rng(new_zrtp);
    if (zrtp_status_ok != s) {
		ZRTP_LOG(1, (_ZTU_,"ERROR! zrtp_init_rng() failed:%s.\n", zrtp_log_status2str(s)));
		return zrtp_status_rng_fail;
	}
   	
	/* Initialize SRTP engine */
	s =  zrtp_srtp_init(new_zrtp);
	if (zrtp_status_ok != s) {
		ZRTP_LOG(1, (_ZTU_,"ERROR! zrtp_srtp_init() failed:<%s>\n", zrtp_log_status2str(s)));
		return zrtp_status_fail;
    }    

	if (new_zrtp->cb.cache_cb.on_init)  {
		s = new_zrtp->cb.cache_cb.on_init(new_zrtp);
		if (zrtp_status_ok != s) {
			ZRTP_LOG(1, (_ZTU_,"ERROR! cache on_init() callback failed <%s>\n", zrtp_log_status2str(s)));
			zrtp_srtp_down(new_zrtp);
			return zrtp_status_fail;
		}
	}
	
	if (new_zrtp->cb.sched_cb.on_init)  {
		s = new_zrtp->cb.sched_cb.on_init(new_zrtp);
		if (zrtp_status_ok != s) {
			ZRTP_LOG(1, (_ZTU_,"ERROR! scheduler on_init() callback failed <%s>\n", zrtp_log_status2str(s)));
			zrtp_srtp_down(new_zrtp);
			return zrtp_status_fail;
		}
	}
	
	/* Load default crypto-components */
    zrtp_prepare_pkt(new_zrtp);
    zrtp_defaults_sas(new_zrtp);
    zrtp_defaults_pkt(new_zrtp);
    zrtp_defaults_atl(new_zrtp);
    zrtp_defaults_aes_cipher(new_zrtp);
    zrtp_defaults_hash(new_zrtp);

	*zrtp = new_zrtp;
	
	ZRTP_LOG(3, (_ZTU_,"INITIALIZING LIBZRTP - DONE\n"));
    return  s;
}
Exemple #6
0
/*----------------------------------------------------------------------------*/
zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream)
{
    uint32_t i = 0;
	zrtp_status_t s = zrtp_status_fail;
    zrtp_stream_t* new_stream = NULL;	
    
	ZRTP_LOG(3, (_ZTU_,"ATTACH NEW STREAM to sID=%d:\n", session->id));
	
	/*
	 * Initialize first unused stream. If there are no available streams return error.
	 */
    zrtp_mutex_lock(session->streams_protector);
    for (i=0; i<ZRTP_MAX_STREAMS_PER_SESSION; i++) {
		if (ZRTP_STATE_NONE == session->streams[i].state) {
			new_stream = &session->streams[i];
			zrtp_memset(new_stream, 0, sizeof(zrtp_stream_t));
			break;
 		}
    }
	zrtp_mutex_unlock(session->streams_protector);

	if (!new_stream) {
		ZRTP_LOG(1, (_ZTU_,"\tWARNING! Can't attach one more stream. Limit is reached."
					 " Use #ZRTP_MAX_STREAMS_PER_SESSION. sID=%u\n", session->id));
		return zrtp_status_alloc_fail;
	}
	
	/*
	 * Initialize the private data stream with default initial values	 
	 */
	zrtp_mutex_init(&new_stream->stream_protector);
	_zrtp_change_state(new_stream, ZRTP_STATE_ACTIVE);
	new_stream->mode	= ZRTP_STREAM_MODE_CLEAR;
	new_stream->id		= session->zrtp->streams_count++;
	new_stream->session = session;
	new_stream->zrtp	= session->zrtp;
	new_stream->mitm_mode = ZRTP_MITM_MODE_UNKN;
	new_stream->is_hello_received = 0;
	
	ZSTR_SET_EMPTY(new_stream->cc.hmackey);
	ZSTR_SET_EMPTY(new_stream->cc.peer_hmackey);
	ZSTR_SET_EMPTY(new_stream->cc.zrtp_key);
	ZSTR_SET_EMPTY(new_stream->cc.peer_zrtp_key);

	new_stream->dh_cc.initialized_with	= ZRTP_COMP_UNKN;
	bnBegin(&new_stream->dh_cc.peer_pv);
	ZSTR_SET_EMPTY(new_stream->dh_cc.dhss);		
	
	ZRTP_LOG(3, (_ZTU_,"\tEmpty slot was found - initializing new stream with ID=%u.\n", new_stream->id));

	do {
	zrtp_string32_t hash_buff = ZSTR_INIT_EMPTY(hash_buff);
	zrtp_hash_t *hash = zrtp_comp_find(ZRTP_CC_HASH, ZRTP_HASH_SHA256, new_stream->zrtp);		
	s = zrtp_status_algo_fail;
		
	if (sizeof(uint16_t) !=  zrtp_randstr( new_stream->zrtp,
										  (uint8_t*)&new_stream->media_ctx.high_out_zrtp_seq,
										  sizeof(uint16_t))) {
		break;
	}	

	/*
	 * Compute and store message hashes to prevent DoS attacks.
	 * Generate H0 as a random nonce and compute H1, H2 and H3
	 * using the leftmost 128 bits from every hash.
	 * Then insert these directly into the message structures.
     */

	zrtp_memset(&new_stream->messages, 0, sizeof(new_stream->messages));
	ZSTR_SET_EMPTY(new_stream->messages.h0);
	ZSTR_SET_EMPTY(new_stream->messages.signaling_hash);

	/* Generate Random nonce, compute H1 and store in the DH packet */
	new_stream->messages.h0.length = (uint16_t)zrtp_randstr( new_stream->zrtp,
															 (unsigned char*)new_stream->messages.h0.buffer,
															 ZRTP_MESSAGE_HASH_SIZE);
	if (ZRTP_MESSAGE_HASH_SIZE != new_stream->messages.h0.length) {		
		break;
	}

	s = hash->hash(hash, ZSTR_GV(new_stream->messages.h0), ZSTR_GV(hash_buff));
	if (zrtp_status_ok != s) {
		break;
	}
	zrtp_memcpy(new_stream->messages.dhpart.hash, hash_buff.buffer, ZRTP_MESSAGE_HASH_SIZE);	

	/* Compute H2 for the Commit */		
	s = hash->hash_c(hash, (char*)new_stream->messages.dhpart.hash, ZRTP_MESSAGE_HASH_SIZE, ZSTR_GV(hash_buff));
	if (zrtp_status_ok != s) {
		break;
	}
	zrtp_memcpy(new_stream->messages.commit.hash, hash_buff.buffer, ZRTP_MESSAGE_HASH_SIZE);	

	/* Compute H3 for the Hello message */
	s = hash->hash_c(hash, (char*)new_stream->messages.commit.hash, ZRTP_MESSAGE_HASH_SIZE, ZSTR_GV(hash_buff));
	if (zrtp_status_ok != s) {
		break;
	}
	zrtp_memcpy(new_stream->messages.hello.hash, hash_buff.buffer, ZRTP_MESSAGE_HASH_SIZE);
	
	s = zrtp_status_ok;
	} while (0);
	
	if (zrtp_status_ok != s) {
		ZRTP_LOG(1, (_ZTU_,"\tERROR! Fail to compute messages hashes <%s>.\n", zrtp_log_status2str(s)));
		return s;
	}
	
    /*
	 * Preparing HELLO based on user's profile
	 */
	ZRTP_LOG(3, (_ZTU_,"\tPreparing ZRTP Hello according to the Session profile.\n"));
	{
	zrtp_packet_Hello_t* hello = &new_stream->messages.hello;	
	uint8_t i = 0;
	int8_t* comp_ptr = NULL;

	/* Set Protocol Version and ClientID */
	zrtp_memcpy(hello->version, ZRTP_PROTOCOL_VERSION, ZRTP_VERSION_SIZE);
	zrtp_memcpy(hello->cliend_id, session->zrtp->client_id.buffer, session->zrtp->client_id.length);
		
	/* Set flags. */
	hello->pasive	=  (ZRTP_LICENSE_MODE_PASSIVE == session->zrtp->lic_mode) ? 1 : 0;
	hello->uflag	= (ZRTP_LICENSE_MODE_UNLIMITED == session->zrtp->lic_mode) ? 1 : 0;
	hello->mitmflag = session->zrtp->is_mitm;	
	hello->sigflag	= 0;	
		
	zrtp_memcpy(hello->zid, session->zid.buffer, session->zid.length);
	
	comp_ptr = (int8_t*)hello->comp;
	i = 0;
	while ( session->profile.hash_schemes[i]) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_HASH, session->profile.hash_schemes[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->hc = i;	

	i = 0;
	while (session->profile.cipher_types[i]) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_CIPHER, session->profile.cipher_types[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->cc = i;

	i = 0;
	while (session->profile.auth_tag_lens[i] ) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_ATL, session->profile.auth_tag_lens[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->ac = i;

	i = 0;
	while (session->profile.pk_schemes[i] ) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_PKT, session->profile.pk_schemes[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->kc = i;

	i = 0;
	while (session->profile.sas_schemes[i]) {
		zrtp_memcpy( comp_ptr,
					zrtp_comp_id2type(ZRTP_CC_SAS, session->profile.sas_schemes[i++]),
					ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->sc = i;

	/*
	 * Hmac will appear at the end of the message, after the dynamic portion.
	 * i is the length of the dynamic part.
	 */	
	i = (hello->hc + hello->cc + hello->ac + hello->kc + hello->sc) * ZRTP_COMP_TYPE_SIZE;
	_zrtp_packet_fill_msg_hdr( new_stream,
							   ZRTP_HELLO,
							   ZRTP_HELLO_STATIC_SIZE + i + ZRTP_HMAC_SIZE,
							   &hello->hdr);
	}
	
	*stream = new_stream;
	
	ZRTP_LOG(3, (_ZTU_,"ATTACH NEW STREAM - DONE.\n"));
    return zrtp_status_ok;
}
Exemple #7
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;
}