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 #2
0
zrtp_status_t zrtp_test_session_create(zrtp_test_id_t endpoint_id,
									   zrtp_test_session_cfg_t* cfg,
									   zrtp_test_id_t* id) {
	zrtp_status_t s;
	unsigned i;
	zrtp_test_session_t *the_session;
	zrtp_endpoint_t *the_endpoint = zrtp_test_endpoint_by_id(endpoint_id);

	if (!the_endpoint)
		return zrtp_status_fail;

	if (the_endpoint->sessions_count >= K_ZRTP_TEST_MAX_SESSIONS_PER_ENDPOINT)
		return zrtp_status_fail;

	the_session = &the_endpoint->sessions[the_endpoint->sessions_count++];

	zrtp_memset(the_session, 0, sizeof(zrtp_test_session_t));

	zrtp_memcpy(&the_session->cfg, cfg, sizeof(zrtp_test_session_cfg_t));

	the_session->id = g_sessions_counter++;
	the_session->endpoint_id = endpoint_id;

	s = zrtp_session_init(the_endpoint->zrtp,
						  &cfg->zrtp,
						  the_endpoint->zid,
						  cfg->role,
						  &the_session->zrtp);

	if (zrtp_status_ok == s) {

		zrtp_session_set_userdata(the_session->zrtp, &the_session->id);

		for (i=0; i<cfg->streams_count; i++) {
			zrtp_test_stream_t *the_stream = &the_session->streams[i];
			zrtp_memset(the_stream, 0, sizeof(zrtp_test_stream_t));

			the_stream->id = g_streams_counter++;
			the_stream->session_id = the_session->id;
			the_stream->endpoint_id = endpoint_id;

			s = zrtp_stream_attach(the_session->zrtp, &the_stream->zrtp);
			if (zrtp_status_ok == s) {
				zrtp_stream_set_userdata(the_stream->zrtp, &the_stream->id);
				the_session->streams_count++;
			} else {
				break;
			}
		}
	}

	if (zrtp_status_ok == s) {
		*id = the_session->id;
	}

	return s;
}
Example #3
0
zrtp_status_t zrtp_test_channel_create(zrtp_test_id_t left_id, zrtp_test_id_t right_id, zrtp_test_id_t* id) {
	zrtp_test_channel_t *the_channel;
	zrtp_test_stream_t *left = zrtp_test_stream_by_id(left_id);
	zrtp_test_stream_t *right = zrtp_test_stream_by_id(right_id);

	if (!left || !right)
		return zrtp_status_bad_param;

	if (g_test_channels_count >= K_ZRTP_TEST_MAX_CHANNELS)
		return zrtp_status_bad_param;

	zrtp_endpoint_t *left_endpoint = zrtp_test_endpoint_by_id(left->endpoint_id);
	zrtp_endpoint_t *right_endpoint = zrtp_test_endpoint_by_id(right->endpoint_id);

	the_channel = &g_test_channels[g_test_channels_count++];
	zrtp_memset(the_channel, 0, sizeof(zrtp_test_channel_t));

	the_channel->id = g_channels_counter++;
	the_channel->left = left;
	the_channel->right = right;

	left->output = right_endpoint->input_queue;
	left->input = left_endpoint->input_queue;
	right->output = left_endpoint->input_queue;
	right->input = right_endpoint->input_queue;

	right->channel_id = the_channel->id;
	left->channel_id = the_channel->id;

	the_channel->is_attached = 1;

	*id = the_channel->id;

	return zrtp_status_ok;
}
Example #4
0
void zrtp_config_defaults(zrtp_config_t* config)
{
	zrtp_memset(config, 0, sizeof(zrtp_config_t));
	
	zrtp_memcpy(config->client_id, "ZRTP def. peer", 15);
	config->lic_mode = ZRTP_LICENSE_MODE_PASSIVE;
	
	ZSTR_SET_EMPTY(config->def_cache_path);
	zrtp_zstrncpyc(ZSTR_GV(config->def_cache_path), "./zrtp_def_cache_path.dat", 25);

	config->cache_auto_store = 1; /* cache auto flushing should be enabled by default */

#if (defined(ZRTP_USE_BUILTIN_CACHE) && (ZRTP_USE_BUILTIN_CACHE == 1))
	config->cb.cache_cb.on_init					= zrtp_def_cache_init;
	config->cb.cache_cb.on_down					= zrtp_def_cache_down;
	config->cb.cache_cb.on_put					= zrtp_def_cache_put;
	config->cb.cache_cb.on_put_mitm				= zrtp_def_cache_put_mitm;
	config->cb.cache_cb.on_get					= zrtp_def_cache_get;
	config->cb.cache_cb.on_get_mitm				= zrtp_def_cache_get_mitm;
	config->cb.cache_cb.on_set_verified			= zrtp_def_cache_set_verified;
	config->cb.cache_cb.on_get_verified			= zrtp_def_cache_get_verified;
	config->cb.cache_cb.on_reset_since			= zrtp_def_cache_reset_since;
	config->cb.cache_cb.on_presh_counter_set	= zrtp_def_cache_set_presh_counter;
	config->cb.cache_cb.on_presh_counter_get	= zrtp_def_cache_get_presh_counter;
#endif

#if (defined(ZRTP_USE_BUILTIN_SCEHDULER) && (ZRTP_USE_BUILTIN_SCEHDULER == 1))
	config->cb.sched_cb.on_init					= zrtp_def_scheduler_init;
	config->cb.sched_cb.on_down					= zrtp_def_scheduler_down;
	config->cb.sched_cb.on_call_later			= zrtp_def_scheduler_call_later;
	config->cb.sched_cb.on_cancel_call_later	= zrtp_def_scheduler_cancel_call_later;
	config->cb.sched_cb.on_wait_call_later		= zrtp_def_scheduler_wait_call_later;
#endif
}
Example #5
0
/*----------------------------------------------------------------------------*/
void zrtp_profile_defaults(zrtp_profile_t* profile, zrtp_global_t* zrtp)
{   
	zrtp_memset(profile, 0, sizeof(zrtp_profile_t));

	profile->autosecure			= 1;	
	profile->allowclear			= 0;
	profile->discovery_optimization = 1;
	profile->cache_ttl			= ZRTP_CACHE_DEFAULT_TTL;

	profile->sas_schemes[0]		= ZRTP_SAS_BASE256;
	profile->sas_schemes[1]		= ZRTP_SAS_BASE32;	
	profile->cipher_types[0]	= ZRTP_CIPHER_AES256;
	profile->cipher_types[1]	= ZRTP_CIPHER_AES128;
	profile->auth_tag_lens[0]	= ZRTP_ATL_HS32;
	profile->hash_schemes[0]	= ZRTP_HASH_SHA256;

	if (zrtp && (ZRTP_LICENSE_MODE_PASSIVE == zrtp->lic_mode)) {
		profile->pk_schemes[0]		= ZRTP_PKTYPE_DH2048;
		profile->pk_schemes[1]		= ZRTP_PKTYPE_EC256P;
		profile->pk_schemes[2]		= ZRTP_PKTYPE_DH3072;
	} else {
		profile->pk_schemes[0]		= ZRTP_PKTYPE_EC256P;
		profile->pk_schemes[1]		= ZRTP_PKTYPE_DH3072;
		profile->pk_schemes[2]		= ZRTP_PKTYPE_DH2048;
	}
	profile->pk_schemes[3]		= ZRTP_PKTYPE_MULT;
}
Example #6
0
void zrtp_wipe_zstring(zrtp_stringn_t *zstr)
{
	if (zstr && zstr->length) {
		zrtp_memset(zstr->buffer, 0, zstr->max_length);
		zstr->length = 0;
	}
}
Example #7
0
/*----------------------------------------------------------------------------*/
static zrtp_status_t _attach_secret( zrtp_session_t *session,
									 zrtp_proto_secret_t* psec,
									 zrtp_shared_secret_t* sec,
									 uint8_t is_initiator)
{
	zrtp_uchar32_t buff;
	static const zrtp_string16_t initiator	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_ROLE_INITIATOR);
	static const zrtp_string16_t responder	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_ROLE_RESPONDER);

	const zrtp_string16_t* role				= is_initiator ? &initiator : &responder;
	const zrtp_string16_t* his_role			= is_initiator ? &responder : &initiator;

	ZSTR_SET_EMPTY(psec->id);
	ZSTR_SET_EMPTY(psec->peer_id);
	psec->secret = sec;

	/*
	 * If secret's value is available (from the cache or from SIP) - use hmac;
	 * use zero-strings in other case.
	 */
	if (psec->secret) {
		session->hash->hmac_truncated( session->hash,
									   ZSTR_GV(sec->value),
									   ZSTR_GVP(role),
									   ZRTP_RSID_SIZE,
									   ZSTR_GV(psec->id));

		session->hash->hmac_truncated( session->hash,
									   ZSTR_GV(sec->value),
									   ZSTR_GVP(his_role),
									   ZRTP_RSID_SIZE,
									   ZSTR_GV(psec->peer_id));
	} else {
		psec->id.length = ZRTP_RSID_SIZE;
		zrtp_memset(psec->id.buffer, 0, psec->id.length);

		psec->peer_id.length = ZRTP_RSID_SIZE;
		zrtp_memset(psec->peer_id.buffer, 0, psec->peer_id.length);
	}

	ZRTP_LOG(3,(_ZTU_,"\tAttach RS id=%s.\n",
				hex2str((const char*)psec->id.buffer, psec->id.length, (char*)buff, sizeof(buff))));
	ZRTP_LOG(3,(_ZTU_,"\tAttach RS peer_id=%s.\n",
				hex2str((const char*)psec->peer_id.buffer, psec->peer_id.length, (char*)buff, sizeof(buff))));

	return zrtp_status_ok;
}
Example #8
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 #9
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 #10
0
static void init_rs_secret_(zrtp_shared_secret_t *sec, unsigned char val_fill) {
	
	char val_buff[ZRTP_HASH_SIZE];
	zrtp_memset(val_buff, val_fill, sizeof(val_buff));
	
	ZSTR_SET_EMPTY(sec->value);
	zrtp_zstrcpyc(ZSTR_GV(sec->value), val_buff);
	
	sec->_cachedflag = 0;
	sec->ttl = 0;
	sec->lastused_at = 0;
}
Example #11
0
zrtp_status_t zrtp_test_stream_get(zrtp_test_id_t id,
								   zrtp_test_stream_info_t* info) {

	zrtp_test_stream_t *stream = zrtp_test_stream_by_id(id);
	if (stream) {
		zrtp_status_t s;
		zrtp_memset(info, 0, sizeof(zrtp_test_stream_info_t));

		zrtp_memcpy(info->zrtp_events_queueu, stream->zrtp_events_queueu, sizeof(info->zrtp_events_queueu));
		info->zrtp_events_count = stream->zrtp_events_count;

		s = zrtp_stream_get(stream->zrtp, &info->zrtp);
		return s;
	} else {
		return zrtp_status_bad_param;
	}
}
Example #12
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 #13
0
void zrtp_test_endpoint_config_defaults(zrtp_test_endpoint_cfg_t* cfg) {

	zrtp_memset(cfg, 0, sizeof(zrtp_test_endpoint_cfg_t));

	cfg->generate_traffic = 0;

	/* It's always a good idea to start with default values */
	zrtp_config_defaults(&cfg->zrtp);

	/* Set ZRTP client id */
	strcpy(cfg->zrtp.client_id, "zrtp-test-engine");

	cfg->zrtp.is_mitm = 0;
	cfg->zrtp.lic_mode = ZRTP_LICENSE_MODE_ACTIVE;

	cfg->zrtp.cb.event_cb.on_zrtp_secure			= &on_zrtp_secure;
	cfg->zrtp.cb.event_cb.on_zrtp_security_event	= &on_zrtp_event;
	cfg->zrtp.cb.event_cb.on_zrtp_protocol_event	= &on_zrtp_event;
	cfg->zrtp.cb.misc_cb.on_send_packet				= &on_send_packet;
}
Example #14
0
zrtp_status_t zrtp_test_channel_get(zrtp_test_id_t id,
									zrtp_test_channel_info_t* info) {

	zrtp_test_channel_t *channel = zrtp_test_channel_by_id(id);
	if (channel) {
		zrtp_status_t s;

		zrtp_memset(info, 0, sizeof(zrtp_test_channel_info_t));

		s = zrtp_test_stream_get(channel->left->id, &info->left);
		if (zrtp_status_ok == s) {
			s = zrtp_test_stream_get(channel->right->id, &info->right);
			if (zrtp_status_ok == s) {
				info->is_secure = channel->is_secure;
			}
		}

		return s;
	} else {
		return zrtp_status_bad_param;
	}
}
Example #15
0
zrtp_status_t zrtp_stream_get(zrtp_stream_t *stream, zrtp_stream_info_t *info)
{
	if (!stream || !info) {
		return zrtp_status_bad_param;
	}
	
	zrtp_memset(info, 0, sizeof(zrtp_stream_info_t));
	
	info->id			= stream->id;
	info->state			= stream->state;
	info->mode			= stream->mode;
	info->mitm_mode		= stream->mitm_mode;
	
	if (stream->state > ZRTP_STATE_ACTIVE) {
		info->last_error	= stream->last_error;
		info->peer_passive	= stream->peer_passive;
		info->res_allowclear= stream->allowclear;
		info->peer_disclose	= stream->peer_disclose_bit;
		info->peer_mitm		= stream->peer_mitm_flag;
	}
	
	return zrtp_status_ok;
}
Example #16
0
/*----------------------------------------------------------------------------*/
int zrtp_add_system_state(zrtp_global_t* zrtp, MD_CTX *ctx)
{
    uint8_t buffer[64];
    size_t bytes_read	= 0;
    static size_t length= sizeof(buffer);
    FILE *fp  			= NULL;
    
    fp = fopen("/dev/urandom", "rb");
    if (!fp) {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! can't get access to /dev/urandom - trying /dev/random.\n"));
		fp = fopen("/dev/random", "rb");
    }
	
    if (fp) {
		int number_of_retries = 1024;
		while ((bytes_read < length) && (number_of_retries-- > 0)) {
			setbuf(fp, NULL); /* Otherwise fread() tries to read() 4096 bytes or other default value */
			bytes_read	+= fread(buffer+bytes_read, 1, length-bytes_read, fp);
		}

		if (0 != fclose(fp)) {
			ZRTP_LOG(1,(_ZTU_,"\tERROR! unable to cloas /dev/random\n"));
		}
    } else {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! RNG Can't open /dev/random\n"));
    }    

    if (bytes_read < length) {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! can't read random string! Current session have to be closed.\n"));
		return -1;
    }

    MD_Update(ctx, buffer, length);
	zrtp_memset(buffer, 0, sizeof(buffer));

    return bytes_read;
}
Example #17
0
/*----------------------------------------------------------------------------*/
zrtp_status_t _zrtp_machine_process_sasrelay(zrtp_stream_t *stream, zrtp_rtp_info_t *packet)
{
	zrtp_session_t *session = stream->session;
	zrtp_packet_SASRelay_t *sasrelay = (zrtp_packet_SASRelay_t*) packet->message;
	void* cipher_ctx = NULL;
	zrtp_sas_id_t rendering_id = ZRTP_COMP_UNKN;
	zrtp_status_t s = zrtp_status_fail;
	zrtp_string128_t hmac = ZSTR_INIT_EMPTY(hmac);
	char zerosashash[32];
	unsigned sas_scheme_did_change = 0;
	unsigned sas_hash_did_change = 0;
	
	/* (padding + sig_len + flags) + SAS scheme and SAS hash */
	const uint8_t encrypted_body_size = (2 + 1 + 1) + 4 + 32;
	
	zrtp_memset(zerosashash, 0, sizeof(zerosashash));

	/* Check if the remote endpoint is assigned to relay the SAS values */
	if (!stream->peer_mitm_flag) {
		ZRTP_LOG(2,(_ZTU_, ZRTP_RELAYED_SAS_FROM_NONMITM_STR));
		return zrtp_status_fail;
	}
	
	/* Check the HMAC */
	s = session->hash->hmac_c( session->hash,
								stream->cc.peer_hmackey.buffer,
								stream->cc.peer_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 zrtp_status_fail;
	}

	if (0 != zrtp_memcmp(sasrelay->hmac, hmac.buffer, ZRTP_HMAC_SIZE)) {
		ZRTP_LOG(2,(_ZTU_, ZRTP_VERIFIED_RESP_WARNING_STR));
		return zrtp_status_fail;
	}

	ZRTP_LOG(3,(_ZTU_, "\tHMAC value for the SASRELAY is correct - decrypting...\n"));

	/* Then we need to decrypt Confirm body */
	do
	{
		cipher_ctx = session->blockcipher->start( session->blockcipher,
												   (uint8_t*)stream->cc.peer_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 decrypt Confirm. status=%d ID=%u\n", s, stream->id));
		return s;
	}

	ZRTP_LOG(2,(_ZTU_,"\tSasRelay FLAGS old/new A=%d/%d, D=%d/%d.\n",
					stream->allowclear, (uint8_t)(sasrelay->flags & 0x02),
					stream->peer_disclose_bit, (uint8_t)(sasrelay->flags & 0x01)));

	/* Set evil bit if other-side disclosed session key */
	stream->peer_disclose_bit = (sasrelay->flags & 0x01);

	/* Enable ALLOWCLEAR option only if both sides support it */
	stream->allowclear = (sasrelay->flags & 0x02) && session->profile.allowclear;

	/*
	 * We don't handle verified flag in SASRelaying because it makes no
	 * sense in implementation of the ZRTP Internet Draft.
	 */

	/*
	 * Only enrolled users can do SAS transferring. (Non-enrolled users can
	 * only change the SAS rendering scheme).
	 */

	rendering_id = zrtp_comp_type2id(ZRTP_CC_SAS, (char*)sasrelay->sas_scheme);
	if (-1 == zrtp_profile_find(&session->profile, ZRTP_CC_SAS, rendering_id)) {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! PBX Confirm packet with transferred SAS have unknown or"
					" unsupported rendering scheme %.4s.ID=%u\n", sasrelay->sas_scheme, stream->id));
		
		_zrtp_machine_enter_initiatingerror(stream, zrtp_error_invalid_packet, 1);
		return zrtp_status_fail;
	}

	/* Check is SAS rendering did change */
	if (rendering_id != session->sasscheme->base.id) {
		session->sasscheme = zrtp_comp_find(ZRTP_CC_SAS, rendering_id, session->zrtp );

		sas_scheme_did_change = 1;
		ZRTP_LOG(3,(_ZTU_,"\tSasrelay: Rendering scheme was updated to %.4s.\n", session->sasscheme->base.type));
	}

	if (session->secrets.matches & ZRTP_BIT_PBX) {
		if ( ( ((uint32_t) *sasrelay->sas_scheme) != (uint32_t)0x0L ) &&
			 (0 != zrtp_memcmp(sasrelay->sashash, zerosashash, sizeof(sasrelay->sashash))) )
		{
			char buff[256];
			session->sasbin.length = ZRTP_MITM_SAS_SIZE;
			/* First 32 bits if sashash includes sasvalue */
			zrtp_memcpy(session->sasbin.buffer, sasrelay->sashash, session->sasbin.length);
			stream->mitm_mode = ZRTP_MITM_MODE_RECONFIRM_CLIENT;
	
			sas_hash_did_change = 1;
			ZRTP_LOG(3,(_ZTU_,"\tSasRelay: SAS value was updated to bin=%s.\n",
							hex2str(buff, sizeof(buff), session->sasbin.buffer, session->sasbin.length)));
		}
	} else if (0 != zrtp_memcmp(sasrelay->sashash, zerosashash, sizeof(sasrelay->sashash))) {
		ZRTP_LOG(1,(_ZTU_,"\tWARNING! SAS Value was received from NOT Trusted MiTM. ID=%u\n", stream->id));
		_zrtp_machine_enter_initiatingerror(stream, zrtp_error_possible_mitm3, 1);
		return zrtp_status_fail;
	} else {
		ZRTP_LOG(1,(_ZTU_, "\rERROR! For SasRelay Other secret doesn't match. ID=%u\n", stream->id));
	}


	/* Generate new SAS if hash or rendering scheme did change.
	 * Note: latest libzrtp may send "empty" SasRelay with the same SAS rendering
	 *       scheme and empty Hello hash for consistency reasons, we should ignore
	 *       such packets.
	 */
	if (sas_scheme_did_change || sas_hash_did_change) {
		s = session->sasscheme->compute(session->sasscheme, stream, session->hash, 1);
		if (zrtp_status_ok != s) {
			_zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1);
			return s;
		}

		ZRTP_LOG(3,(_ZTU_,"\tSasRelay: Updated SAS is <%s> <%s>.\n", session->sas1.buffer, session->sas2.buffer));

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

	return zrtp_status_ok;
}
Example #18
0
zrtp_status_t zrtp_session_get(zrtp_session_t *session, zrtp_session_info_t *info)
{
	int i=0;
	if (!session || !info) {
		return zrtp_status_bad_param;
	}
	
	zrtp_memset(info, 0, sizeof(zrtp_session_info_t));
	
	ZSTR_SET_EMPTY(info->peer_clientid);
	ZSTR_SET_EMPTY(info->peer_version);
	ZSTR_SET_EMPTY(info->zid);
	ZSTR_SET_EMPTY(info->peer_zid);	
	ZSTR_SET_EMPTY(info->sas1);
	ZSTR_SET_EMPTY(info->sasbin);
	ZSTR_SET_EMPTY(info->sas2);
	ZSTR_SET_EMPTY(info->auth_name);
	ZSTR_SET_EMPTY(info->cipher_name);
	ZSTR_SET_EMPTY(info->hash_name);
	ZSTR_SET_EMPTY(info->sas_name);
	ZSTR_SET_EMPTY(info->pk_name);
	
	info->id = session->id;
	zrtp_zstrcpy(ZSTR_GV(info->zid), ZSTR_GV(session->zid));
	zrtp_zstrcpy(ZSTR_GV(info->peer_zid), ZSTR_GV(session->peer_zid));
	
	for (i=0; i<ZRTP_MAX_STREAMS_PER_SESSION; i++) {
		zrtp_stream_t* full_stream = &session->streams[i];
		if ((full_stream->state > ZRTP_STATE_ACTIVE) && !ZRTP_IS_STREAM_FAST(full_stream))
		{
			zrtp_zstrcpyc(ZSTR_GV(info->pk_name), zrtp_pkt2str[full_stream->pubkeyscheme->base.id-1]);
			
			zrtp_zstrncpyc( ZSTR_GV(info->peer_clientid),
						   (const char*)full_stream->messages.peer_hello.cliend_id, 16);
			zrtp_zstrncpyc( ZSTR_GV(info->peer_version),
						   (const char*)full_stream->messages.peer_hello.version, 4);
			
			info->secrets_ttl = full_stream->cache_ttl;
		}
	}
	
	info->sas_is_ready = (session->zrtpsess.length > 0) ? 1 : 0;
	if (info->sas_is_ready) {
		zrtp_zstrcpy(ZSTR_GV(info->sas1), ZSTR_GV(session->sas1));
		zrtp_zstrcpy(ZSTR_GV(info->sas2), ZSTR_GV(session->sas2));
		zrtp_zstrcpy(ZSTR_GV(info->sasbin), ZSTR_GV(session->sasbin));
		info->sas_is_base256 = (ZRTP_SAS_BASE256 == session->sasscheme->base.id);
		
		info->sas_is_verified = 0;
		if (session->zrtp->cb.cache_cb.on_get_verified) {
			session->zrtp->cb.cache_cb.on_get_verified( ZSTR_GV(session->zid),
													    ZSTR_GV(session->peer_zid),
													    &info->sas_is_verified);
		}

		zrtp_zstrcpyc(ZSTR_GV(info->hash_name), zrtp_hash2str[session->hash->base.id-1]);
		zrtp_zstrcpyc(ZSTR_GV(info->cipher_name), zrtp_cipher2str[session->blockcipher->base.id-1]);
		zrtp_zstrcpyc(ZSTR_GV(info->auth_name), zrtp_atl2str[session->authtaglength->base.id-1]);
		zrtp_zstrcpyc(ZSTR_GV(info->sas_name), zrtp_sas2str[session->sasscheme->base.id-1]);
		
		info->cached_flags	= session->secrets.cached_curr;
		info->matches_flags= session->secrets.matches_curr;
		info->wrongs_flags	= session->secrets.wrongs_curr;
	}
	
	return zrtp_status_ok;
}
Example #19
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;
}
Example #20
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 #21
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;
}
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 #23
0
void
lbnMemWipe(void *ptr, unsigned bytes)
{
	zrtp_memset(ptr, 0, bytes);
}
Example #24
0
/*----------------------------------------------------------------------------*/
zrtp_status_t _zrtp_set_public_value( zrtp_stream_t *stream,
									  int is_initiator)
{
	/*
	 * This function performs the following actions according to ZRTP draft 5.6
	 * a) Computes total hash;
	 * b) Calculates DHResult;
	 * c) Computes final stream key S0, based on DHSS and retained secrets;
	 * d) Computes HMAC Key and ZRTP key;
	 * e) Computes srtp keys and salts and creates srtp session.
	 */

	zrtp_session_t *session = stream->session;
	zrtp_proto_crypto_t* cc = stream->protocol->cc;
	void* hash_ctx = NULL;

	static const zrtp_string32_t hmac_keyi_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_INITIATOR_HMAKKEY_STR);
	static const zrtp_string32_t hmac_keyr_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_RESPONDER_HMAKKEY_STR);

    static const zrtp_string32_t srtp_mki_label	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_INITIATOR_KEY_STR);
    static const zrtp_string32_t srtp_msi_label	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_INITIATOR_SALT_STR);
    static const zrtp_string32_t srtp_mkr_label	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_RESPONDER_KEY_STR);
    static const zrtp_string32_t srtp_msr_label	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_RESPONDER_SALT_STR);

	static const zrtp_string32_t zrtp_keyi_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_INITIATOR_ZRTPKEY_STR);
	static const zrtp_string32_t zrtp_keyr_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_RESPONDER_ZRTPKEY_STR);

	uint32_t cipher_key_length = (ZRTP_CIPHER_AES128 == session->blockcipher->base.id) ? 16 : 32;

	const zrtp_string32_t *output_mk_label;
    const zrtp_string32_t *output_ms_label;
    const zrtp_string32_t *input_mk_label;
    const zrtp_string32_t *input_ms_label;
	const zrtp_string32_t *hmac_key_label;
	const zrtp_string32_t *peer_hmac_key_label;
	const zrtp_string32_t *zrtp_key_label;
	const zrtp_string32_t *peer_zrtp_key_label;

    /* Define roles and prepare structures */
    if (is_initiator) {
		output_mk_label		= &srtp_mki_label;
		output_ms_label		= &srtp_msi_label;
		input_mk_label		= &srtp_mkr_label;
		input_ms_label		= &srtp_msr_label;
		hmac_key_label		= &hmac_keyi_label;
		peer_hmac_key_label	= &hmac_keyr_label;
		zrtp_key_label		= &zrtp_keyi_label;
		peer_zrtp_key_label	= &zrtp_keyr_label;
    } else {
		output_mk_label		= &srtp_mkr_label;
		output_ms_label		= &srtp_msr_label;
		input_mk_label		= &srtp_mki_label;
		input_ms_label		= &srtp_msi_label;
		hmac_key_label		= &hmac_keyr_label;
		peer_hmac_key_label	= &hmac_keyi_label;
		zrtp_key_label		= &zrtp_keyr_label;
		peer_zrtp_key_label	= &zrtp_keyi_label;
    }

	ZRTP_LOG(3, (_ZTU_,"---------------------------------------------------\n"));
	ZRTP_LOG(3,(_ZTU_,"\tSWITCHING TO SRTP. ID=%u\n", zrtp_log_mode2str(stream->mode), stream->id));
	ZRTP_LOG(3,(_ZTU_,"\tI %s\n", is_initiator ? "Initiator" : "Responder"));
	
	/*
	 * Compute total messages hash:
	 * total_hash = hash(Hello of responder | Commit | DHPart1 | DHPart2) for DH streams
	 * total_hash = hash(Hello of responder | Commit ) for Fast modes.
	 */
	{
		uint8_t* tok	 = NULL;
		uint16_t tok_len = 0;

		hash_ctx = session->hash->hash_begin(session->hash);
		if (0 == hash_ctx) {			
			return zrtp_status_fail;
		}

		tok		= is_initiator ? (uint8_t*)&stream->messages.peer_hello : (uint8_t*) &stream->messages.hello;
		tok_len = is_initiator ? stream->messages.peer_hello.hdr.length : stream->messages.hello.hdr.length;
		tok_len = zrtp_ntoh16(tok_len)*4;
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)tok, tok_len);

		tok		= is_initiator ? (uint8_t*)&stream->messages.commit : (uint8_t*)&stream->messages.peer_commit;
		tok_len	= is_initiator ? stream->messages.commit.hdr.length : stream->messages.peer_commit.hdr.length;
		tok_len = zrtp_ntoh16(tok_len)*4;
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)tok, tok_len);		

		if (ZRTP_IS_STREAM_DH(stream))
		{
			tok = (uint8_t*) (is_initiator ? &stream->messages.peer_dhpart : &stream->messages.dhpart);
			tok_len	= is_initiator ? stream->messages.peer_dhpart.hdr.length : stream->messages.dhpart.hdr.length;
			tok_len = zrtp_ntoh16(tok_len)*4;
			session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)tok, tok_len);

			tok = (uint8_t*)(is_initiator ? &stream->messages.dhpart :  &stream->messages.peer_dhpart);
			tok_len	= is_initiator ? stream->messages.dhpart.hdr.length : stream->messages.peer_dhpart.hdr.length;
			tok_len = zrtp_ntoh16(tok_len)*4;
			session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)tok, tok_len);
		}

		session->hash->hash_end(session->hash, hash_ctx, ZSTR_GV(cc->mes_hash));
		hash_ctx = NULL;
	} /* total hash computing */
	
	/* Total Hash is ready and we can create KDF_Context */
	zrtp_zstrcat(ZSTR_GV(cc->kdf_context), is_initiator ? ZSTR_GV(session->zrtp->zid) : ZSTR_GV(session->peer_zid));
	zrtp_zstrcat(ZSTR_GV(cc->kdf_context), is_initiator ? ZSTR_GV(session->peer_zid) : ZSTR_GV(session->zrtp->zid));
	zrtp_zstrcat(ZSTR_GV(cc->kdf_context), ZSTR_GV(cc->mes_hash));

	/* Derive stream key S0 according to key exchange scheme */
	if (zrtp_status_ok != _derive_s0(stream, is_initiator)) {
		return zrtp_status_fail;
	}

    /*
	 * Compute HMAC keys. These values will be used after confirmation:
	 * hmackeyi = KDF(s0, "Initiator HMAC key", KDF_Context, negotiated hash length)
	 * hmackeyr = KDF(s0, "Responder HMAC key", KDF_Context, negotiated hash length)
	 */
	_zrtp_kdf( stream,
			   ZSTR_GV(cc->s0),
			   ZSTR_GVP(hmac_key_label),
			   ZSTR_GV(stream->protocol->cc->kdf_context),
			   session->hash->digest_length,
			   ZSTR_GV(stream->cc.hmackey));
	_zrtp_kdf( stream,
			   ZSTR_GV(cc->s0),
			   ZSTR_GVP(peer_hmac_key_label),
			   ZSTR_GV(stream->protocol->cc->kdf_context),
			   session->hash->digest_length,
			   ZSTR_GV(stream->cc.peer_hmackey));
	
	/*
	 * Computing ZRTP keys for protection of the Confirm packet:
	 * zrtpkeyi = KDF(s0, "Initiator ZRTP key", KDF_Context, negotiated AES key length)	 
	 * zrtpkeyr = KDF(s0, "Responder ZRTP key", KDF_Context, negotiated AES key length)
	 */
	_zrtp_kdf( stream,
			   ZSTR_GV(cc->s0),
			   ZSTR_GVP(zrtp_key_label),
			   ZSTR_GV(stream->protocol->cc->kdf_context),
			   cipher_key_length,
			   ZSTR_GV(stream->cc.zrtp_key));
	_zrtp_kdf( stream,
			   ZSTR_GV(cc->s0),
			   ZSTR_GVP(peer_zrtp_key_label),
			   ZSTR_GV(stream->protocol->cc->kdf_context),
			   cipher_key_length,
			   ZSTR_GV(stream->cc.peer_zrtp_key));
