/*---------------------------------------------------------------------------*/ 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; }
/*----------------------------------------------------------------------------*/ 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; }