示例#1
0
/*---------------------------------------------------------------------------*/
zrtp_status_t zrtp_register_with_trusted_mitm(zrtp_stream_t* stream)
{
	zrtp_session_t *session = stream->session;
	zrtp_status_t s = zrtp_status_bad_param;
	
	if (!stream) {
		return zrtp_status_bad_param;
	}
	
	ZRTP_LOG(3,(_ZTU_,"MARKING this call as REGISTRATION ID=%u\n", stream->id));
	
	if (NULL == stream->zrtp->cb.cache_cb.on_get_mitm) {
		ZRTP_LOG(2,(_ZTU_,"WARNING: Can't use MiTM Functions with no ZRTP Cache.\n"));
		return zrtp_status_notavailable;
	}
	
	if (!stream->protocol) {
		return zrtp_status_bad_param;
	}
	
	/* Passive Client endpoint should NOT generate PBX Secret. */
	if ((stream->mitm_mode == ZRTP_MITM_MODE_REG_CLIENT) &&
		(ZRTP_LICENSE_MODE_PASSIVE == stream->zrtp->lic_mode)) {
		ZRTP_LOG(2,(_ZTU_,"WARNING: Passive Client endpoint should NOT generate PBX Secret.\n"));
		return zrtp_status_bad_param;
	}

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

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

	return s;
}
示例#2
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;
}