558 lines
19 KiB
C
558 lines
19 KiB
C
/*
|
|
* libZRTP SDK library, implements the ZRTP secure VoIP protocol.
|
|
* Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved.
|
|
* Contact: http://philzimmermann.com
|
|
* For licensing and other legal details, see the file zrtp_legal.c.
|
|
*
|
|
* Viktor Krykun <v.krikun at zfoneproject.com>
|
|
*/
|
|
|
|
#include "zrtp.h"
|
|
|
|
#define _ZTU_ "zrtp initiator"
|
|
|
|
extern zrtp_status_t _zrtp_machine_start_initiating_secure(zrtp_stream_t *stream);
|
|
|
|
/*! These functions set constructs and start ZRTP messages replays */
|
|
static zrtp_status_t _zrtp_machine_start_send_and_resend_commit(zrtp_stream_t *stream);
|
|
static zrtp_status_t _zrtp_machine_start_send_and_resend_dhpart2(zrtp_stream_t *stream);
|
|
static zrtp_status_t _zrtp_machine_start_send_and_resend_confirm2(zrtp_stream_t *stream);
|
|
|
|
/*!
|
|
* We need to know the contents of the DH2 packet before we send the Commit to
|
|
* compute the hash value. So, we construct DH packet but don't send it till
|
|
* WAITING_FOR_CONFIRM1 state.
|
|
*/
|
|
static void _prepare_dhpart2(zrtp_stream_t *stream);
|
|
|
|
/*
|
|
* Parses DH packet: check for MitM1 attack and makes a copy of the packet for
|
|
* later. \exception: Handles all exceptions -- informs user and switches to
|
|
* CLEAR.(MITM attacks)
|
|
*/
|
|
static zrtp_status_t _zrtp_machine_process_incoming_dhpart1( zrtp_stream_t *stream,
|
|
zrtp_rtp_info_t *packet);
|
|
/*
|
|
* Just a wrapper over the protocol::_zrtp_machine_process_confirm().
|
|
* \exception: Handles all exceptions -- informs user and switches to
|
|
* CLEAR. (SOFTWARE)
|
|
*/
|
|
static zrtp_status_t _zrtp_machine_process_incoming_confirm1( zrtp_stream_t *stream,
|
|
zrtp_rtp_info_t *packet);
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* State handlers */
|
|
/*===========================================================================*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t _zrtp_machine_process_while_in_initiatingsecure( zrtp_stream_t* stream,
|
|
zrtp_rtp_info_t* packet)
|
|
{
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
|
|
switch (packet->type)
|
|
{
|
|
case ZRTP_COMMIT:
|
|
if (ZRTP_STATEMACHINE_RESPONDER == _zrtp_machine_preparse_commit(stream, packet)) {
|
|
_zrtp_cancel_send_packet_later(stream, ZRTP_COMMIT);
|
|
s = _zrtp_machine_enter_pendingsecure(stream, packet);
|
|
}
|
|
break;
|
|
|
|
case ZRTP_DHPART1:
|
|
if (ZRTP_IS_STREAM_DH(stream)) {
|
|
_zrtp_cancel_send_packet_later(stream, ZRTP_COMMIT);
|
|
|
|
s = _zrtp_machine_process_incoming_dhpart1(stream, packet);
|
|
if (zrtp_status_ok != s) {
|
|
ZRTP_LOG(1,(_ZTU_,"\tERROR! _zrtp_machine_process_incoming_dhpart1() failed with status=%d ID=%u\n.", s, stream->id));
|
|
break;
|
|
}
|
|
|
|
_zrtp_machine_start_send_and_resend_dhpart2(stream);
|
|
|
|
/* Perform Key generation according to draft 5.6 */
|
|
s = _zrtp_set_public_value(stream, 1);
|
|
if (zrtp_status_ok != s) {
|
|
ZRTP_LOG(1,(_ZTU_,"\tERROR! set_public_value1() failed with status=%d ID=%u.\n", s, stream->id));
|
|
_zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1);
|
|
break;
|
|
}
|
|
|
|
_zrtp_change_state(stream, ZRTP_STATE_WAIT_CONFIRM1);
|
|
}
|
|
break;
|
|
|
|
case ZRTP_CONFIRM1:
|
|
if (ZRTP_IS_STREAM_FAST(stream)) {
|
|
s = _zrtp_set_public_value(stream, 1);
|
|
if (zrtp_status_ok != s) {
|
|
break;
|
|
}
|
|
|
|
s = _zrtp_machine_process_incoming_confirm1(stream, packet);
|
|
if (zrtp_status_ok != s) {
|
|
ZRTP_LOG(1,(_ZTU_,"\tERROR! process_incoming_confirm1() failed with status=%d ID=%u.\n", s, stream->id));
|
|
break;
|
|
}
|
|
|
|
_zrtp_cancel_send_packet_later(stream, ZRTP_COMMIT);
|
|
_zrtp_change_state(stream, ZRTP_STATE_WAIT_CONFIRMACK);
|
|
s = _zrtp_machine_start_send_and_resend_confirm2(stream);
|
|
}
|
|
break;
|
|
|
|
case ZRTP_NONE:
|
|
s = zrtp_status_drop;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t _zrtp_machine_process_while_in_waitconfirm1( zrtp_stream_t* stream,
|
|
zrtp_rtp_info_t* packet)
|
|
{
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
|
|
switch (packet->type)
|
|
{
|
|
case ZRTP_CONFIRM1:
|
|
s = _zrtp_machine_process_incoming_confirm1(stream, packet);
|
|
if (zrtp_status_ok != s) {
|
|
ZRTP_LOG(1,(_ZTU_,"\tERROR! process_incoming_confirm1() failed with status=%d ID=%u.\n", s, stream->id));
|
|
break;
|
|
}
|
|
|
|
_zrtp_change_state(stream, ZRTP_STATE_WAIT_CONFIRMACK);
|
|
_zrtp_cancel_send_packet_later(stream, ZRTP_DHPART2);
|
|
s = _zrtp_machine_start_send_and_resend_confirm2(stream);
|
|
break;
|
|
|
|
case ZRTP_NONE:
|
|
s = zrtp_status_drop;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t _zrtp_machine_process_while_in_waitconfirmack( zrtp_stream_t* stream,
|
|
zrtp_rtp_info_t* packet)
|
|
{
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
|
|
switch (packet->type)
|
|
{
|
|
case ZRTP_NONE:
|
|
s = _zrtp_protocol_decrypt(stream->protocol, packet, 1);
|
|
if (s == zrtp_status_ok) {
|
|
/*
|
|
* High level functions triggers mutexes for protocol messages only.
|
|
* We have manually protect this transaction triggered by media packet, not protocol packet.
|
|
*/
|
|
zrtp_mutex_lock(stream->stream_protector);
|
|
|
|
ZRTP_LOG(3,(_ZTU_, "Received FIRST VALID SRTP packet - switching to SECURE state. ID=%u\n", stream->id));
|
|
_zrtp_cancel_send_packet_later(stream, ZRTP_CONFIRM2);
|
|
_zrtp_machine_enter_secure(stream);
|
|
|
|
zrtp_mutex_unlock(stream->stream_protector);
|
|
}
|
|
break;
|
|
|
|
case ZRTP_CONFIRM2ACK:
|
|
_zrtp_cancel_send_packet_later(stream, ZRTP_CONFIRM2);
|
|
s = _zrtp_machine_enter_secure(stream);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* State switchers */
|
|
/*===========================================================================*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t _zrtp_machine_enter_initiatingsecure(zrtp_stream_t* stream)
|
|
{
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
|
|
ZRTP_LOG(3,(_ZTU_,"\tENTER STATE INITIATING SECURE for ID=%u mode=%s state=%s.\n",
|
|
stream->id, zrtp_log_mode2str(stream->mode), zrtp_log_state2str(stream->state)));
|
|
|
|
if (!ZRTP_IS_STREAM_MULT(stream)) {
|
|
uint8_t id = ZRTP_COMP_UNKN;
|
|
zrtp_session_t *session = stream->session;
|
|
zrtp_packet_Hello_t *peer_hello = &stream->messages.peer_hello;
|
|
|
|
/*
|
|
* ZRTP specification provides that default crypto components may be
|
|
* omitted from the Hello message, so we initialize components with
|
|
* default values.
|
|
*/
|
|
session->hash = zrtp_comp_find(ZRTP_CC_HASH, ZRTP_HASH_SHA256, session->zrtp);
|
|
session->blockcipher = zrtp_comp_find(ZRTP_CC_CIPHER, ZRTP_CIPHER_AES128, session->zrtp);
|
|
session->authtaglength = zrtp_comp_find(ZRTP_CC_ATL, ZRTP_ATL_HS32, session->zrtp);
|
|
session->sasscheme = zrtp_comp_find(ZRTP_CC_SAS, ZRTP_SAS_BASE32, session->zrtp);
|
|
|
|
id = _zrtp_choose_best_comp(&session->profile, peer_hello, ZRTP_CC_HASH);
|
|
if (id != ZRTP_COMP_UNKN) {
|
|
session->hash = zrtp_comp_find(ZRTP_CC_HASH, id, session->zrtp);
|
|
}
|
|
id = _zrtp_choose_best_comp(&session->profile, peer_hello, ZRTP_CC_CIPHER);
|
|
if (id != ZRTP_COMP_UNKN) {
|
|
session->blockcipher = zrtp_comp_find(ZRTP_CC_CIPHER, id, session->zrtp);
|
|
}
|
|
id = _zrtp_choose_best_comp(&session->profile, peer_hello, ZRTP_CC_ATL);
|
|
if (id != ZRTP_COMP_UNKN) {
|
|
session->authtaglength = zrtp_comp_find(ZRTP_CC_ATL, id, session->zrtp);
|
|
}
|
|
id = _zrtp_choose_best_comp(&session->profile, peer_hello, ZRTP_CC_SAS);
|
|
if (id != ZRTP_COMP_UNKN) {
|
|
session->sasscheme = zrtp_comp_find(ZRTP_CC_SAS, id, session->zrtp);
|
|
}
|
|
|
|
ZRTP_LOG(3,(_ZTU_,"\tInitiator selected following options:\n"));
|
|
ZRTP_LOG(3,(_ZTU_,"\t Hash: %.4s\n", session->hash->base.type));
|
|
ZRTP_LOG(3,(_ZTU_,"\t Cipher: %.4s\n", session->blockcipher->base.type));
|
|
ZRTP_LOG(3,(_ZTU_,"\t ATL: %.4s\n", session->authtaglength->base.type));
|
|
ZRTP_LOG(3,(_ZTU_,"\tVAD scheme: %.4s\n", session->sasscheme->base.type));
|
|
}
|
|
|
|
do{
|
|
/* Allocate resources for Initiator's state-machine */
|
|
s = _zrtp_protocol_init(stream, 1, &stream->protocol);
|
|
if (zrtp_status_ok != s) {
|
|
break; /* Software error */
|
|
}
|
|
|
|
_zrtp_change_state(stream, ZRTP_STATE_INITIATINGSECURE);
|
|
|
|
/* Prepare DHPart2 message to compute hvi. For DH and Preshared streams only*/
|
|
if (ZRTP_IS_STREAM_DH(stream)) {
|
|
_prepare_dhpart2(stream);
|
|
}
|
|
|
|
s = _zrtp_machine_start_send_and_resend_commit(stream);
|
|
if (zrtp_status_ok != s) {
|
|
break; /* EH: Software error */
|
|
}
|
|
|
|
if (stream->zrtp->cb.event_cb.on_zrtp_protocol_event) {
|
|
stream->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_INITIATINGSECURE);
|
|
}
|
|
} while (0);
|
|
|
|
if (zrtp_status_ok != s) {
|
|
if (stream->protocol) {
|
|
_zrtp_protocol_destroy(stream->protocol);
|
|
stream->protocol = NULL;
|
|
}
|
|
_zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1);
|
|
}
|
|
|
|
if (ZRTP_IS_STREAM_DH(stream)) {
|
|
/*
|
|
* If stream->concurrent is set this means that we stopped a concurrent
|
|
* DH stream to break a tie. This can happen when Commit messages are
|
|
* sent by both ZRTP endpoints at the same time, but are received in
|
|
* different media streams. Now current stream has finished DH setup and
|
|
* we can resume the other one.
|
|
*/
|
|
if (stream->concurrent) {
|
|
zrtp_stream_t* tctx = stream->concurrent;
|
|
stream->concurrent = NULL;
|
|
ZRTP_LOG(3,(_ZTU_,"\tRelease Concurrent Stream ID=%u. ID=%u\n", tctx->id, stream->id));
|
|
_zrtp_machine_start_initiating_secure(tctx);
|
|
}
|
|
}
|
|
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* Packet handlers */
|
|
/*===========================================================================*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static zrtp_status_t _zrtp_machine_process_incoming_dhpart1( zrtp_stream_t *stream,
|
|
zrtp_rtp_info_t *packet)
|
|
{
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
zrtp_packet_DHPart_t *dhpart1 = (zrtp_packet_DHPart_t*) packet->message;
|
|
|
|
/* Validating DH (pvr is 1 or p-1) */
|
|
bnInsertBigBytes(&stream->dh_cc.peer_pv, dhpart1->pv, 0, stream->pubkeyscheme->pv_length);
|
|
|
|
s = stream->pubkeyscheme->validate(stream->pubkeyscheme, &stream->dh_cc.peer_pv);
|
|
if (zrtp_status_ok != s) {
|
|
ZRTP_LOG(2,(_ZTU_,"\tERROR! " ZRTP_MITM1_WARNING_STR " ID=%u\n", stream->id));
|
|
_zrtp_machine_enter_initiatingerror(stream, zrtp_error_possible_mitm1, 1);
|
|
return s;
|
|
}
|
|
|
|
/* Copy DH Part1 packet for further hashing */
|
|
zrtp_memcpy(&stream->messages.peer_dhpart, dhpart1, zrtp_ntoh16(dhpart1->hdr.length)*4);
|
|
|
|
return s;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static zrtp_status_t _zrtp_machine_process_incoming_confirm1( zrtp_stream_t *stream,
|
|
zrtp_rtp_info_t *packet)
|
|
{
|
|
return _zrtp_machine_process_confirm(stream, (zrtp_packet_Confirm_t*) packet->message);
|
|
}
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* Packet senders */
|
|
/*===========================================================================*/
|
|
|
|
static void _send_and_resend_commit(zrtp_stream_t *stream, zrtp_retry_task_t* task)
|
|
{
|
|
if (task->_retrys >= ZRTP_T2_MAX_COUNT) {
|
|
ZRTP_LOG(2,(_ZTU_,"WARNING! COMMIT Max retransmissions count reached. ID=%u\n", stream->id));
|
|
_zrtp_machine_enter_initiatingerror(stream, zrtp_error_timeout, 0);
|
|
} else if (task->_is_enabled) {
|
|
zrtp_status_t s = zrtp_status_fail;
|
|
zrtp_packet_Commit_t* commit = (zrtp_packet_Commit_t*) &stream->messages.commit;
|
|
|
|
s = _zrtp_packet_send_message(stream, ZRTP_COMMIT, commit);
|
|
task->timeout = _zrtp_get_timeout((uint32_t)task->timeout, ZRTP_COMMIT);
|
|
if (s == zrtp_status_ok) {
|
|
task->_retrys++;
|
|
}
|
|
if (stream->zrtp->cb.sched_cb.on_call_later) {
|
|
stream->zrtp->cb.sched_cb.on_call_later(stream, task);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static zrtp_status_t _zrtp_machine_start_send_and_resend_commit(zrtp_stream_t *stream)
|
|
{
|
|
zrtp_proto_crypto_t* cc = stream->protocol->cc;
|
|
zrtp_packet_Commit_t* commit = &stream->messages.commit;
|
|
zrtp_retry_task_t* task = &stream->messages.commit_task;
|
|
uint8_t hmac_offset = ZRTP_COMMIT_STATIC_SIZE;
|
|
zrtp_session_t *session = stream->session;
|
|
|
|
zrtp_memcpy(commit->zid, stream->messages.hello.zid, sizeof(zrtp_zid_t));
|
|
|
|
zrtp_memcpy(commit->hash_type, session->hash->base.type, ZRTP_COMP_TYPE_SIZE);
|
|
zrtp_memcpy(commit->cipher_type, session->blockcipher->base.type, ZRTP_COMP_TYPE_SIZE);
|
|
zrtp_memcpy(commit->auth_tag_length, session->authtaglength->base.type, ZRTP_COMP_TYPE_SIZE );
|
|
zrtp_memcpy(commit->public_key_type, stream->pubkeyscheme->base.type, ZRTP_COMP_TYPE_SIZE);
|
|
zrtp_memcpy(commit->sas_type, session->sasscheme->base.type, ZRTP_COMP_TYPE_SIZE);
|
|
|
|
/*
|
|
* According to the last version of the internet draft 08b., hvi should be
|
|
* computed as:
|
|
* a) hvi=hash(initiator's DHPart2 message | responder's Hello message) for DH stream.
|
|
* b) For Multistream it just a 128 bit random nonce.
|
|
* c) For Preshared streams it keyID = HMAC(preshared_key, "Prsh") truncated to 64 bits
|
|
*/
|
|
switch (stream->mode)
|
|
{
|
|
case ZRTP_STREAM_MODE_DH:
|
|
{
|
|
void *hash_ctx = session->hash->hash_begin(session->hash);
|
|
if (!hash_ctx) {
|
|
return zrtp_status_alloc_fail;
|
|
}
|
|
|
|
session->hash->hash_update( session->hash,
|
|
hash_ctx,
|
|
(const int8_t*)&stream->messages.dhpart,
|
|
zrtp_ntoh16(stream->messages.dhpart.hdr.length)*4);
|
|
session->hash->hash_update( session->hash,
|
|
hash_ctx,
|
|
(const int8_t*)&stream->messages.peer_hello,
|
|
zrtp_ntoh16(stream->messages.peer_hello.hdr.length)*4);
|
|
|
|
session->hash->hash_end(session->hash, hash_ctx, ZSTR_GV(cc->hv));
|
|
zrtp_memcpy(commit->hv, cc->hv.buffer, ZRTP_HV_SIZE);
|
|
hmac_offset += ZRTP_HV_SIZE;
|
|
} break;
|
|
|
|
case ZRTP_STREAM_MODE_PRESHARED:
|
|
{
|
|
zrtp_string8_t key_id = ZSTR_INIT_EMPTY(key_id);
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
|
|
/* Generate random 4 word nonce */
|
|
if (ZRTP_HV_NONCE_SIZE != zrtp_randstr(session->zrtp, (unsigned char*)cc->hv.buffer, ZRTP_HV_NONCE_SIZE)) {
|
|
return zrtp_status_rng_fail;
|
|
}
|
|
cc->hv.length = ZRTP_HV_NONCE_SIZE;
|
|
|
|
/*
|
|
* Generate Preshared_key:
|
|
* hash(len(rs1) | rs1 | len(auxsecret) | auxsecret | len(pbxsecret) | pbxsecret)
|
|
*/
|
|
s = _zrtp_compute_preshared_key( session,
|
|
ZSTR_GV(session->secrets.rs1->value),
|
|
(session->secrets.auxs->_cachedflag) ? ZSTR_GV(session->secrets.auxs->value) : NULL,
|
|
(session->secrets.pbxs->_cachedflag) ? ZSTR_GV(session->secrets.pbxs->value) : NULL,
|
|
NULL,
|
|
ZSTR_GV(key_id));
|
|
if (zrtp_status_ok != s) {
|
|
return s;
|
|
}
|
|
|
|
/* Copy 4 word nonce and add 2 word keyID */
|
|
zrtp_memcpy(commit->hv, cc->hv.buffer, ZRTP_HV_NONCE_SIZE);
|
|
hmac_offset += ZRTP_HV_NONCE_SIZE;
|
|
|
|
zrtp_memcpy(commit->hv+ZRTP_HV_NONCE_SIZE, key_id.buffer, ZRTP_HV_KEY_SIZE);
|
|
hmac_offset += ZRTP_HV_KEY_SIZE;
|
|
} break;
|
|
|
|
case ZRTP_STREAM_MODE_MULT:
|
|
{
|
|
if(ZRTP_HV_NONCE_SIZE != zrtp_randstr(session->zrtp, (unsigned char*)cc->hv.buffer, ZRTP_HV_NONCE_SIZE)) {
|
|
return zrtp_status_rng_fail;
|
|
}
|
|
|
|
cc->hv.length = ZRTP_HV_NONCE_SIZE;
|
|
zrtp_memcpy(commit->hv, cc->hv.buffer, ZRTP_HV_NONCE_SIZE);
|
|
hmac_offset += ZRTP_HV_NONCE_SIZE;
|
|
}break;
|
|
default: break;
|
|
}
|
|
|
|
_zrtp_packet_fill_msg_hdr(stream, ZRTP_COMMIT, hmac_offset + ZRTP_HMAC_SIZE, &commit->hdr);
|
|
|
|
{
|
|
char buff[256];
|
|
ZRTP_LOG(3,(_ZTU_,"\tStart Sending COMMIT ID=%u mode=%s state=%s:\n",
|
|
stream->id, zrtp_log_mode2str(stream->mode), zrtp_log_state2str(stream->state)));
|
|
ZRTP_LOG(3,(_ZTU_,"\t Hash: %.4s\n", commit->hash_type));
|
|
ZRTP_LOG(3,(_ZTU_,"\t Cipher: %.4s\n", commit->cipher_type));
|
|
ZRTP_LOG(3,(_ZTU_,"\t ATL: %.4s\n", commit->auth_tag_length));
|
|
ZRTP_LOG(3,(_ZTU_,"\t PK scheme: %.4s\n", commit->public_key_type));
|
|
ZRTP_LOG(3,(_ZTU_,"\tVAD scheme: %.4s\n", commit->sas_type));
|
|
|
|
ZRTP_LOG(3,(_ZTU_,"\t hv: %s\n", hex2str((const char*)commit->hv, ZRTP_HV_SIZE, (char*)buff, sizeof(buff))));
|
|
}
|
|
|
|
task->_is_enabled = 1;
|
|
task->callback = _send_and_resend_commit;
|
|
task->_retrys = 0;
|
|
_send_and_resend_commit(stream, task);
|
|
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static void _send_and_resend_dhpart2(zrtp_stream_t *stream, zrtp_retry_task_t* task)
|
|
{
|
|
if (task->_retrys >= ZRTP_T2_MAX_COUNT)
|
|
{
|
|
ZRTP_LOG(1,(_ZTU_,"WARNING! DH2 Max retransmissions count reached. ID=%u\n", stream->id));
|
|
_zrtp_machine_enter_initiatingerror(stream, zrtp_error_timeout, 0);
|
|
} else if (task->_is_enabled) {
|
|
zrtp_status_t s = _zrtp_packet_send_message(stream, ZRTP_DHPART2, &stream->messages.dhpart);
|
|
task->timeout = _zrtp_get_timeout((uint32_t)task->timeout, ZRTP_DHPART2);
|
|
if (zrtp_status_ok == s) {
|
|
task->_retrys++;
|
|
}
|
|
if (stream->zrtp->cb.sched_cb.on_call_later) {
|
|
stream->zrtp->cb.sched_cb.on_call_later(stream, task);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _prepare_dhpart2(zrtp_stream_t *stream)
|
|
{
|
|
zrtp_proto_crypto_t* cc = stream->protocol->cc;
|
|
zrtp_packet_DHPart_t *dh2 = &stream->messages.dhpart;
|
|
uint16_t dh_length = (uint16_t)stream->pubkeyscheme->pv_length;
|
|
|
|
zrtp_memcpy(dh2->rs1ID, cc->rs1.id.buffer, ZRTP_RSID_SIZE);
|
|
zrtp_memcpy(dh2->rs2ID, cc->rs2.id.buffer, ZRTP_RSID_SIZE);
|
|
zrtp_memcpy(dh2->auxsID, cc->auxs.id.buffer, ZRTP_RSID_SIZE);
|
|
zrtp_memcpy(dh2->pbxsID, cc->pbxs.id.buffer, ZRTP_RSID_SIZE);
|
|
|
|
bnExtractBigBytes(&stream->dh_cc.pv, dh2->pv, 0, dh_length);
|
|
|
|
_zrtp_packet_fill_msg_hdr( stream,
|
|
ZRTP_DHPART2,
|
|
dh_length + ZRTP_DH_STATIC_SIZE + ZRTP_HMAC_SIZE,
|
|
&dh2->hdr );
|
|
}
|
|
|
|
static zrtp_status_t _zrtp_machine_start_send_and_resend_dhpart2(zrtp_stream_t *stream)
|
|
{
|
|
zrtp_retry_task_t* task = &stream->messages.dhpart_task;
|
|
|
|
task->_is_enabled = 1;
|
|
task->callback = _send_and_resend_dhpart2;
|
|
task->_retrys = 0;
|
|
_send_and_resend_dhpart2(stream, task);
|
|
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static void _send_and_resend_confirm2(zrtp_stream_t *stream, zrtp_retry_task_t* task)
|
|
{
|
|
if (task->_retrys >= ZRTP_T2_MAX_COUNT) {
|
|
ZRTP_LOG(1,(_ZTU_,"WARNING! CONFIRM2 Max retransmissions count reached. ID=%u\n", stream->id));
|
|
_zrtp_machine_enter_initiatingerror(stream, zrtp_error_timeout, 0);
|
|
} else if (task->_is_enabled) {
|
|
zrtp_status_t s = zrtp_status_ok;
|
|
s = _zrtp_packet_send_message(stream, ZRTP_CONFIRM2, &stream->messages.confirm);
|
|
task->timeout = _zrtp_get_timeout((uint32_t)task->timeout, ZRTP_CONFIRM2);
|
|
if (zrtp_status_ok == s) {
|
|
task->_retrys++;
|
|
}
|
|
if (stream->zrtp->cb.sched_cb.on_call_later) {
|
|
stream->zrtp->cb.sched_cb.on_call_later(stream, task);
|
|
}
|
|
}
|
|
}
|
|
|
|
static zrtp_status_t _zrtp_machine_start_send_and_resend_confirm2(zrtp_stream_t *stream)
|
|
{
|
|
zrtp_retry_task_t* task = &stream->messages.confirm_task;
|
|
|
|
zrtp_status_t s = _zrtp_machine_create_confirm(stream, &stream->messages.confirm);
|
|
if (zrtp_status_ok != s) {
|
|
return s;
|
|
}
|
|
|
|
s = _zrtp_packet_fill_msg_hdr( stream,
|
|
ZRTP_CONFIRM2,
|
|
sizeof(zrtp_packet_Confirm_t) - sizeof(zrtp_msg_hdr_t),
|
|
&stream->messages.confirm.hdr);
|
|
|
|
if (zrtp_status_ok == s) {
|
|
task->_is_enabled = 1;
|
|
task->callback = _send_and_resend_confirm2;
|
|
task->_retrys = 0;
|
|
_send_and_resend_confirm2(stream, task);
|
|
}
|
|
|
|
return s;
|
|
}
|