#if (defined(ZRTP_DEBUG_ZRTP_KEYS) && ZRTP_DEBUG_ZRTP_KEYS == 1)
	{
	char print_buff[256];
	ZRTP_LOG(3,(_ZTU_,"\t  Messages hash:%s\n", hex2str(cc->mes_hash.buffer, cc->mes_hash.length, print_buff, sizeof(print_buff))));
    ZRTP_LOG(3,(_ZTU_,"\t             S0:%s\n", hex2str(cc->s0.buffer, cc->s0.length, print_buff, sizeof(print_buff))));
	ZRTP_LOG(3,(_ZTU_,"\t      ZRTP Sess:%s\n", hex2str(session->zrtpsess.buffer, session->zrtpsess.length, print_buff, sizeof(print_buff))));
	ZRTP_LOG(3,(_ZTU_,"\t        hmackey:%s\n", hex2str(stream->cc.hmackey.buffer, stream->cc.hmackey.length, print_buff, sizeof(print_buff))));
	ZRTP_LOG(3,(_ZTU_,"\t  peer_hmackeyr:%s\n", hex2str(stream->cc.peer_hmackey.buffer, stream->cc.peer_hmackey.length, print_buff, sizeof(print_buff))));
	ZRTP_LOG(3,(_ZTU_,"\t       ZRTP key:%s\n", hex2str(stream->cc.zrtp_key.buffer, stream->cc.zrtp_key.length, print_buff, sizeof(print_buff))));
	ZRTP_LOG(3,(_ZTU_,"\t  Peer ZRTP key:%s\n", hex2str(stream->cc.peer_zrtp_key.buffer, stream->cc.peer_zrtp_key.length, print_buff, sizeof(print_buff))));
	}
