Esempio n. 1
0
/*----------------------------------------------------------------------------*/
zrtp_status_t _zrtp_protocol_decrypt( zrtp_protocol_t *proto,
									  zrtp_rtp_info_t *packet,
									  uint8_t is_rtp)
{
	zrtp_status_t s = zrtp_status_ok;

	if (is_rtp) {
		s = zrtp_srtp_unprotect(proto->context->zrtp->srtp_global, proto->_srtp, packet);
	} else {
		s = zrtp_srtp_unprotect_rtcp(proto->context->zrtp->srtp_global, proto->_srtp, packet);
	}

	if (zrtp_status_ok != s) {
		ZRTP_UNALIGNED(zrtp_rtp_hdr_t) *hdr = (zrtp_rtp_hdr_t*) packet->packet;
		ZRTP_LOG(2,(_ZTU_,"ERROR! Decrypt failed. ID=%u:%s s=%s (%s size=%d ssrc=%u seq=%u/%u pt=%d)\n",
					    proto->context->id,
						zrtp_log_mode2str(proto->context->mode),
						zrtp_log_status2str(s),
						is_rtp ? "RTP" : "RTCP",
						*packet->length,
						zrtp_ntoh32(hdr->ssrc),
						zrtp_ntoh16(hdr->seq),
						packet->seq,
						hdr->pt));
    }

	return s;
}
Esempio n. 2
0
/*----------------------------------------------------------------------------*/
zrtp_status_t _zrtp_machine_process_confirm( zrtp_stream_t *stream,
											 zrtp_packet_Confirm_t *confirm)
{
	/* Compute Hmac over encrypted part of Confirm and reject malformed packets */
	void* cipher_ctx = NULL;
	zrtp_status_t s = zrtp_status_fail;
	zrtp_session_t *session = stream->session;
	zrtp_string128_t hmac = ZSTR_INIT_EMPTY(hmac);

	/* hash + (padding + sig_len + flags) + ttl */
	const uint8_t encrypted_body_size = ZRTP_MESSAGE_HASH_SIZE + (2 + 1 + 1) + 4;
	s = session->hash->hmac_c( session->hash,
							    stream->cc.peer_hmackey.buffer,
							    stream->cc.peer_hmackey.length,
							    (const char*)&confirm->hash,
							    encrypted_body_size,
							    ZSTR_GV(hmac) );
	if (zrtp_status_ok != s) {
		ZRTP_LOG(1,(_ZTU_,"\tERROR! failed to compute Incoming Confirm hmac. s=%d ID=%u\n", s, stream->id));
		return zrtp_status_fail;
	}
    
    
    // MARK: TRACE CONFIRM HMAC ERROR
#if 0
    {
        char buff[512];
        ZRTP_LOG(3,(_ZTU_,"HMAC TRACE. VERIFY\n"));
        ZRTP_LOG(3,(_ZTU_,"\tcipher text:%s. size=%u\n",
                    hex2str((const char*)&confirm->hash, encrypted_body_size, buff, sizeof(buff)), encrypted_body_size));
        ZRTP_LOG(3,(_ZTU_,"\t        key:%s.\n",
                    hex2str(stream->cc.peer_hmackey.buffer, stream->cc.peer_hmackey.length, buff, sizeof(buff))));
        ZRTP_LOG(3,(_ZTU_,"\t comp hmac:%s.\n",
                    hex2str(hmac.buffer, hmac.length, buff, sizeof(buff))));
        ZRTP_LOG(3,(_ZTU_,"\t      hmac:%s.\n",
                    hex2str((const char*)confirm->hmac, ZRTP_HMAC_SIZE, buff, sizeof(buff))));
    }
#endif
    

	if (0 != zrtp_memcmp(confirm->hmac, hmac.buffer, ZRTP_HMAC_SIZE)) {
		/*
		 * Weird. Perhaps a bug in our code or our peer's code. Or it could be an attacker
		 * who doesn't realize that Man-In-The-Middling the Diffie-Hellman key generation
		 * but allowing the correct rsIds to pass through accomplishes nothing more than
		 * forcing us to fallback to cleartext mode. If this attacker had gone ahead and deleted
		 * or replaced the rsIds, then he would have been able to stay in the middle (although
		 * he would of course still face the threat of a Voice Authentication Check).  On the
		 * other hand if this attacker wanted to force us to fallback to cleartext mode, he could
		 * have done that more simply, for example by intercepting our ZRTP HELLO packet and
		 * replacing it with a normal non-ZRTP comfort noise packet.  In any case, we'll do our
		 * "switch to cleartext fallback" behavior.
		 */

		ZRTP_LOG(2,(_ZTU_,"\tWARNING!" ZRTP_VERIFIED_RESP_WARNING_STR "ID=%u\n", stream->id));

		_zrtp_machine_enter_initiatingerror(stream, zrtp_error_auth_decrypt, 1);
		return zrtp_status_fail;
	}

	/* 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*)confirm->iv);
		if (zrtp_status_ok != s) {
			break;
		}

		s = session->blockcipher->decrypt( session->blockcipher,
										    cipher_ctx,
										    (uint8_t*)&confirm->hash,
										    encrypted_body_size);
	} while(0);
	if (cipher_ctx) {
		session->blockcipher->stop(session->blockcipher, cipher_ctx);
	}	
	if (zrtp_status_ok != s) {
		ZRTP_LOG(3,(_ZTU_,"\tERROR! failed to decrypt incoming  Confirm. s=%d ID=%u\n", s, stream->id));
		return s;
	}

	/* We have access to hash field and can check hmac of the previous message */
	{
		zrtp_msg_hdr_t *hdr = NULL;
		char *key=NULL;
		zrtp_string32_t tmphash_str = ZSTR_INIT_EMPTY(tmphash_str);
		zrtp_hash_t *hash = zrtp_comp_find( ZRTP_CC_HASH, ZRTP_HASH_SHA256, stream->zrtp);

		if (ZRTP_IS_STREAM_DH(stream)) {
			hdr = &stream->messages.peer_dhpart.hdr;
			key = (char*)confirm->hash;
		} else {
			hash->hash_c(hash, (char*)confirm->hash, ZRTP_MESSAGE_HASH_SIZE, ZSTR_GV(tmphash_str));

			if (ZRTP_STATEMACHINE_INITIATOR == stream->protocol->type) {
				hdr = &stream->messages.peer_hello.hdr;
				hash->hash_c( hash,
							  tmphash_str.buffer,
						      ZRTP_MESSAGE_HASH_SIZE,
							  ZSTR_GV(tmphash_str) );
			} else {
				hdr = &stream->messages.peer_commit.hdr;
			}
			key = tmphash_str.buffer;
		}

		if (0 != _zrtp_validate_message_hmac(stream, hdr, key)) {
			return zrtp_status_fail;
		}
	}

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

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

	/* Drop RS1 VERIFIED flag if other side didn't verified key exchange */
	if (0 == (confirm->flags & 0x04)) {
		ZRTP_LOG(2,(_ZTU_,"\tINFO: Other side Confirm V=0 - set verified to 0! ID=%u\n", stream->id));
		zrtp_verified_set(session->zrtp, &session->zrtp->zid, &session->peer_zid, 0);
	}

    /* Look for Enrollment replay flag */
	if (confirm->flags & 0x08)
	{
		ZRTP_LOG(2,(_ZTU_,"\tINFO: Confirm PBX Enrolled flag is set - it is a Registration call! ID=%u\n", stream->id));

		if (stream->mitm_mode != ZRTP_MITM_MODE_CLIENT) {
			ZRTP_LOG(2,(_ZTU_,"\tERROR: PBX enrollment flag was received in wrong MiTM mode %s."
						" ID=%u\n", zrtp_log_mode2str(stream->mode), stream->id));			
			_zrtp_machine_enter_initiatingerror(stream, zrtp_error_invalid_packet, 1);
			return zrtp_status_fail;
		}
		
		/* Passive endpoint should ignore PBX Enrollment. */
		if (ZRTP_LICENSE_MODE_PASSIVE != stream->zrtp->lic_mode) {
			stream->mitm_mode = ZRTP_MITM_MODE_REG_CLIENT;
		} else {
			ZRTP_LOG(2,(_ZTU_,"\tINFO: Ignore PBX Enrollment flag as we are Passive ID=%u\n", stream->id));			
		}
	}

	stream->cache_ttl = ZRTP_MIN(session->profile.cache_ttl, zrtp_ntoh32(confirm->expired_interval));

	/* Copy packet for future hashing */
	zrtp_memcpy(&stream->messages.peer_confirm, confirm, zrtp_ntoh16(confirm->hdr.length)*4);

	return zrtp_status_ok;
}
Esempio n. 3
0
void *process_incoming(void *param)
#endif
{
	zrtp_endpoint_t *the_endpoint = (zrtp_endpoint_t *)param;

	while (the_endpoint->is_running) {
		zrtp_test_packet_t* packet = NULL;
		zrtp_queue_elem_t* elem = NULL;
		zrtp_status_t s = zrtp_status_fail;
		zrtp_test_stream_t *stream;
		int is_protocol = 0;

		// TODO: use peak to not to block processing if queue for this stream is empty
		elem = zrtp_test_queue_pop(the_endpoint->input_queue);
		if (!elem || elem->size <= 0) {
			if (elem) zrtp_sys_free(elem);
			break;
		}

		packet = (zrtp_test_packet_t*) elem->data;
		zrtp_test_id_t stream_id;
		{
			if (packet->is_rtp) {
				ZRTP_UNALIGNED(zrtp_rtp_hdr_t) *rtp_hdr = (zrtp_rtp_hdr_t*)packet->body;
				stream_id = zrtp_ntoh32(rtp_hdr->ssrc); /* remember, we use stream Id as it's RTP SSRC */
			} else {
				ZRTP_UNALIGNED(zrtp_rtcp_hdr_t) *rtcp_hdr = (zrtp_rtcp_hdr_t*)packet->body;
				stream_id = zrtp_ntoh32(rtcp_hdr->ssrc); /* remember, we use stream Id as it's RTP SSRC */
			}
			stream = zrtp_test_stream_by_peerid(stream_id);
		}

		/*
		 * Process incoming packet by libzrtp. Is this a RTP media packet - copy it to the buffer
		 * to print out later.
		 */
		if (packet->is_rtp) {
			s = zrtp_process_srtp(stream->zrtp, packet->body, &packet->length);
		} else {
			s = zrtp_process_srtcp(stream->zrtp, packet->body, &packet->length);
		}

		if (!is_protocol) {
			char *body;
			if (packet->is_rtp) {
				body = packet->body + sizeof(zrtp_rtp_hdr_t);
				body[packet->length - sizeof(zrtp_rtp_hdr_t)] = 0;
			} else {
				body = packet->body + sizeof(zrtp_rtcp_hdr_t);
				body[packet->length - sizeof(zrtp_rtcp_hdr_t)] = 0;
			}

			switch (s)
			{
			case zrtp_status_ok: {
				ZRTP_LOG(1, (_ZTU_,"Incoming: (%s) [%p:ssrc=%u] OK. <%s> decrypted %d bytes.\n",
						zrtp_log_state2str(stream->zrtp->state), stream->zrtp,  stream->id, body, packet->length));
			} break;

			case zrtp_status_drop: {
				ZRTP_LOG(1, (_ZTU_,"Incoming: (%s) [%p:ssrc=%u] DROPPED. <%s>\n",
						zrtp_log_state2str(stream->zrtp->state), stream->zrtp, stream->id, body));
			} break;

			case zrtp_status_fail: {
				ZRTP_LOG(1, (_ZTU_,"Incoming: (%s) [%p:ssrc=%u] DECRYPT FAILED. <%s>\n",
						zrtp_log_state2str(stream->zrtp->state), stream->zrtp, stream->id, body));
			} break;

			default:
				break;
			}
		}

		zrtp_sys_free(elem);

		/*
		 * When zrtp_stream is in the pending clear state and other side wants to send plain
		 * traffic. We have to call zrtp_clear_stream().
		 */
		if (stream->zrtp->state == ZRTP_STATE_PENDINGCLEAR) {
			zrtp_stream_clear(stream->zrtp);
		}
	}
#if   (ZRTP_PLATFORM == ZP_WIN32) || (ZRTP_PLATFORM == ZP_WINCE)
	return 0;
#else
	return NULL;
#endif
}