mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-09 17:26:03 +00:00
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.
233 lines
6.2 KiB
C
233 lines
6.2 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>
|
|
*/
|
|
|
|
#if (defined(ZRTP_USE_EXTERN_SRTP) && (ZRTP_USE_EXTERN_SRTP == 1))
|
|
|
|
/* exactly in this order (for winsock) */
|
|
#include <srtp.h>
|
|
#include "zrtp.h"
|
|
|
|
struct zrtp_srtp_ctx
|
|
{
|
|
srtp_t outgoing_srtp;
|
|
srtp_t incoming_srtp;
|
|
};
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void init_policy(crypto_policy_t *sp, zrtp_srtp_policy_t *zp)
|
|
{
|
|
//TODO: make incoming policy crypto algorithm check for David A. McGrew's implementation support
|
|
|
|
/* there are no another appropriate ciphers in the David A. McGrew's implementation yet */
|
|
sp->cipher_type = AES_128_ICM;
|
|
sp->cipher_key_len = zp->cipher_key_len;
|
|
sp->auth_type = HMAC_SHA1;
|
|
sp->auth_key_len = zp->auth_key_len;
|
|
sp->auth_tag_len = zp->auth_tag_len->tag_length ? zp->auth_tag_len->tag_length : 10;
|
|
sp->sec_serv = sec_serv_conf_and_auth;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t create_srtp_stream( srtp_t *srtp_stream,
|
|
zrtp_srtp_profile_t *profile,
|
|
ssrc_type_t ssrc_type )
|
|
{
|
|
srtp_policy_t policy;
|
|
uint8_t *tmp_key;
|
|
|
|
init_policy(&policy.rtp, &profile->rtp_policy);
|
|
init_policy(&policy.rtcp, &profile->rtcp_policy);
|
|
|
|
policy.ssrc.type = ssrc_type;
|
|
policy.ssrc.value = 0;
|
|
|
|
/* David A. McGrew's implementation uses key and salt as whole buffer, so let's make it */
|
|
tmp_key = (uint8_t*)zrtp_sys_alloc(profile->key.length + profile->salt.length);
|
|
if(NULL == tmp_key){
|
|
return zrtp_status_fail;
|
|
}
|
|
zrtp_memcpy(tmp_key, profile->key.buffer, profile->key.length);
|
|
zrtp_memcpy(tmp_key+profile->key.length, profile->salt.buffer, profile->salt.length);
|
|
|
|
policy.key = tmp_key;
|
|
policy.next = NULL;
|
|
|
|
/* add salt length to the key length of each policy */
|
|
policy.rtp.cipher_key_len += 14;
|
|
policy.rtcp.cipher_key_len += 14;
|
|
|
|
if(err_status_ok != srtp_create(srtp_stream, &policy)){
|
|
zrtp_sys_free(tmp_key);
|
|
return zrtp_status_fail;
|
|
}
|
|
|
|
zrtp_sys_free(tmp_key);
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
|
|
/*===========================================================================*/
|
|
/* Public interface */
|
|
/*===========================================================================*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_srtp_init(zrtp_global_ctx_t *zrtp_global)
|
|
{
|
|
err_status_t s = srtp_init();
|
|
return (err_status_ok == s) ? zrtp_status_ok : s;
|
|
}
|
|
|
|
zrtp_status_t zrtp_srtp_down( zrtp_global_ctx_t *zrtp_global )
|
|
{
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_srtp_ctx_t * zrtp_srtp_create( zrtp_srtp_global_t *srtp_global,
|
|
zrtp_srtp_profile_t *inc_profile,
|
|
zrtp_srtp_profile_t *out_profile)
|
|
{
|
|
zrtp_status_t res = zrtp_status_ok;
|
|
zrtp_srtp_ctx_t *srtp_ctx = NULL;
|
|
|
|
if(NULL == inc_profile || NULL == out_profile){
|
|
return NULL;
|
|
}
|
|
|
|
do{
|
|
srtp_policy_t *policy_head, *policy_next;
|
|
|
|
srtp_ctx = zrtp_sys_alloc(sizeof(zrtp_srtp_ctx_t));
|
|
if(NULL == srtp_ctx){
|
|
break;
|
|
}
|
|
|
|
res = create_srtp_stream(&srtp_ctx->incoming_srtp, inc_profile, ssrc_any_inbound);
|
|
if(zrtp_status_ok != res){
|
|
zrtp_sys_free(srtp_ctx);
|
|
srtp_ctx = NULL;
|
|
break;
|
|
}
|
|
|
|
res = create_srtp_stream(&srtp_ctx->outgoing_srtp, out_profile, ssrc_any_outbound);
|
|
if(zrtp_status_ok != res){
|
|
srtp_dealloc(srtp_ctx->incoming_srtp);
|
|
zrtp_sys_free(srtp_ctx);
|
|
srtp_ctx = NULL;
|
|
break;
|
|
}
|
|
|
|
}while(0);
|
|
|
|
return srtp_ctx;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_srtp_destroy( zrtp_srtp_global_t *zrtp_srtp_global,
|
|
zrtp_srtp_ctx_t *srtp_ctx )
|
|
{
|
|
srtp_dealloc(srtp_ctx->incoming_srtp);
|
|
srtp_dealloc(srtp_ctx->outgoing_srtp);
|
|
zrtp_sys_free(srtp_ctx);
|
|
return zrtp_status_ok;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_srtp_protect( zrtp_srtp_global_t *srtp_global,
|
|
zrtp_srtp_ctx_t *srtp_ctx,
|
|
zrtp_rtp_info_t *packet)
|
|
{
|
|
err_status_t res;
|
|
res = srtp_protect(srtp_ctx->outgoing_srtp, packet->packet, packet->length);
|
|
if(err_status_ok != res){
|
|
return zrtp_status_fail;
|
|
}else{
|
|
return zrtp_status_ok;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_srtp_unprotect( zrtp_srtp_global_t *srtp_global,
|
|
zrtp_srtp_ctx_t *srtp_ctx,
|
|
zrtp_rtp_info_t *packet)
|
|
{
|
|
err_status_t res;
|
|
res = srtp_unprotect(srtp_ctx->incoming_srtp, packet->packet, packet->length);
|
|
if(err_status_ok != res){
|
|
return zrtp_status_fail;
|
|
}else{
|
|
return zrtp_status_ok;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_srtp_protect_rtcp( zrtp_srtp_global_t *srtp_global,
|
|
zrtp_srtp_ctx_t *srtp_ctx,
|
|
zrtp_rtp_info_t *packet)
|
|
{
|
|
err_status_t res;
|
|
res = srtp_protect_rtcp(srtp_ctx->outgoing_srtp, packet->packet, packet->length);
|
|
if(err_status_ok != res){
|
|
return zrtp_status_fail;
|
|
}else{
|
|
return zrtp_status_ok;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
zrtp_status_t zrtp_srtp_unprotect_rtcp( zrtp_srtp_global_t *srtp_global,
|
|
zrtp_srtp_ctx_t *srtp_ctx,
|
|
zrtp_rtp_info_t *packet)
|
|
{
|
|
err_status_t res;
|
|
res = srtp_unprotect_rtcp(srtp_ctx->incoming_srtp, packet->packet, packet->length);
|
|
if(err_status_ok != res){
|
|
return zrtp_status_fail;
|
|
}else{
|
|
return zrtp_status_ok;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
uint64_t make64(uint32_t high, uint32_t low)
|
|
{
|
|
uint64_t_ res;
|
|
uint32_t *p = (uint32_t*)&res;
|
|
|
|
#if ZRTP_BYTE_ORDER == ZBO_LITTLE_ENDIAN
|
|
*p++ = low;
|
|
*p = high;
|
|
#else
|
|
*p++ = high;
|
|
*p = low;
|
|
#endif
|
|
return res;
|
|
}
|
|
|
|
uint32_t high32(uint64_t x)
|
|
{
|
|
uint32_t *p = &x;
|
|
#if ZRTP_BYTE_ORDER == ZBO_LITTLE_ENDIAN
|
|
p++;
|
|
#endif
|
|
return *p;
|
|
}
|
|
|
|
uint32_t low32(uint64_t x)
|
|
{
|
|
uint32_t *p = &x;
|
|
#if ZRTP_BYTE_ORDER == ZBO_BIG_ENDIAN
|
|
p++;
|
|
#endif
|
|
return *p;
|
|
}
|
|
|
|
#endif /*ZRTP_USE_EXTERN_SRTP*/
|