/*----------------------------------------------------------------------------*/ void zrtp_session_down(zrtp_session_t *session) { int i =0; if (!session) { return; } /* Stop ZRTP engine and clear all crypto sources for every stream in the session. */ zrtp_mutex_lock(session->streams_protector); for(i=0; i<ZRTP_MAX_STREAMS_PER_SESSION; i++) { zrtp_stream_t *the_stream = &session->streams[i]; zrtp_stream_stop(the_stream); } zrtp_mutex_unlock(session->streams_protector); /* Release memory allocated on initialization */ if (session->secrets.rs1) { zrtp_sys_free(session->secrets.rs1); } if (session->secrets.rs2) { zrtp_sys_free(session->secrets.rs2); } if (session->secrets.auxs) { zrtp_sys_free(session->secrets.auxs); } if (session->secrets.pbxs) { zrtp_sys_free(session->secrets.pbxs); } /* We don't need the session key anymore - clear it */ zrtp_wipe_zstring(ZSTR_GV(session->zrtpsess)); /* Removing session from the global list */ zrtp_mutex_lock(session->zrtp->sessions_protector); mlist_del(&session->_mlist); zrtp_mutex_unlock(session->zrtp->sessions_protector); zrtp_mutex_destroy(session->streams_protector); zrtp_mutex_destroy(session->init_protector); zrtp_sys_free(session); }
/*---------------------------------------------------------------------------*/ zrtp_status_t _zrtp_machine_enter_secure(zrtp_stream_t* stream) { /* * When switching to SECURE all ZRTP crypto values were already computed by * state-machine. Then we need to have logic to manage SAS value and shared * secrets only. So: we compute SAS, refresh secrets flags and save the * secrets to the cache after RS2 and RS1 swapping. We don't need any * crypto sources any longer - destroy them. */ zrtp_status_t s = zrtp_status_ok; zrtp_proto_crypto_t* cc = stream->protocol->cc; zrtp_session_t *session = stream->session; zrtp_secrets_t *secrets = &stream->session->secrets; uint8_t was_exp = 0; uint64_t exp_date = 0; ZRTP_LOG(3,(_ZTU_,"\tEnter state SECURE (%s).\n", zrtp_log_mode2str(stream->mode))); _zrtp_cancel_send_packet_later(stream, ZRTP_NONE); /* * Compute the SAS value if it isn't computed yet. If there are several * streams running in parallel - stream with the biggest hvi should * generate the SAS. */ if (!session->sas1.length) { s = session->sasscheme->compute(session->sasscheme, stream, session->hash, 0); if (zrtp_status_ok != s) { _zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1); return s; } ZRTP_LOG(3,(_ZTU_,"\tThis is the very first stream in sID GENERATING SAS value.\n", session->id)); ZRTP_LOG(3,(_ZTU_,"\tSAS computed: <%.16s> <%.16s>.\n", session->sas1.buffer, session->sas2.buffer)); } /* * Compute a new value for RS1 and store the prevoious one. * Compute result secrets' flags. */ if (ZRTP_IS_STREAM_DH(stream)) { ZRTP_LOG(3,(_ZTU_,"\tCheck expiration interval: last_use=%u ttl=%u new_ttl=%u exp=%u now=%u\n", secrets->rs1->lastused_at, secrets->rs1->ttl, stream->cache_ttl, (secrets->rs1->lastused_at + secrets->rs1->ttl), zrtp_time_now()/1000)); if (secrets->rs1->ttl != 0xFFFFFFFF) { exp_date = secrets->rs1->lastused_at; exp_date += secrets->rs1->ttl; if (ZRTP_IS_STREAM_DH(stream) && (exp_date < zrtp_time_now()/1000)) { ZRTP_LOG(3,(_ZTU_,"\tUsing EXPIRED secrets: last_use=%u ttl=%u exp=%u now=%u\n", secrets->rs1->lastused_at, secrets->rs1->ttl, (secrets->rs1->lastused_at + secrets->rs1->ttl), zrtp_time_now()/1000)); was_exp = 1; } } if (!was_exp) { secrets->wrongs = secrets->matches ^ secrets->cached; secrets->wrongs &= ~ZRTP_BIT_RS2; secrets->wrongs &= ~ZRTP_BIT_PBX; } } /* * We going to update RS1 and change appropriate secrets flags. Let's back-up current values. * Back-upped values could be used in debug purposes and in the GUI to reflect current state of the call */ if (!ZRTP_IS_STREAM_MULT(stream)) { secrets->cached_curr = secrets->cached; secrets->matches_curr = secrets->matches; secrets->wrongs_curr = secrets->wrongs; } ZRTP_LOG(3,(_ZTU_,"\tFlags C=%x M=%x W=%x ID=%u\n", secrets->cached, secrets->matches, secrets->wrongs, stream->id)); _zrtp_change_state(stream, ZRTP_STATE_SECURE); /* * Alarm user if the following condition is TRUE for both RS1 and RS2: * "secret is wrong if it has been restored from the cache but hasn't matched * with the remote one". */ if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_SECURE); } if (session->zrtp->cb.event_cb.on_zrtp_secure) { session->zrtp->cb.event_cb.on_zrtp_secure(stream); } /* Alarm user if possible MiTM attack detected */ if (secrets->wrongs) { session->mitm_alert_detected = 1; if (session->zrtp->cb.event_cb.on_zrtp_security_event) { session->zrtp->cb.event_cb.on_zrtp_security_event(stream, ZRTP_EVENT_MITM_WARNING); } } /* Check for unenrollemnt first */ if ((secrets->cached & ZRTP_BIT_PBX) && !(secrets->matches & ZRTP_BIT_PBX)) { ZRTP_LOG(2,(_ZTU_,"\tINFO! The user requires new un-enrolment - the nedpint may clear" " the cache or perform other action. ID=%u\n", stream->id)); if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_USER_UNENROLLED); } } /* * Handle PBX registration, if required: If PBX already had a shared secret * for the ZID it leaves the cache entry unmodified. Else, it computes a new * one. If the PBX detects cache entry for the static shared secret, but the * phone does not have a matching cache entry - the PBX generates a new one. */ if (ZRTP_MITM_MODE_REG_SERVER == stream->mitm_mode) { if (secrets->matches & ZRTP_BIT_PBX) { ZRTP_LOG(2,(_ZTU_,"\tINFO! User have been already registered - skip enrollment ritual. ID=%u\n", stream->id)); if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_USER_ALREADY_ENROLLED); } } else { ZRTP_LOG(2,(_ZTU_,"\tINFO! The user requires new enrolment - generate new MiTM secret. ID=%u\n", stream->id)); zrtp_register_with_trusted_mitm(stream); if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { stream->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_NEW_USER_ENROLLED); } } } else if (ZRTP_MITM_MODE_REG_CLIENT == stream->mitm_mode) { if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_CLIENT_ENROLLMENT); } } /* * Compute new RS for FULL DH streams only. Don't update RS1 if cache TTL is 0 */ if (ZRTP_IS_STREAM_DH(stream)) { static const zrtp_string32_t rss_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_RS_STR); if (stream->cache_ttl > 0) { /* Replace RS2 with RS1 */ zrtp_sys_free(secrets->rs2); secrets->rs2 = secrets->rs1; secrets->rs1 = _zrtp_alloc_shared_secret(session); if (!secrets->rs1) { _zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1); return zrtp_status_fail; } /* * Compute new RS1 based on previous one and S0: * rs1 = KDF(s0, "retained secret", KDF_Context, negotiated hash length) */ _zrtp_kdf( stream, ZSTR_GV(cc->s0), ZSTR_GV(rss_label), ZSTR_GV(cc->kdf_context), ZRTP_HASH_SIZE, ZSTR_GV(secrets->rs1->value)); /* * Mark secrets as cached: RS1 have been just generated and cached; * RS2 is cached if previous secret was cached as well. */ secrets->rs1->_cachedflag = 1; secrets->cached |= ZRTP_BIT_RS1; secrets->matches |= ZRTP_BIT_RS1; if (secrets->rs2->_cachedflag) { secrets->cached |= ZRTP_BIT_RS2; } /* Let's update the TTL interval for the new secret */ secrets->rs1->ttl = stream->cache_ttl; secrets->rs1->lastused_at = (uint32_t)(zrtp_time_now()/1000); /* If possible MiTM attach detected - postpone storing the cache until after the user verify the SAS */ if (!session->mitm_alert_detected) { zrtp_cache_put(session->zrtp->cache, ZSTR_GV(session->peer_zid), secrets->rs1); } { uint32_t verifiedflag = 0; char buff[128]; zrtp_cache_get_verified(session->zrtp->cache, ZSTR_GV(session->peer_zid), &verifiedflag); ZRTP_LOG(3,(_ZTU_,"\tNew secret was generated:\n")); ZRTP_LOG(3,(_ZTU_,"\t\tRS1 value:<%s>\n", hex2str(secrets->rs1->value.buffer, secrets->rs1->value.length, buff, sizeof(buff)))); ZRTP_LOG(3,(_ZTU_,"\t\tTTL=%u, flags C=%x M=%x W=%x V=%d\n", secrets->rs1->ttl, secrets->cached, secrets->matches, secrets->wrongs, verifiedflag)); } } /* for TTL > 0 only */ else { secrets->rs1->ttl = 0; zrtp_cache_put(session->zrtp->cache, ZSTR_GV(session->peer_zid), secrets->rs1); } } /* For DH mode only */ if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_IS_SECURE_DONE); } /* We have computed all subkeys from S0 and don't need it any longer. */ zrtp_wipe_zstring(ZSTR_GV(cc->s0)); /* Clear DH crypto context */ if (ZRTP_IS_STREAM_DH(stream)) { bnEnd(&stream->dh_cc.peer_pv); bnEnd(&stream->dh_cc.pv); bnEnd(&stream->dh_cc.sv); zrtp_wipe_zstring(ZSTR_GV(stream->dh_cc.dhss)); } /* * Now, let's check if the transition to CLEAR was caused by Active/Passive rules. * If local endpoint is a MitM and peer MiTM linked stream is Unlimited, we * could break the rules and send commit to Passive endpoint. */ if (stream->zrtp->is_mitm && stream->peer_super_flag) { if (stream->linked_mitm && stream->linked_mitm->peer_passive) { if (stream->linked_mitm->state == ZRTP_STATE_CLEAR) { ZRTP_LOG(2,(_ZTU_,"INFO: Linked Peer stream id=%u suspended in CLEAR-state due to" " Active/Passive restrictions, but we are running in MiTM mode and " "current peer endpoint is Super-Active. Let's Go Secure for the linked stream.\n", stream->id)); /* @note: don't use zrtp_secure_stream() wrapper as it checks for Active/Passive stuff. */ _zrtp_machine_start_initiating_secure(stream->linked_mitm); } } } /* * Increase calls counter for Preshared mode and reset it on DH */ uint32_t calls_counter = 0; zrtp_cache_get_presh_counter(session->zrtp->cache, ZSTR_GV(session->peer_zid), &calls_counter); if (ZRTP_IS_STREAM_DH(stream)) { zrtp_cache_set_presh_counter(session->zrtp->cache, ZSTR_GV(session->peer_zid), 0); } else if ZRTP_IS_STREAM_PRESH(stream) { zrtp_cache_set_presh_counter(session->zrtp->cache, ZSTR_GV(session->peer_zid), ++calls_counter); } clear_crypto_sources(stream); return zrtp_status_ok; }