The libzrtp library consists of three main components: the protocol module responsible for the safe connection of a call, the encryption module, and a set of interfaces. ZRTP works by assuming control of the VoIP traffic and initiating an encrypted connection between two ZRTP endpoints after a safe mode is achieved. To integrate the library, please review our documentation on the ZRTP interfaces, connections management, and integration plan.
To provide portability, libzrtp uses a set of system-dependent functions as a set of interfaces, which are divided into the following groups:
libzrtp requires some retrofit work, where the developer will need to write about 15 to 20 lines of code. To see how the library works, please refer to the libzrtp_test application, described in detail in Guide to the libZRTP Test Suite.
typedef struct testcon { zrtp_conn_ctx_t zsession; zrtp_stream_ctx_t* audio; // ZRTP stream for voice encr zrtp_stream_ctx_t* video; // ZRTP stream for video encr. } testcon_t; testcon_t safe_connection; zrtp_global_t zrtp_global; // persistent storage for libzrtp data if ( zrtp_status_ok != zrtp_init(&zrtp_global, "zrtp_testapp") ) { // Some error during initialization } // library has been initialized and is ready to use . .
if (zrtp_status_ok == zrtp_init_session_ctx( &safe_connection.zsession, &zrtp_global, NULL; zid) ) { // // New ZRTP session with default options has been created - // attaching streams. (Voice and then video) // safe_connection->audio = zrtp_attach_stream(safe_connection->zsession, audio_ssrc); safe_connection->video = zrtp_attach_stream(safe_connection->zsession, video_ssrc); if ( !safe_connection->video || !safe_connection->audio ) { // Session stack is overflow or some other error } }
// Starting protocol for both streams if( ztyp_status_ok != zrtp_start_stream(safe_connection->audio) ) { // ZRTP stream can't be started: see log file } if( ztyp_status_ok != zrtp_start_stream(safe_connection->video) ) { // ZRTP stream can't be started: see log file }
The three steps above create the encrypted channel. After entering the "Secure" state, you provide a plain packet to the library and receive an encrypted packet ready to be sent. Decryption works in the analogous way.
zrtp_status_t status = zrtp_status_fail; char packetp[MAX_RTP_SIZE]; int size = 0; // some abstract function for packets receiving size = get_packet(packet); // // Processing incoming packets. // You must determine media type and choose corresponding ZRTP stream // status = zrtp_process_srtp(safe_connection->voice/video, packet, &size); switch (status) { case zrtp_status_forward: case zrtp_status_ok: // // Packet was successfully decrypted. Dont forget that packet // size was changed during decryption. New size now in size // case zrtp_status_drop: // // This is a protocol ZRTP packet or masked RTP media. // In either case the packet must be dropped to protect your // media codec case zrtp_status_fail: // // This is some kind of error - see logs for more information // }
void zrtp_event_callback(zrtp_event_t event, zrtp_stream_ctx_t *ctx) { test_options_t* info; // some user-defined stream options switch (event) { case ZRTP_EVENT_IS_SECURE: // Get shared secrets creation time-stamp. Can be used for displaying at // GUI or for other purposes. info->secure_since = ctx->_session_ctx->secrets._rs1->crated_at; // Get verification flag. MUST be displayed if application supports // secrets' cache. Use the zrtp_set_verified() function to change this // value. info->is_verified = ctx->_session_ctx->secrets.verifieds & ZRTP_BIT_RS0; // Copy shot authentication strings. As we used default stream options // the SAS type should be base256 and rendered as a 2-part string. memcpy(&info->sas1, &ctx->_session_ctx->sas_values.str1.buffer, ctx->_session_ctx->sas_values.str1.length); memcpy(&info->sas2, &ctx->_session_ctx->sas_values.str2.buffer, ctx->_session_ctx->sas_values.str2.length); // Obtain other stream options: // "Allow Clear" - to enable "go clear button" if our GUI has it; // "Disclose bit" - to alert user if remote peer has a shared stream key. info->allowclear = ctx->allowclear; info->disclose_bit = ctx->peer_disclose_bit; break; } // ... // handle other events there default: break; } // end events case }
An overview for closing an secure channel using libzrtp:
zrtp_done_session_ctx(&safe_connection->zsession);
zrtp_down(&zrtp_global);