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;
}
Example #2
0
zrtp_status_t zrtp_test_endpoint_create(zrtp_test_endpoint_cfg_t* cfg,
										const char *name,
										zrtp_test_id_t* id) {
	zrtp_status_t s;
	unsigned i;
	char cache_file_path[ZRTP_TEST_STR_LEN];
	zrtp_endpoint_t *new_endpoint;

	if (g_test_endpoints_count >= K_ZRTP_TEST_MAX_ENDPOINTS)
		return zrtp_status_alloc_fail;

	new_endpoint = &g_test_endpoints[g_test_endpoints_count++];
	zrtp_memset(new_endpoint, 0, sizeof(zrtp_endpoint_t));

	/* Copy configuration, we will use it later to clean up after ourselves */
	zrtp_memcpy(&new_endpoint->cfg, cfg, sizeof(zrtp_test_endpoint_cfg_t));

	/* Remember endpoint name */
	strcpy(new_endpoint->name, name);

	new_endpoint->id = g_endpoints_counter++;

	/* Adjust cache file path so each endpoint will use it's own file. */
	sprintf(cache_file_path, "./%s_cache.dat", name);
	zrtp_zstrcpyc(ZSTR_GV(new_endpoint->cfg.zrtp.def_cache_path), cache_file_path);

	/* Initialize libzrtp engine for this endpoint */
	s = zrtp_init(&new_endpoint->cfg.zrtp, &new_endpoint->zrtp);
	if (zrtp_status_ok == s) {
		*id = new_endpoint->id;

		/* Generate random ZID */
		zrtp_randstr(new_endpoint->zrtp, new_endpoint->zid, sizeof(new_endpoint->zid));
	}

	/* Create Input queue*/
	s = zrtp_test_queue_create(&new_endpoint->input_queue);
	if (zrtp_status_ok != s) {
		return s;
	}

	/* Start processing loop */
	new_endpoint->is_running = 1;

	for (i = 0; i<K_ZRTP_TEST_PROCESSORS_COUNT; i++) {
		if (0 != zrtp_thread_create(process_incoming, new_endpoint)) {
			return zrtp_status_fail;
		}

		if (cfg->generate_traffic) {
			if (0 != zrtp_thread_create(process_outgoing, new_endpoint)) {
				return zrtp_status_fail;
			}
		}
	}

	return s;
}
Example #3
0
static void init_random_map(uint8_t *map, int width, zrtp_global_t *zrtp) {
	int i;
	for(i=0; i<width; i++) {
		uint32_t rnd = 0;
		zrtp_randstr(zrtp, (uint8_t*)&rnd, sizeof(rnd));
		if(rnd%10 < 5) {
			zrtp_bitmap_set_bit(map, i);
		} else {
			zrtp_bitmap_clear_bit(map, i);
		}
	}
}
Example #4
0
static zrtp_test_stream_t *get_stream_to_process_(zrtp_endpoint_t *endpoint) {
	zrtp_test_id_t all_streams[K_ZRTP_TEST_MAX_SESSIONS_PER_ENDPOINT*ZRTP_MAX_STREAMS_PER_SESSION];
	unsigned streams_count = 0;
	unsigned i, j;

	for (i=0; i<endpoint->sessions_count; i++) {
		for (j=0; j<endpoint->sessions[i].streams_count; j++) {
			zrtp_test_stream_t *stream = &endpoint->sessions[i].streams[j];
			if (stream->input && stream->output)
				all_streams[streams_count++] = stream->id;
		}
	}

	if (0 == streams_count)
		return NULL;

	zrtp_randstr(endpoint->zrtp, (unsigned char*)&i, sizeof(i));
	j = (unsigned)i;
	j = j % streams_count;

	//printf("trace>>> CHOOSE stream Endpoint=%u IDX=%u ID=%u\n", endpoint->id,  j, all_streams[j]);
	return zrtp_test_stream_by_id(all_streams[j]);
}
Example #5
0
/*----------------------------------------------------------------------------*/
static zrtp_status_t _create_sasrelay( zrtp_stream_t *stream,
									   zrtp_sas_id_t transf_sas_scheme,
									   zrtp_string32_t* transf_sas_value,
									   uint8_t transf_ac_flag,
									   uint8_t transf_d_flag,
									   zrtp_packet_SASRelay_t* sasrelay )
{
	zrtp_session_t *session = stream->session;
	zrtp_status_t s = zrtp_status_fail;
	void* cipher_ctx = NULL;

	/* (padding + sig_len + flags) + SAS scheme and SASHash */
	const uint8_t encrypted_body_size = (2 + 1 + 1) + 4 + 32;

	zrtp_memset(sasrelay, 0, sizeof(zrtp_packet_SASRelay_t));

	/* generate a random initialization vector for CFB cipher  */
	if (ZRTP_CFBIV_SIZE != zrtp_randstr(session->zrtp, sasrelay->iv, ZRTP_CFBIV_SIZE)) {
		return zrtp_status_rp_fail;
	}

	sasrelay->flags |= (session->profile.disclose_bit || transf_d_flag) ? 0x01 : 0x00;
	sasrelay->flags |= (session->profile.allowclear && transf_ac_flag) ? 0x02 : 0x00;
	sasrelay->flags |= 0x04;

	zrtp_memcpy( sasrelay->sas_scheme,
				 zrtp_comp_id2type(ZRTP_CC_SAS, transf_sas_scheme),
				 ZRTP_COMP_TYPE_SIZE );
	if (transf_sas_value)
		zrtp_memcpy(sasrelay->sashash, transf_sas_value->buffer, transf_sas_value->length);

	/* Then we need to encrypt Confirm before computing Hmac. Use AES CFB */
	do {
		cipher_ctx = session->blockcipher->start( session->blockcipher,
												   (uint8_t*)stream->cc.zrtp_key.buffer,
												   NULL,
												   ZRTP_CIPHER_MODE_CFB );
		if (!cipher_ctx) {
			break;
		}

		s = session->blockcipher->set_iv( session->blockcipher,
										  cipher_ctx,
										  (zrtp_v128_t*)sasrelay->iv);
		if (zrtp_status_ok != s) {
			break;
		}

		s = session->blockcipher->encrypt( session->blockcipher,
										    cipher_ctx,
										    (uint8_t*)&sasrelay->pad,
										    encrypted_body_size );
	} while(0);
	if (cipher_ctx) {
		session->blockcipher->stop(session->blockcipher, cipher_ctx);
	}
	
	if (zrtp_status_ok != s) {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! Failed to encrypt SASRELAY Message status=%d. ID=%u\n", s, stream->id));
		return s;
	}

	/* Compute Hmac over encrypted part of Confirm */
	{
		zrtp_string128_t hmac = ZSTR_INIT_EMPTY(hmac);
		s = session->hash->hmac_c( session->hash,
									stream->cc.hmackey.buffer,
									stream->cc.hmackey.length,
									(const char*)&sasrelay->pad,
									encrypted_body_size,
									ZSTR_GV(hmac) );
		if (zrtp_status_ok != s) {
			ZRTP_LOG(1,(_ZTU_,"\tERROR! Failed to compute CONFIRM hmac status=%d. ID=%u\n", s, stream->id));
			return s;
		}
		zrtp_memcpy(sasrelay->hmac, hmac.buffer, ZRTP_HMAC_SIZE);
	}

	return s;
}
Example #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;
}
Example #7
0
/*----------------------------------------------------------------------------*/
zrtp_status_t _zrtp_machine_create_confirm( zrtp_stream_t *stream,
										    zrtp_packet_Confirm_t* confirm)
{
	void* cipher_ctx = NULL;
	zrtp_status_t s = zrtp_status_fail;
	zrtp_session_t *session = stream->session;
	uint32_t verifiedflag = 0;

	/* hash + (padding + sig_len + flags) + ttl */
	const uint8_t encrypted_body_size = ZRTP_MESSAGE_HASH_SIZE + (2 + 1 + 1) + 4;

	/*
	 * Create the Confirm packet according to draft 6.7
	 * AES CFB vector at first, SIG length and flags octet and cache TTL at the end
	 * This version doesn't support signatures so sig_length=0
	 */
	if (ZRTP_CFBIV_SIZE != zrtp_randstr(session->zrtp, confirm->iv, ZRTP_CFBIV_SIZE)) {
		return zrtp_status_fail;
	}

	zrtp_memcpy(confirm->hash, stream->messages.h0.buffer, ZRTP_MESSAGE_HASH_SIZE);

	zrtp_cache_get_verified(session->zrtp->cache, ZSTR_GV(session->peer_zid), &verifiedflag);

	confirm->expired_interval = zrtp_hton32(session->profile.cache_ttl);
	confirm->flags = 0;
	confirm->flags |= session->profile.disclose_bit ? 0x01 : 0x00;
	confirm->flags |= session->profile.allowclear ? 0x02 : 0x00;
	confirm->flags |= verifiedflag ? 0x04 : 0x00;
	confirm->flags |= (ZRTP_MITM_MODE_REG_SERVER == stream->mitm_mode) ? 0x08 : 0x00;

	/* Then we need to encrypt Confirm before Hmac computing. Use AES CFB */
	do
	{
		cipher_ctx = session->blockcipher->start( session->blockcipher,
												  (uint8_t*)stream->cc.zrtp_key.buffer,
												  NULL,
												  ZRTP_CIPHER_MODE_CFB);
		if (!cipher_ctx) {
			break;
		}

		s = session->blockcipher->set_iv(session->blockcipher, cipher_ctx, (zrtp_v128_t*)confirm->iv);
		if (zrtp_status_ok != s) {
			break;
		}

		s = session->blockcipher->encrypt( session->blockcipher,
										    cipher_ctx,
										    (uint8_t*)&confirm->hash,
										    encrypted_body_size );
	} while(0);
	if (cipher_ctx) {
		session->blockcipher->stop(session->blockcipher, cipher_ctx);
	}
	if (zrtp_status_ok != s) {
		ZRTP_LOG(1,(_ZTU_,"ERROR! failed to encrypt Confirm. s=%d ID=%u\n", s, stream->id));
		return s;
	}

	/* Compute Hmac over encrypted part of Confirm */
	{
		zrtp_string128_t hmac = ZSTR_INIT_EMPTY(hmac);
		s = session->hash->hmac_c( session->hash,
								    stream->cc.hmackey.buffer,
								    stream->cc.hmackey.length,
								    (const char*)&confirm->hash,
								    encrypted_body_size,
								    ZSTR_GV(hmac) );
		if (zrtp_status_ok != s) {
			ZRTP_LOG(1,(_ZTU_,"ERROR! failed to compute Confirm hmac. s=%d ID=%u\n", s, stream->id));
			return s;
		}
        
        zrtp_memcpy(confirm->hmac, hmac.buffer, ZRTP_HMAC_SIZE);
        
        {
            char buff[512];
            ZRTP_LOG(3,(_ZTU_,"HMAC TRACE. COMPUTE.\n"));
            ZRTP_LOG(3,(_ZTU_,"\tcipher text:%s. size=%u\n",
                        hex2str((const char*)&confirm->hash, encrypted_body_size, buff, sizeof(buff)), encrypted_body_size));
            ZRTP_LOG(3,(_ZTU_,"\t        key:%s.\n",
                        hex2str(stream->cc.hmackey.buffer, stream->cc.hmackey.length, buff, sizeof(buff))));
            ZRTP_LOG(3,(_ZTU_,"\t comp hmac:%s.\n",
                        hex2str(hmac.buffer, hmac.length, buff, sizeof(buff))));
            ZRTP_LOG(3,(_ZTU_,"\t      hmac:%s.\n",
                        hex2str((const char*)confirm->hmac, ZRTP_HMAC_SIZE, buff, sizeof(buff))));
        }
	}

	return zrtp_status_ok;
}