forked from Mirrors/freeswitch
d2edcad66e
Thanks to Phil Zimmermann for the code and for the license exception we needed to include it. There remains some build system integration work to be done before this code will build properly in the FreeSWITCH tree.
388 lines
15 KiB
C
388 lines
15 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>
|
|
*/
|
|
|
|
|
|
#ifndef __ZRTP_ENGINE_H__
|
|
#define __ZRTP_ENGINE_H__
|
|
|
|
#include "zrtp_config.h"
|
|
#include "zrtp_types.h"
|
|
#include "zrtp_crypto.h"
|
|
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
/**
|
|
* @defgroup engine_dev ZRTP Engine related types and functions
|
|
* @ingroup zrtp_dev
|
|
* \{
|
|
*/
|
|
|
|
#define ZRTP_IS_STREAM_DH(stream) \
|
|
(stream->mode == ZRTP_STREAM_MODE_DH)
|
|
|
|
#define ZRTP_IS_STREAM_FAST(stream) \
|
|
(stream->mode != ZRTP_STREAM_MODE_DH)
|
|
|
|
#define ZRTP_IS_STREAM_MULT(stream) \
|
|
(stream->mode == ZRTP_STREAM_MODE_MULT)
|
|
|
|
#define ZRTP_IS_STREAM_PRESH(stream) \
|
|
(stream->mode == ZRTP_STREAM_MODE_PRESHARED)
|
|
|
|
|
|
/**
|
|
* @brief Test Passive Rule N1
|
|
* A passive endpoint never sends a Commit message. Semi-active endpoint does
|
|
* not send a commit to a passive endpoint.
|
|
* Return 1 if the tast have been passed successfully and 0 in other case.
|
|
*/
|
|
#define ZRTP_PASSIVE1_TEST(stream) \
|
|
( (ZRTP_LICENSE_MODE_UNLIMITED == stream->zrtp->lic_mode) || \
|
|
((ZRTP_LICENSE_MODE_ACTIVE == stream->zrtp->lic_mode) && (!stream->messages.peer_hello.pasive)) )
|
|
|
|
/**
|
|
* @brief Test Passive Rule N2
|
|
* A passive phone, if acting as a SIP initiator (meaning it initiated the call),
|
|
* rejects all commit packets from everyone.
|
|
* Return 1 if the tast have been passed successfully and 0 in other case
|
|
*/
|
|
#define ZRTP_PASSIVE2_TEST(stream) \
|
|
( !((ZRTP_LICENSE_MODE_PASSIVE == stream->zrtp->lic_mode) && \
|
|
(stream->session->signaling_role == ZRTP_SIGNALING_ROLE_INITIATOR)) )
|
|
|
|
/**
|
|
* @brief Test Passive Rule N3
|
|
* A passive phone rejects all commit messages from a PBX.
|
|
* Return 1 if the tast have been passed successfully and 0 in other case
|
|
*/
|
|
#define ZRTP_PASSIVE3_TEST(stream) \
|
|
( !(!stream->zrtp->is_mitm && stream->peer_mitm_flag && \
|
|
(ZRTP_LICENSE_MODE_PASSIVE == stream->zrtp->lic_mode)) )
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* PROTOCOL Logic */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* @brief Allocate ZRTP protocol structure
|
|
* Allocates and initializes all necessary data according to the protocol mode.
|
|
* Initializes required DH crypto context info and generates secret IDs.
|
|
* @param stream - stream context in which protocol should be allocated;
|
|
* @param is_initiator - defines protocol type (1 - initiator, 0 - responder).
|
|
* @exception SOFTWARE exceptions.
|
|
*/
|
|
zrtp_status_t _zrtp_protocol_init( zrtp_stream_t *stream,
|
|
uint8_t is_initiator,
|
|
zrtp_protocol_t **proto);
|
|
|
|
/**
|
|
* @brief Release protocol structure
|
|
* Stops all replay tasks, clears all crypto sources and SRTP engine, and
|
|
* releases memory. The protocol should be destroyed on: stream closing, or
|
|
* switching to CLEAR or ERROR states.
|
|
*/
|
|
void _zrtp_protocol_destroy(zrtp_protocol_t *proto);
|
|
|
|
/**
|
|
* @brief Encrypts RTP/RTCP media
|
|
* After switching to Secure, the protocol structure is able to encrypt
|
|
* media using the SRTP crypto-engine.
|
|
* @param self - self-pointer to protocol instance;
|
|
* @param packet - media packet for encryption;
|
|
* @param is_rtp - defines type of media for encryption; value equal to 1
|
|
* means RTP packet, 0 - RTCP.
|
|
* @return
|
|
* - zrtp_status_ok - if successfully encrypted;
|
|
* - one of zrtp_status_t errors otherwise.
|
|
*/
|
|
zrtp_status_t _zrtp_protocol_encrypt( zrtp_protocol_t *proto,
|
|
zrtp_rtp_info_t *packet,
|
|
uint8_t is_rtp);
|
|
|
|
/**
|
|
* @brief Decrypts RTP/RTCP media
|
|
* After switching to Secure, the protocol structure is able to decrypt
|
|
* media using the SRTP crypto-engine.
|
|
* @param self - self-pointer to protocol instance;
|
|
* @param packet - media packet for decryption;
|
|
* @param is_rtp - defines type of media for decryption; value equal to 1
|
|
* means RTP packet, 0 - RTCP.
|
|
* @return
|
|
* - zrtp_status_ok - if successfully decrypted;
|
|
* - one of zrtp_status_t errors otherwise.
|
|
*/
|
|
zrtp_status_t _zrtp_protocol_decrypt( zrtp_protocol_t *self,
|
|
zrtp_rtp_info_t *packet,
|
|
uint8_t is_rtp);
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* CRTPTO Utilities */
|
|
/*===========================================================================*/
|
|
|
|
/**
|
|
* ZRTP KDF function.
|
|
* KDF(KI, Label, Context, L) = HMAC(KI, i | Label | 0x00 | Context | L). See
|
|
* Section "4.5.1. The ZRTP Key Derivation Function" in ZRTP RFC for more info.
|
|
* @param stream - used to obtain negotiated HMAC function and other parameters;
|
|
* @param ki- secret key derivation key that is unknown to the wiretapper
|
|
* (for example, s0);
|
|
* @param label - string of nonzero octets that identifies the purpose for the
|
|
* derived keying material;
|
|
* @param context - includes ZIDi, ZIDr, and some optional nonce material;
|
|
* @param length - needed digest length. (The output of the KDF is truncated to
|
|
* the leftmost length bits);
|
|
* @param digest - destination buffer.
|
|
*/
|
|
zrtp_status_t _zrtp_kdf( zrtp_stream_t* stream,
|
|
zrtp_stringn_t* ki,
|
|
zrtp_stringn_t* label,
|
|
zrtp_stringn_t* context,
|
|
uint32_t length,
|
|
zrtp_stringn_t* digest);
|
|
|
|
/*!
|
|
* \brief Allocate shared secret structure
|
|
* This function allocates memory for a zrtp_shared_secret_t and initializes
|
|
* the secret value using a zrtp_fill_shared_secret() function call. Used in
|
|
* protocol allocating.
|
|
* \param session - ZRTP session for access to global data.
|
|
* \return
|
|
* - allocated secrets - on success;
|
|
* - NULL - if allocation fails.
|
|
*/
|
|
zrtp_shared_secret_t *_zrtp_alloc_shared_secret(zrtp_session_t* session);
|
|
|
|
/*!
|
|
* \brief Restores secrets from the cache
|
|
* Uploads retained secrets from the cache and initializes secret flags. If
|
|
* the secret has expired (is_expired flag is set), its value will be randomly
|
|
* regenerated. _zrtp_prepare_secrets() is called after the discovery phase on
|
|
* the setting up the very first stream. After secrets are uploaded the
|
|
* zrtp_secrets_t#_is_ready flag is enabled to prevent secrets from reinitialization
|
|
* on setting up the next stream.
|
|
* \param session - ZRTP session in which secrets should be restored.
|
|
* - zrtp_status_ok - if secrets were restored successfully;
|
|
* - one of zrtp_status_t errors in case of failure.
|
|
*/
|
|
zrtp_status_t _zrtp_prepare_secrets(zrtp_session_t* session);
|
|
|
|
/**
|
|
* @brief Validate confirm chmac message.
|
|
* In case of chmac failure it switches to Initiating Error state and generate
|
|
* ZRTP_EVENT_WRONG_MESSAGE_HMAC security event.
|
|
* @return
|
|
* -1 - in case of error and 0 - on success.
|
|
*/
|
|
int _zrtp_validate_message_hmac(zrtp_stream_t *stream, zrtp_msg_hdr_t* msg2check, char* hmackey);
|
|
|
|
/**
|
|
* @brief Computes preshared key using available secrets.
|
|
* hash(len(rs1) | rs1 | len(auxsecret) | auxsecret | len(pbxsecret) | pbxsecret)
|
|
* Result key stored in key variable, if key_id not NULL - hmac
|
|
* of the preshared_key will be stored.
|
|
* return
|
|
* - zrtp_status_ok on success and one of libzrtp errors in case of failure
|
|
*/
|
|
zrtp_status_t _zrtp_compute_preshared_key( zrtp_session_t *session,
|
|
zrtp_stringn_t* rs1,
|
|
zrtp_stringn_t* auxs,
|
|
zrtp_stringn_t* pbxs,
|
|
zrtp_stringn_t* key,
|
|
zrtp_stringn_t* key_id);
|
|
|
|
/** @brief Perform Key generation according to ZRTp RFC sec. 5.6 */
|
|
zrtp_status_t _zrtp_set_public_value(zrtp_stream_t *stream, int is_initiator);
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* PROTOCOL Utilites */
|
|
/*===========================================================================*/
|
|
|
|
/*!
|
|
* \brief Check availability to start stream (DH or Preshared)
|
|
* The ZRTP specification says that only one DH stream can be run at a time between
|
|
* two ZRTP endpoints. So _zrtp_can_start_stream(DH) looks over all sessions
|
|
* between two ZIDs and if any other stream is running it denies the start of
|
|
* another DH stream in parallel. Although the ZRTP standard says that Preshared
|
|
* or Multistream stream can't be run in parallel with DH streams between two
|
|
* ZRTP endpoints. So _zrtp_can_start_stream(PRESH) looks over all sessions between
|
|
* two ZIDs and if any other DH stream is running it denies the start of
|
|
* Preshared/Multistream stream in parallel. All operations with sessions and
|
|
* streams are protected by mutexes. Call this function every time before starting
|
|
* "initiating secure" process. For internal use only.
|
|
* \sa "break the tie schemes" internal document.
|
|
* \param stream - ZRTP stream which going to be started;
|
|
* \param conc - in this variable _zrtp_can_start_stream() returns pointer to the
|
|
* concurrent DH stream if it's in progress. It's used in "breaking the tie"
|
|
* scheme.
|
|
* \param mode - stream mode.
|
|
* \return
|
|
* - 1 if stream can be started;
|
|
* - 0 - if stream can't be started and should wait for concurrent stream
|
|
* establishment.
|
|
*/
|
|
int _zrtp_can_start_stream( zrtp_stream_t* stream,
|
|
zrtp_stream_t** conc,
|
|
zrtp_stream_mode_t mode);
|
|
|
|
/** Return ZRTP Stream mode which should be used for current stream. */
|
|
zrtp_stream_mode_t _zrtp_define_stream_mode(zrtp_stream_t* stream);
|
|
|
|
/*!
|
|
* \brief Chooses the best crypto component of the given type
|
|
* Selects the crypto component according to the local initiator's profile and
|
|
* the remote responder's Hello.
|
|
* \param profile - local profile;
|
|
* \param peer_hello - Hello packet, received from the remote peer;
|
|
* \param type - type of the crypto component to be chosen.
|
|
* \return:
|
|
* - identifier of the chosen component (according to type);
|
|
* - ZRTP_COMP_UNKN in case of error.
|
|
*/
|
|
uint8_t _zrtp_choose_best_comp( zrtp_profile_t* profile,
|
|
zrtp_packet_Hello_t* peer_hello,
|
|
zrtp_crypto_comp_t type);
|
|
|
|
/*!
|
|
* \brief Computes replay timeouts
|
|
* This function computes messages replays schedule. There are some recommended
|
|
* values by ZRTP specification, but in some network environments values may be
|
|
* sligh different
|
|
*/
|
|
uint32_t _zrtp_get_timeout(uint32_t curr_timeout, zrtp_msg_type_t msg);
|
|
|
|
|
|
/*!
|
|
* \brief Terminates retransmission task
|
|
* This function is a wrapper around zrtp_cancele_send_packet_later() which
|
|
* unsets the zrtp_retry_task_t#_is_enabled flag to prevent the scheduler from
|
|
* re-adding tasks after their termination.
|
|
*/
|
|
void _zrtp_cancel_send_packet_later( zrtp_stream_t* stream,
|
|
zrtp_msg_type_t type);
|
|
|
|
/*!
|
|
* \brief state switcher
|
|
* This function changes stream state to \c state, makes a backup of the previous
|
|
* state at zrtp_stream_t#_prev_state and prints debug information.
|
|
* \warning Don't change the stream state directly. Use this function.
|
|
* \param stream - ZRTP stream to be changed;
|
|
* \param state - new state.
|
|
*/
|
|
void _zrtp_change_state( zrtp_stream_t* stream, zrtp_state_t state);
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* Shared STATE-MACHINE Routine */
|
|
/*===========================================================================*/
|
|
|
|
// TODO: clean this up
|
|
zrtp_status_t _zrtp_machine_enter_pendingsecure(zrtp_stream_t* stream, zrtp_rtp_info_t* commit);
|
|
zrtp_status_t _zrtp_machine_enter_initiatingsecure(zrtp_stream_t* stream);
|
|
zrtp_status_t _zrtp_machine_enter_secure(zrtp_stream_t* stream);
|
|
zrtp_status_t _zrtp_machine_enter_pendingclear(zrtp_stream_t* stream);
|
|
zrtp_status_t _zrtp_machine_enter_initiatingerror( zrtp_stream_t *stream,
|
|
zrtp_protocol_error_t code,
|
|
uint8_t notif);
|
|
|
|
zrtp_status_t _zrtp_machine_create_confirm(zrtp_stream_t *stream, zrtp_packet_Confirm_t* confirm);
|
|
zrtp_status_t _zrtp_machine_process_confirm(zrtp_stream_t *stream, zrtp_packet_Confirm_t *confirm);
|
|
zrtp_status_t _zrtp_machine_process_goclear(zrtp_stream_t* stream, zrtp_rtp_info_t* packet);
|
|
|
|
zrtp_status_t _zrtp_machine_start_initiating_secure(zrtp_stream_t *stream);
|
|
zrtp_statemachine_type_t _zrtp_machine_preparse_commit(zrtp_stream_t *stream, zrtp_rtp_info_t* packet);
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* PARSERS */
|
|
/*===========================================================================*/
|
|
|
|
/*!
|
|
* \brief Prepare RTP/ZRTP media packet for the further processing.
|
|
* This function defines the packet type, parses SSRC and makes the sequence
|
|
* number implicit. If it is a ZRTP message, packet length correctness and CRC
|
|
* are checked as well.
|
|
* \param stream - ZRTP stream associated with this packet;
|
|
* \param packet - packet for preparing;
|
|
* \param length - packet length;
|
|
* \param info - resulting packet structure;
|
|
* \param is_input - 1 - assumes incoming and 0 - outgoing packet direction.
|
|
*/
|
|
zrtp_status_t _zrtp_packet_preparse( zrtp_stream_t* stream,
|
|
char* packet,
|
|
uint32_t *length,
|
|
zrtp_rtp_info_t* info,
|
|
uint8_t is_input);
|
|
|
|
/*!
|
|
* \brief Fills ZRTP message header and computes messages HMAC
|
|
* _zrtp_packet_fill_msg_hdr() prepares a ZRTP message header for sending. It calculates
|
|
* the total message length in 4-byte words and fills the message type block.
|
|
* \param stream - stream within in the operation will be performed
|
|
* \param type - ZRTP message type;
|
|
* \param body_length - message body length (without header);
|
|
* \param hdr - message ZRTP header
|
|
* \return
|
|
* - zrtp_status_ok - if success;
|
|
* - zrtp_status_bad_param - if message \c type is unknown.
|
|
*/
|
|
zrtp_status_t _zrtp_packet_fill_msg_hdr( zrtp_stream_t *stream,
|
|
zrtp_msg_type_t type,
|
|
uint16_t body_length,
|
|
zrtp_msg_hdr_t *hdr);
|
|
|
|
/**
|
|
* @brief Sends ZRTP message onto the network
|
|
* _zrtp_packet_send_message constructs a ZRTP header and prepares packet for sending,
|
|
* computes CRC and injects the packet into the network using the interface
|
|
* function zrtp_send_rtp().
|
|
* @param ctx - ZRTP stream context;
|
|
* @param type - packet type to construct primitive ZRTP messages;
|
|
* @param message - ZRTP message for sending.
|
|
* @return
|
|
* - 0 - if sent successfully;
|
|
* - -1 - if error.
|
|
*/
|
|
int _zrtp_packet_send_message( zrtp_stream_t *stream,
|
|
zrtp_msg_type_t type,
|
|
const void *message);
|
|
|
|
/** @brief Returns ZRTP message type by symbolic name in header. */
|
|
zrtp_msg_type_t _zrtp_packet_get_type(ZRTP_UNALIGNED(zrtp_rtp_hdr_t)*hdr, uint32_t length);
|
|
|
|
/**
|
|
* @brief Insert CRC32 to ZRTP packets
|
|
* This function computes the 32 bit ZRTP packet checksum according to RFC 3309.
|
|
* As specified at ZRTP RFC, CRC32 is appended to the end of the extension for every ZRTP packet.
|
|
* @param packet - zrtp packet wrapper structure.
|
|
*/
|
|
void _zrtp_packet_insert_crc(char* packet, uint32_t length);
|
|
|
|
/**
|
|
* @brief Validate ZRTP packet CRC
|
|
* @return
|
|
* - 0 if correct CRC;
|
|
* - -1 if CRC validation failed.
|
|
*/
|
|
int8_t _zrtp_packet_validate_crc(const char* packet, uint32_t length);
|
|
|
|
/* \} */
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif /* __ZRTP_ENGINE_H__ */
|