#endif
	/*
	 * Preparing SRTP crypto engine:
	 * srtpkeyi = KDF(s0, "Initiator SRTP master key", KDF_Context, negotiated AES key length)	 
	 * srtpsalti = KDF(s0, "Initiator SRTP master salt", KDF_Context, 112)
	 * srtpkeyr = KDF(s0, "Responder SRTP master key", KDF_Context, negotiated AES key length)	 
	 * srtpsaltr = KDF(s0, "Responder SRTP master salt", KDF_Context, 112)	 
	 */
	{
		zrtp_srtp_profile_t iprof;
		zrtp_srtp_profile_t oprof;

		ZSTR_SET_EMPTY(iprof.salt);
		ZSTR_SET_EMPTY(iprof.key);

		iprof.rtp_policy.cipher			= session->blockcipher;
		iprof.rtp_policy.auth_tag_len	= session->authtaglength;
		iprof.rtp_policy.hash			= zrtp_comp_find(ZRTP_CC_HASH, ZRTP_SRTP_HASH_HMAC_SHA1, session->zrtp);
		iprof.rtp_policy.auth_key_len	= 20;
		iprof.rtp_policy.cipher_key_len = cipher_key_length;

		zrtp_memcpy(&iprof.rtcp_policy, &iprof.rtp_policy, sizeof(iprof.rtcp_policy));
		iprof.dk_cipher = session->blockcipher;

		zrtp_memcpy(&oprof, &iprof, sizeof(iprof));

		_zrtp_kdf( stream,
				   ZSTR_GV(cc->s0),
				   ZSTR_GVP(input_mk_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   cipher_key_length,
				   ZSTR_GV(iprof.key));
		_zrtp_kdf( stream,
				   ZSTR_GV(cc->s0),
				   ZSTR_GVP(input_ms_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   14,
				   ZSTR_GV(iprof.salt));
		_zrtp_kdf( stream,
				   ZSTR_GV(cc->s0),
				   ZSTR_GVP(output_mk_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   cipher_key_length,
				   ZSTR_GV(oprof.key));
		_zrtp_kdf( stream,
				   ZSTR_GV(cc->s0),
				   ZSTR_GVP(output_ms_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   14,
				   ZSTR_GV(oprof.salt));

		stream->protocol->_srtp = zrtp_srtp_create(session->zrtp->srtp_global, &iprof, &oprof);

		/* Profiles and keys in them are not needed anymore - clear them */
		zrtp_memset(&iprof, 0, sizeof(iprof));
		zrtp_memset(&oprof, 0, sizeof(oprof));

		if (!stream->protocol->_srtp) {
			ZRTP_LOG(1,(_ZTU_,"\tERROR! Can't initialize SRTP engine. ID=%u\n", stream->id));
			return zrtp_status_fail;
		}
	} /* SRTP initialization */

    return zrtp_status_ok;
}
Example #25
0
/*----------------------------------------------------------------------------*/
int zrtp_randstr(zrtp_global_t* zrtp, unsigned char *buffer, uint32_t length)
{
	//TODO: replace bg_aes_xxx() with our own block cipher component.
	//TODO: Do the same with the hash functions.

    aes_encrypt_ctx	aes_ctx;
    MD_CTX			rand_ctx2;
    unsigned char	md[MD_DIGEST_LENGTH];
    unsigned char	ctr[AES_BLOCK_SIZE];
    unsigned char	rdata[AES_BLOCK_SIZE];
    uint32_t		generated = length;
	
	/*
	 * In few cases we need to gerate random value before initializing libzrtp engine.
	 * Following trick makes it possible.
	 */	
	if (!zrtp->rand_initialized) {
		if (zrtp_status_ok != zrtp_init_rng(zrtp)) {
			return -1;
		}
	}	

	zrtp_mutex_lock(zrtp->rng_protector);

    /*
     * Add entropy from system state
     * We will include whatever happens to be in the buffer, it can't hurt
     */
    if ( 0 > zrtp_entropy_add(zrtp, buffer, length) ) {		
		zrtp_mutex_unlock(zrtp->rng_protector);
        return -1;
    }

    /* Copy the zrtp->rand_ctx and finalize it into the md buffer */
    rand_ctx2 = zrtp->rand_ctx;
    MD_Final(&rand_ctx2, md);
    
    zrtp_mutex_unlock(zrtp->rng_protector);

    /* Key an AES context from this buffer */
    zrtp_bg_aes_encrypt_key256(md, &aes_ctx);

    /* Initialize counter, using excess from md if available */
    zrtp_memset (ctr, 0, sizeof(ctr));
    if (MD_DIGEST_LENGTH > (256/8)) {
		uint32_t ctrbytes = MD_DIGEST_LENGTH - (256/8);
		if (ctrbytes > AES_BLOCK_SIZE)
			ctrbytes = AES_BLOCK_SIZE;
		zrtp_memcpy(ctr + sizeof(ctr) - ctrbytes, md + (256/8), ctrbytes);
    }
	
    /* Encrypt counter, copy to destination buffer, increment counter */
    while (length)
    {
		unsigned char *ctrptr;
		uint32_t copied;
		zrtp_bg_aes_encrypt(ctr, rdata, &aes_ctx);
		copied = (sizeof(rdata) < length) ? sizeof(rdata) : length;
		zrtp_memcpy (buffer, rdata, copied);
		buffer += copied;
		length -= copied;
		
		/* Increment counter */
		ctrptr = ctr + sizeof(ctr) - 1;
		while (ctrptr >= ctr) {
			if ((*ctrptr-- += 1) != 0) {
				break;
			}
		}
    }

    /* Done!  Cleanup and exit */
    MD_Cleanup (&rand_ctx2);
    MD_Cleanup (md);
    MD_Cleanup (&aes_ctx);
    MD_Cleanup (ctr);
    MD_Cleanup (rdata);
	
    return generated;
}
Example #26
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 #27
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 #28
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
}