diff --git a/build_inplace b/build_inplace index 2456f657..cfbaa33d 100755 --- a/build_inplace +++ b/build_inplace @@ -1,9 +1,8 @@ #!/bin/sh -chmod +x extract_pjsip.sh -./extract_pjsip.sh +./get_dependencies.sh chmod +x deps/pjsip/configure chmod +x deps/pjsip/aconfigure python3 setup.py build_ext --inplace "$@" test -d build && python3 setup.py clean diff --git a/deps/update_pjsip_210/patches/pjsip_210.patch b/deps/patches/001_pjsip_210.patch similarity index 100% rename from deps/update_pjsip_210/patches/pjsip_210.patch rename to deps/patches/001_pjsip_210.patch diff --git a/deps/update_pjsip_210/patches/zsrtp.patch b/deps/patches/002_zsrtp.patch similarity index 100% rename from deps/update_pjsip_210/patches/zsrtp.patch rename to deps/patches/002_zsrtp.patch diff --git a/deps/patches/001_pjsip_tls_log_fix.patch b/deps/patches/003_pjsip_tls_log_fix.patch similarity index 100% rename from deps/patches/001_pjsip_tls_log_fix.patch rename to deps/patches/003_pjsip_tls_log_fix.patch diff --git a/deps/pjsip-2.10.tgz b/deps/pjsip-2.10.tgz deleted file mode 100644 index ddf5ac09..00000000 Binary files a/deps/pjsip-2.10.tgz and /dev/null differ diff --git a/deps/update_pjsip_210/README b/deps/update_pjsip_210/README deleted file mode 100644 index 4da44aa7..00000000 --- a/deps/update_pjsip_210/README +++ /dev/null @@ -1,18 +0,0 @@ -This patch must be applied once, on top of the darcs tag: - -before-pjsip-210 - -The following patches have been preserved as a reference for future -upgrades: - - - deps/update_pjsip_210/patches/pjsip_210.patch - - deps/update_pjsip_210/patches/zsrtp.patch - -SIP SIMPLE SDK depends hereinafter upon the following third party sources: - -- PJSIP base revision 210 from 2020-02-14 - https://github.com/pjsip/pjproject/archive/2.10.tar.gz - -- ZRTP tag 6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03 - https://github.com/wernerd/ZRTPCPP.git - diff --git a/deps/update_pjsip_210/TODO b/deps/update_pjsip_210/TODO deleted file mode 100644 index cdf6c626..00000000 --- a/deps/update_pjsip_210/TODO +++ /dev/null @@ -1,4 +0,0 @@ - * Opus codec not working - * Allow build without video support --disable-video - * Mac compilation problem - * Test Windows build diff --git a/deps/update_pjsip_210/patches/sipsimple_core.patch b/deps/update_pjsip_210/patches/sipsimple_core.patch deleted file mode 100644 index f249dfed..00000000 --- a/deps/update_pjsip_210/patches/sipsimple_core.patch +++ /dev/null @@ -1,367 +0,0 @@ -diff -ruN sipsimple/configuration/settings.py sipsimple/configuration/settings.py ---- sipsimple/configuration/settings.py 2021-02-18 22:20:23.927865045 +0100 -+++ sipsimple/configuration/settings.py 2021-02-06 20:08:25.900660619 +0100 -@@ -69,7 +69,7 @@ - port_range = Setting(type=PortRange, default=PortRange(50000, 50500)) - timeout = Setting(type=NonNegativeInteger, default=30) - audio_codec_list = Setting(type=AudioCodecList, default=AudioCodecList(('opus', 'G722', 'PCMU', 'PCMA'))) -- video_codec_list = Setting(type=VideoCodecList, default=VideoCodecList(('H264', 'VP8'))) -+ video_codec_list = Setting(type=VideoCodecList, default=VideoCodecList(('H264', 'VP8', 'VP9'))) - - - def sip_port_validator(port, sibling_port): -diff -ruN sipsimple/configuration/datatypes.py sipsimple/configuration/datatypes.py ---- sipsimple/configuration/datatypes.py 2021-02-18 22:20:23.927865045 +0100 -+++ sipsimple/configuration/datatypes.py 2021-02-06 20:08:25.900660619 +0100 -@@ -269,7 +269,7 @@ - - - class VideoCodecList(CodecList): -- available_values = {'H264', 'VP8'} -+ available_values = {'H264', 'VP8', 'VP9'} - - - # Address and transport datatypes -diff -ruN sipsimple/core/_core.lib.pxi sipsimple/core/_core.lib.pxi ---- sipsimple/core/_core.lib.pxi 2021-02-18 22:20:23.927865045 +0100 -+++ sipsimple/core/_core.lib.pxi 2021-02-06 20:08:25.900660619 +0100 -@@ -146,7 +146,7 @@ cdef class PJSIPEndpoint: - self._make_local_addr(&local_addr, self._local_ip_used, port) - pjsip_tls_setting_default(&tls_setting) - # The following value needs to be reasonably low, as TLS negotiation hogs the PJSIP polling loop -- tls_setting.timeout.sec = self._tls_timeout / 1000 -+ tls_setting.timeout.sec = (self._tls_timeout / 1000) - tls_setting.timeout.msec = self._tls_timeout % 1000 - if self._tls_ca_file is not None: - tls_setting.ca_list_file = self._tls_ca_file.pj_str -@@ -181,13 +181,13 @@ cdef class PJSIPEndpoint: - if resolver == NULL: - raise SIPCoreError("Could not get DNS resolver on endpoint") - -- pj_servers = malloc(sizeof(pj_str_t)*num_servers) -+ pj_servers = malloc(sizeof(pj_str_t)) - if pj_servers == NULL: - raise MemoryError() - -- for i, ns in enumerate(servers): -- _str_to_pj_str(ns.encode(), &pj_servers[i]) -- status = pj_dns_resolver_set_ns(resolver, num_servers, pj_servers, NULL) -+ # set only 1st nameserver -+ _str_to_pj_str(servers[0].encode(), &pj_servers[0]) -+ status = pj_dns_resolver_set_ns(resolver, 1, pj_servers, NULL) - free(pj_servers) - if status != 0: - raise PJSIPError("Could not set nameservers on DNS resolver", status) -@@ -269,7 +269,7 @@ - if status != 0: - raise PJSIPError("Could not initialize ffmpeg video codecs", status) - self._has_ffmpeg_video = 1 -- status = pjmedia_codec_vpx_init(NULL, &caching_pool._obj.factory) -+ status = pjmedia_codec_vpx_vid_init(NULL, &caching_pool._obj.factory) - if status != 0: - raise PJSIPError("Could not initialize vpx video codecs", status) - self._has_vpx = 1 -@@ -284,7 +284,7 @@ - if self._has_ffmpeg_video: - pjmedia_codec_ffmpeg_vid_deinit() - if self._has_vpx: -- pjmedia_codec_vpx_deinit() -+ pjmedia_codec_vpx_vid_deinit() - if pjmedia_vid_codec_mgr_instance() != NULL: - pjmedia_vid_codec_mgr_destroy(NULL) - if pjmedia_event_mgr_instance() != NULL: -@@ -298,7 +298,6 @@ - cdef unsigned int count = PJMEDIA_CODEC_MGR_MAX_CODECS - cdef pjmedia_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS] - cdef unsigned int prio[PJMEDIA_CODEC_MGR_MAX_CODECS] -- cdef int i - cdef list retval - cdef int status - status = pjmedia_codec_mgr_enum_codecs(pjmedia_endpt_get_codec_mgr(self._obj), &count, info, prio) -@@ -343,7 +342,7 @@ - all_codecs = set(self._get_all_codecs()) - codec_set = new_codecs.difference(all_codecs) - if len(codec_set) > 0: -- raise SIPCoreError("Unknown audio codecs: %s" % codec_set) -+ raise SIPCoreError("Unknown audio codecs: %s" % ", ".join(cdc.decode() for cdc in codec_set)) - # reverse the codec data tuples so that we can easily sort on sample rate - # to make sure that bigger sample rates get higher priority - codecs = [list(reversed(codec_data)) for codec_data in self._get_codecs()] -@@ -372,7 +371,6 @@ - cdef unsigned int count = PJMEDIA_VID_CODEC_MGR_MAX_CODECS - cdef pjmedia_vid_codec_info info[PJMEDIA_VID_CODEC_MGR_MAX_CODECS] - cdef unsigned int prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS] -- cdef int i - cdef list retval - cdef int status - status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, info, prio) -@@ -415,7 +413,7 @@ - raise ValueError("Requested video codec list contains doubles") - codec_set = new_codecs.difference(set(self._get_all_video_codecs())) - if len(codec_set) > 0: -- raise SIPCoreError("Unknown video codecs: %s" % codec_set) -+ raise SIPCoreError("Unknown video codecs: %s" % ", ".join(cdc.decode() for cdc in codec_set)) - codecs = self._get_video_codecs() - codec_prio = list() - for codec in req_codecs: -@@ -443,7 +441,6 @@ - cdef pjmedia_vid_codec_info info[PJMEDIA_VID_CODEC_MGR_MAX_CODECS] - cdef pjmedia_vid_codec_param vparam - cdef unsigned int prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS] -- cdef int i - cdef int status - cdef PJSTR h264_profile_level_id_value - cdef PJSTR h264_packetization_mode_value = PJSTR(b"1") # TODO; make it configurable? -@@ -482,7 +479,6 @@ - cdef pjmedia_vid_codec_info info[PJMEDIA_VID_CODEC_MGR_MAX_CODECS] - cdef pjmedia_vid_codec_param vparam - cdef unsigned int prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS] -- cdef int i - cdef int status - - max_width, max_height = max_resolution -diff -ruN sipsimple/core/_core.mediatransport.pxi sipsimple/core/_core.mediatransport.pxi ---- sipsimple/core/_core.mediatransport.pxi 2021-02-18 22:20:23.931865157 +0100 -+++ sipsimple/core/_core.mediatransport.pxi 2021-02-16 02:49:03.872618274 +0100 -@@ -397,7 +397,7 @@ - pj_remote_sdp = NULL - if sdp_index < 0: - raise ValueError("sdp_index argument cannot be negative") -- if sdp_index >= pj_local_sdp.media_count: -+ if sdp_index >= pj_local_sdp.media_count: - raise ValueError("sdp_index argument out of range") - with nogil: - status = pjmedia_transport_media_create(transport, pool, 0, pj_remote_sdp, sdp_index) -@@ -488,7 +488,6 @@ - def set_INIT(self): - global _ice_cb - cdef int af -- cdef int i - cdef int status - cdef int port - cdef pj_caching_pool *caching_pool -@@ -882,7 +881,7 @@ - pj_remote_sdp = NULL - if sdp_index < 0: - raise ValueError("sdp_index argument cannot be negative") -- if sdp_index >= pj_local_sdp.media_count: -+ if sdp_index >= pj_local_sdp.media_count: - raise ValueError("sdp_index argument out of range") - # Remove ICE and SRTP/ZRTP related attributes from SDP, they will be added by pjmedia_transport_encode_sdp - local_media = local_sdp.media[sdp_index] -diff -ruN sipsimple/core/_core.pxd sipsimple/core/_core.pxd ---- sipsimple/core/_core.pxd 2021-02-18 22:20:23.935865270 +0100 -+++ sipsimple/core/_core.pxd 2021-02-06 20:02:57.495316125 +0100 -@@ -1,4 +1,4 @@ --# cython: language_level=2 -+# cython: language_level=3 - - cdef extern from *: - ctypedef char *char_ptr_const "const char *" -@@ -906,8 +906,8 @@ - int pjmedia_codec_register_audio_codecs(pjmedia_endpt *endpt, const pjmedia_audio_codec_config *c) nogil - int pjmedia_codec_ffmpeg_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf) nogil - int pjmedia_codec_ffmpeg_vid_deinit() nogil -- int pjmedia_codec_vpx_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf) nogil -- int pjmedia_codec_vpx_deinit() nogil -+ int pjmedia_codec_vpx_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf) nogil -+ int pjmedia_codec_vpx_vid_deinit() nogil - - cdef extern from "pjsip.h": - -diff -ruN sipsimple/core/_core.sdp.pxi sipsimple/core/_core.sdp.pxi ---- sipsimple/core/_core.sdp.pxi 2021-02-18 22:20:23.995866960 +0100 -+++ sipsimple/core/_core.sdp.pxi 2021-02-06 19:30:28.787506745 +0100 -@@ -966,7 +966,6 @@ - - cdef SDPSession SDPSession_create(pjmedia_sdp_session_ptr_const pj_session): - cdef SDPConnection connection = None -- cdef int i - if pj_session.conn != NULL: - connection = SDPConnection_create(pj_session.conn) - return SDPSession(_pj_str_to_bytes(pj_session.origin.addr), -@@ -985,7 +984,6 @@ - - cdef FrozenSDPSession FrozenSDPSession_create(pjmedia_sdp_session_ptr_const pj_session): - cdef FrozenSDPConnection connection = None -- cdef int i - if pj_session.conn != NULL: - connection = FrozenSDPConnection_create(pj_session.conn) - return FrozenSDPSession(_pj_str_to_bytes(pj_session.origin.addr), -@@ -1004,7 +1002,6 @@ - - cdef SDPMediaStream SDPMediaStream_create(pjmedia_sdp_media *pj_media): - cdef SDPConnection connection = None -- cdef int i - if pj_media.conn != NULL: - connection = SDPConnection_create(pj_media.conn) - return SDPMediaStream(_pj_str_to_bytes(pj_media.desc.media), -@@ -1018,7 +1015,6 @@ - - cdef FrozenSDPMediaStream FrozenSDPMediaStream_create(pjmedia_sdp_media *pj_media): - cdef FrozenSDPConnection connection = None -- cdef int i - if pj_media.conn != NULL: - connection = FrozenSDPConnection_create(pj_media.conn) - return FrozenSDPMediaStream(_pj_str_to_bytes(pj_media.desc.media), -diff -ruN sipsimple/core/_core.ua.pxi sipsimple/core/_core.ua.pxi ---- sipsimple/core/_core.ua.pxi 2021-02-18 22:20:24.003867185 +0100 -+++ sipsimple/core/_core.ua.pxi 2021-02-06 19:30:46.520008320 +0100 -@@ -1075,8 +1075,6 @@ - cdef pjmedia_sdp_session *sdp - cdef pjmedia_sdp_media *media - cdef pjmedia_sdp_attr *attr -- cdef int i -- cdef int j - cdef pj_str_t new_value - try: - ua = _get_ua() -@@ -1133,10 +1131,10 @@ cdef int _cb_opus_fix_rx(pjsip_rx_data *rdata) with gil: - if pos1 != -1: - pos2 = body_str.find("opus/48000/2") - if pos2 != -1: -- memcpy(body_ptr + pos2 + 11, '1', 1) -+ memcpy(body_ptr + pos2 + 11, b'1', 1) - else: - # old opus, we must make it fail -- memcpy(body_ptr + pos1 + 5, 'XXXXX', 5) -+ memcpy(body_ptr + pos1 + 5, b'XXXXX', 5) - except: - ua._handle_exception(0) - return 0 -diff -ruN sipsimple/core/_core.util.pxi sipsimple/core/_core.util.pxi ---- sipsimple/core/_core.util.pxi 2021-02-18 22:20:24.051868537 +0100 -+++ sipsimple/core/_core.util.pxi 2021-02-06 20:14:30.530825814 +0100 -@@ -219,7 +219,7 @@ - cdef pjsip_ctype_hdr *ctype_header - cdef pjsip_cseq_hdr *cseq_header - cdef char *buf -- cdef int buf_len, i, status -+ cdef int buf_len, status - headers = {} - header = ( &msg.hdr).next - while header != &msg.hdr: -@@ -229,8 +229,9 @@ - if header_name in ("Accept", "Allow", "Require", "Supported", "Unsupported", "Allow-Events"): - array_header = header - header_data = [] -- for i from 0 <= i < array_header.count: -- header_data.append(_pj_str_to_bytes(array_header.values[i])) -+ if array_header.count < 128: -+ for i from 0 <= i < array_header.count: -+ header_data.append(_pj_str_to_bytes(array_header.values[i])) - elif header_name == "Contact": - multi_header = True - header_data = FrozenContactHeader_create( header) ---- sipsimple/core/_core.pyx 2021-03-19 03:05:47.796725137 +0100 -+++ sipsimple/core/_core.pyx 2021-03-11 10:29:24.029286901 +0100 -@@ -21,7 +21,7 @@ - - PJ_VERSION = pj_get_version() - PJ_SVN_REVISION = int(PJ_SVN_REV) --CORE_REVISION = 183 -+CORE_REVISION = 210 - - # exports - ---- sipsimple/core/_core.sound.pxi -+++ sipsimple/core/_core.sound.pxi -@@ -48,12 +48,12 @@ cdef class AudioMixer: - self._snd_pool = snd_pool - with nogil: - status = pjmedia_conf_create(conf_pool, slot_count+1, sample_rate, 1, -- sample_rate / 50, 16, PJMEDIA_CONF_NO_DEVICE, conf_bridge_address) -+ (sample_rate / 50), 16, PJMEDIA_CONF_NO_DEVICE, conf_bridge_address) - if status != 0: - raise PJSIPError("Could not create audio mixer", status) - with nogil: - status = pjmedia_null_port_create(conf_pool, sample_rate, 1, -- sample_rate / 50, 16, null_port_address) -+ (sample_rate / 50), 16, null_port_address) - if status != 0: - raise PJSIPError("Could not create null audio port", status) - self._start_sound_device(ua, input_device, output_device, ec_tail_length) -@@ -377,7 +377,7 @@ cdef class AudioMixer: - port_param.base.rec_id = input_device_i - port_param.base.channel_count = 1 - port_param.base.clock_rate = sample_rate -- port_param.base.samples_per_frame = sample_rate / 50 -+ port_param.base.samples_per_frame = (sample_rate / 50) - port_param.base.bits_per_sample = 16 - port_param.base.flags |= (PJMEDIA_AUD_DEV_CAP_EC | PJMEDIA_AUD_DEV_CAP_EC_TAIL) - port_param.base.ec_enabled = 1 -@@ -672,7 +672,7 @@ cdef class ToneGenerator: - self.mixer = mixer - with nogil: - status = pjmedia_tonegen_create(pool, sample_rate, 1, -- sample_rate / 50, 16, 0, port_address) -+ (sample_rate / 50), 16, 0, port_address) - if status != 0: - raise PJSIPError("Could not create tone generator", status) - -@@ -949,7 +949,7 @@ cdef class RecordingWaveFile: - with nogil: - status = pjmedia_wav_writer_port_create(pool, filename, - sample_rate, 1, -- sample_rate / 50, 16, -+ (sample_rate / 50), 16, - PJMEDIA_FILE_WRITE_PCM, 0, port_address) - if status != 0: - raise PJSIPError("Could not create WAV file", status) -@@ -1290,7 +1290,7 @@ cdef class MixerPort: - self._pool = pool - try: - with nogil: -- status = pjmedia_mixer_port_create(pool, sample_rate, 1, sample_rate / 50, 16, port_address) -+ status = pjmedia_mixer_port_create(pool, sample_rate, 1, (sample_rate / 50), 16, port_address) - if status != 0: - raise PJSIPError("Could not create WAV file", status) - self._slot = self.mixer._add_port(ua, self._pool, self._port) ---- sipsimple/core/__init__.py 2021-03-19 02:52:29.930211280 +0100 -+++ sipsimple/core/__init__.py 2021-03-11 10:29:24.021286694 +0100 -@@ -4,7 +4,7 @@ - from sipsimple.core._helpers import * - from sipsimple.core._primitives import * - --required_revision = 183 -+required_revision = 210 - if CORE_REVISION != required_revision: - raise ImportError("Wrong SIP core revision %d (expected %d)" % (CORE_REVISION, required_revision)) - del required_revision ---- sipsimple/util/_sha1.pyx -+++ sipsimple/util/_sha1.pyx -@@ -1,4 +1,4 @@ --# cython: language_level=2 -+# cython: language_level=3 - - __all__ = ['sha1'] - -@@ -17,7 +17,7 @@ cdef extern from "_sha1.h": - SHA1_DIGEST_SIZE = 20 - - ctypedef struct sha1_context: -- uint32_t state[SHA1_DIGEST_SIZE/4] # state variables -+ uint32_t state[(SHA1_DIGEST_SIZE/4)] # state variables - uint64_t count # 64-bit block count - uint8_t block[SHA1_BLOCK_SIZE] # data block buffer - uint32_t index # index into buffer -@@ -49,7 +49,7 @@ cdef class sha1(object): - return SHA1_DIGEST_SIZE - - def __reduce__(self): -- state_variables = [self.context.state[i] for i in range(sizeof(self.context.state)/4)] -+ state_variables = [self.context.state[i] for i in range(sizeof(self.context.state)/4)] - block = PyBytes_FromStringAndSize(self.context.block, self.context.index) - return self.__class__, (), (state_variables, self.context.count, block) - ---- sipsimple/__info__.py 2021-04-10 16:18:54.429724067 +0200 -+++ sipsimple/__info__.py 2021-04-10 16:19:16.690349803 +0200 -@@ -5,7 +5,7 @@ - __summary__ = "SIP SIMPLE implementation for Python" - __webpage__ = "https://sipsimpleclient.org" - --__version__ = "4.0.3" -+__version__ = "5.0.2" - - __author__ = "AG Projects" - __email__ = "support@ag-projects.com" diff --git a/deps/update_pjsip_210/update_pjsip.sh b/deps/update_pjsip_210/update_pjsip.sh deleted file mode 100755 index 4c3f626c..00000000 --- a/deps/update_pjsip_210/update_pjsip.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash - - -# -# Revert all non-commited changes -# - -echo -echo "Revert uncommitted changes..." -echo - -darcs revert -a - -# -# Update PJSIP -# -# Get latest stable release from github -if [ ! -f 2.10.tar.gz ]; then - echo Downloading PJSIP 2.10... - wget https://github.com/pjsip/pjproject/archive/2.10.tar.gz - if [ $? -eq 0 ]; then - echo "PJSIP downloaded" - else - echo Fail to download PJSIP - exit 1 - fi -fi - -tar xzf 2.10.tar.gz - -echo -echo Copying old files -mkdir old -mv ../pjsip old/ -echo Updating pjsip -mv pjproject* ../pjsip - -# -# Update ZSRTP -# - -# Clone latest version from github -if [ ! -d ZRTPCPP ]; then - echo Downloading ZRTP... - git clone https://github.com/wernerd/ZRTPCPP.git - if [ $? -eq 0 ]; then - echo "ZRTP downloaded" - cd ZRTPCPP - git checkout 6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03 - cd .. - else - echo Fail to download ZRTP - exit 1 - fi -fi - -# Copy wrapper from old version to third_party/zsrtp/ -echo Copying zsrtp wrapper from old version to third_party/zsrtp/ -mkdir ../pjsip/third_party/zsrtp -cp -r old/pjsip/third_party/zsrtp/include ../pjsip/third_party/zsrtp/ -cp -r old/pjsip/third_party/zsrtp/srtp ../pjsip/third_party/zsrtp/ -cp -r old/pjsip/third_party/build/zsrtp ../pjsip/third_party/build/ - -# Copy new version to third_party/zsrtp/ -echo Copying new version of zrtp to third_party/zsrtp/ -mkdir ../pjsip/third_party/zsrtp/zrtp -cp -r ZRTPCPP/bnlib ../pjsip/third_party/zsrtp/zrtp/ -cp -r ZRTPCPP/common ../pjsip/third_party/zsrtp/zrtp/ -cp -r ZRTPCPP/cryptcommon ../pjsip/third_party/zsrtp/zrtp/ -cp -r ZRTPCPP/srtp ../pjsip/third_party/zsrtp/zrtp/ -cp -r ZRTPCPP/zrtp ../pjsip/third_party/zsrtp/zrtp/ -cp ZRTPCPP/COPYING ../pjsip/third_party/zsrtp/zrtp/ -cp ZRTPCPP/README.md ../pjsip/third_party/zsrtp/zrtp/ - -# Clean update directory -# echo Cleaning update directory -#rm -rf ZRTPCPP - -# Clean old directory -echo Cleaning old directory -rm -rf old - -cd .. - -echo Applying pjsip patches -cat update_pjsip_210/patches/pjsip_210.patch | patch -p0 - - -echo Applying zsrtp patches -cat update_pjsip_210/patches/zsrtp.patch | patch -p0 - -cd .. - -echo Applying sipsimple/core patches -cat deps/update_pjsip_210/patches/sipsimple_core.patch | patch -p0 - -cd - - -echo Done diff --git a/deps/zsrtp/build/Makefile b/deps/zsrtp/build/Makefile new file mode 100644 index 00000000..2bf70f64 --- /dev/null +++ b/deps/zsrtp/build/Makefile @@ -0,0 +1,127 @@ +include ../../../build.mak +include ../../../build/common.mak + +export LIBDIR := ../../lib + +RULES_MAK := $(PJDIR)/build/rules.mak + +export ZSRTP_LIB := ../../lib/libzsrtp-$(TARGET_NAME)$(LIBEXT) + +############################################################################### +# Gather all flags. +# +export _CFLAGS := $(CC_INC). $(CC_INC)../../zsrtp/include \ + $(CC_INC)../../zsrtp/zrtp \ + $(CC_INC)../../zsrtp/zrtp/zrtp \ + $(CC_INC)../../zsrtp/zrtp/zrtp/libzrtpcpp \ + $(CC_INC)../../zsrtp/zrtp/srtp \ + $(CC_INC)../../zsrtp/zrtp/srtp/crypto \ + $(CC_INC)../../../pjlib/include \ + $(CC_INC)../../../pjlib-util/include \ + $(CC_INC)../../../pjmedia/include \ + $(CC_CFLAGS) $(OS_CFLAGS) $(HOST_CFLAGS) $(M_CFLAGS) \ + $(CFLAGS) -fno-strict-aliasing +export _CXXFLAGS:= $(_CFLAGS) $(CC_CXXFLAGS) $(OS_CXXFLAGS) $(M_CXXFLAGS) \ + $(HOST_CXXFLAGS) $(CXXFLAGS) +export _LDFLAGS := $(CC_LDFLAGS) $(OS_LDFLAGS) $(M_LDFLAGS) $(HOST_LDFLAGS) \ + $(LDFLAGS) -lsqlite3 -lstdc++ + +ciphersossl = zrtp/srtp/crypto/openssl/SrtpSymCrypto.o \ + zrtp/srtp/crypto/openssl/hmac.o \ + zrtp/zrtp/crypto/openssl/zrtpDH.o \ + zrtp/zrtp/crypto/openssl/hmac256.o \ + zrtp/zrtp/crypto/openssl/sha256.o \ + zrtp/zrtp/crypto/openssl/hmac384.o \ + zrtp/zrtp/crypto/openssl/sha384.o \ + zrtp/zrtp/crypto/openssl/aesCFB.o + +skeinmac = zrtp/cryptcommon/skein.o \ + zrtp/cryptcommon/skein_block.o \ + zrtp/cryptcommon/skeinApi.o \ + zrtp/cryptcommon/macSkein.o \ + zrtp/zrtp/crypto/skein256.o \ + zrtp/zrtp/crypto/skein384.o \ + zrtp/zrtp/crypto/skeinMac256.o \ + zrtp/zrtp/crypto/skeinMac384.o + +twofish = zrtp/cryptcommon/twofish.o \ + zrtp/cryptcommon/twofish_cfb.o \ + zrtp/zrtp/crypto/twoCFB.o + +common = zrtp/common/osSpecifics.o + +# Gcrypt support currently not tested +#ciphersgcrypt = crypto/gcrypt/gcryptAesSrtp.o crypto/gcrypt/gcrypthmac.o \ +# crypto/gcrypt/InitializeGcrypt.o + +zrtpobj = zrtp/zrtp/ZrtpCallbackWrapper.o \ + zrtp/zrtp/ZIDCacheDb.o \ + zrtp/zrtp/ZIDRecordDb.o \ + zrtp/zrtp/zrtpCacheSqliteBackend.o \ + zrtp/zrtp/ZRtp.o \ + zrtp/zrtp/ZrtpCrc32.o \ + zrtp/zrtp/ZrtpPacketCommit.o \ + zrtp/zrtp/ZrtpPacketConf2Ack.o \ + zrtp/zrtp/ZrtpPacketConfirm.o \ + zrtp/zrtp/ZrtpPacketDHPart.o \ + zrtp/zrtp/ZrtpPacketGoClear.o \ + zrtp/zrtp/ZrtpPacketClearAck.o \ + zrtp/zrtp/ZrtpPacketHelloAck.o \ + zrtp/zrtp/ZrtpPacketHello.o \ + zrtp/zrtp/ZrtpPacketError.o \ + zrtp/zrtp/ZrtpPacketErrorAck.o \ + zrtp/zrtp/ZrtpPacketPingAck.o \ + zrtp/zrtp/ZrtpPacketPing.o \ + zrtp/zrtp/ZrtpPacketSASrelay.o \ + zrtp/zrtp/ZrtpPacketRelayAck.o \ + zrtp/zrtp/ZrtpStateClass.o \ + zrtp/zrtp/ZrtpTextData.o \ + zrtp/zrtp/ZrtpConfigure.o \ + zrtp/zrtp/ZrtpCWrapper.o \ + zrtp/zrtp/Base32.o \ + zrtp/zrtp/zrtpB64Encode.o \ + zrtp/zrtp/zrtpB64Decode.o + +srtpobj = srtp/ZsrtpCWrapper.o \ + zrtp/srtp/CryptoContext.o \ + zrtp/srtp/CryptoContextCtrl.o + +cryptobj = $(ciphersossl) $(skeinmac) $(twofish) + +export ZSRTP_SRCDIR = ../../zsrtp +export ZSRTP_OBJS = $(zrtpobj) $(cryptobj) $(srtpobj) $(common) +export ZSRTP_CFLAGS = $(_CFLAGS) +export ZSRTP_CXXFLAGS = $(_CXXFLAGS) + + +export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT +############################################################################### +# Main entry +# +# $(TARGET) is defined in os-$(OS_NAME).mak file in current directory. +# +TARGETS := libzsrtp + +all: $(TARGETS) + +doc: + cd .. && doxygen docs/doxygen.cfg + +dep: depend +distclean: realclean + +.PHONY: dep depend libzsrtp clean realclean distclean + +libzsrtp: + $(MAKE) -f $(RULES_MAK) APP=ZSRTP app=libzsrtp $(ZSRTP_LIB) + +clean print_lib: + $(MAKE) -f $(RULES_MAK) APP=ZSRTP app=libzsrtp $@ + +realclean: + $(subst @@,$(subst /,$(HOST_PSEP),.ilbc-$(TARGET_NAME).depend),$(HOST_RMR)) + $(MAKE) -f $(RULES_MAK) APP=ZSRTP app=libzsrtp $@ + +depend: + $(MAKE) -f $(RULES_MAK) APP=ZSRTP app=libzsrtp $@ + diff --git a/deps/zsrtp/include/ZsrtpCWrapper.h b/deps/zsrtp/include/ZsrtpCWrapper.h new file mode 100644 index 00000000..40613be0 --- /dev/null +++ b/deps/zsrtp/include/ZsrtpCWrapper.h @@ -0,0 +1,455 @@ +/* + This file defines the ZRTP SRTP C-to-C++ wrapper. + Copyright (C) 2010 Werner Dittmann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#ifndef ZSRTPCWRAPPER_H +#define ZSRTPCWRAPPER_H + +/** + * @file ZsrtpCWrapper.h + * @brief C-to-C++ wrapper for the C++ based SRTP and SRTCP implementation + * @defgroup Z_SRTP SRTP/SRTCP implementation for ZRTP including C-to-C++ wrapper + * @ingroup PJMEDIA_TRANSPORT_ZRTP + * @{ + */ + +#include + +/* + * Keep in synch with CryptoContext.h + */ +#define SrtpAuthenticationNull 0 +#define SrtpAuthenticationSha1Hmac 1 +#define SrtpAuthenticationSkeinHmac 2 + + +#define SrtpEncryptionNull 0 +#define SrtpEncryptionAESCM 1 +#define SrtpEncryptionAESF8 2 +#define SrtpEncryptionTWOCM 3 +#define SrtpEncryptionTWOF8 4 + + +#ifdef __cplusplus +extern "C" +{ +#endif +#ifdef __cplusplus + typedef class CryptoContext CryptoContext; +#else + typedef struct CryptoContext CryptoContext; +#endif + + typedef struct zsrtpContext + { + CryptoContext* srtp; + void* userData; + } ZsrtpContext; + + /** + * Create a ZSRTP wrapper fir a SRTP cryptographic context. + * + * This constructor creates an active SRTP cryptographic context were + * algorithms are enabled, keys are computed and so on. This SRTP + * cryptographic context can protect a RTP SSRC stream. + * + * @param ssrc + * The RTP SSRC that this SRTP cryptographic context protects. + * + * @param roc + * The initial Roll-Over-Counter according to RFC 3711. These are the + * upper 32 bit of the overall 48 bit SRTP packet index. Refer to + * chapter 3.2.1 of the RFC. + * + * @param keyDerivRate + * The key derivation rate defines when to recompute the SRTP session + * keys. Refer to chapter 4.3.1 in the RFC. + * + * @param ealg + * The encryption algorithm to use. Possible values are + * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8 + * . See chapter 4.1.1 for AESCM (Counter mode) and 4.1.2 + * for AES F8 mode. + * + * @param aalg + * The authentication algorithm to use. Possible values are + * SrtpEncryptionNull, SrtpAuthenticationSha1Hmac. The only + * active algorithm here is SHA1 HMAC, a SHA1 based hashed message + * authentication code as defined in RFC 2104. + * + * @param masterKey + * Pointer to the master key for this SRTP cryptographic context. + * Must point to masterKeyLength bytes. Refer to chapter + * 3.2.1 of the RFC about the role of the master key. + * + * @param masterKeyLength + * The length in bytes of the master key in bytes. The length must + * match the selected encryption algorithm. Because SRTP uses AES + * based encryption only, then master key length may be 16 or 32 + * bytes (128 or 256 bit master key) + * + * @param masterSalt + * SRTP uses the master salt to computer the initialization vector + * that in turn is input to compute the session key, session + * authentication key and the session salt. + * + * @param masterSaltLength + * The length in bytes of the master salt data in bytes. SRTP uses + * AES as encryption algorithm. AES encrypts 16 byte blocks + * (independent of the key length). According to RFC3711 the standard + * value for the master salt length should be 112 bit (14 bytes). + * + * @param ekeyl + * The length in bytes of the session encryption key that SRTP shall + * compute and use. Usually the same length as for the master key + * length. But you may use a different length as well. Be carefull + * that the key management mechanisms supports different key lengths. + * + * @param akeyl + * The length in bytes of the session authentication key. SRTP + * computes this key and uses it as input to the authentication + * algorithm. + * The standard value is 160 bits (20 bytes). + * + * @param skeyl + * The length in bytes of the session salt. SRTP computes this salt + * key and uses it as input during encryption. The length usually + * is the same as the master salt length. + * + * @param tagLength + * The length is bytes of the authentication tag that SRTP appends + * to the RTP packet. Refer to chapter 4.2. in the RFC 3711. + * + * @returns + * Pointer to a new ZSRTP wrapper context. + */ + ZsrtpContext* zsrtp_CreateWrapper(uint32_t ssrc, int32_t roc, + int64_t keyDerivRate, + const int32_t ealg, + const int32_t aalg, + uint8_t* masterKey, + int32_t masterKeyLength, + uint8_t* masterSalt, + int32_t masterSaltLength, + int32_t ekeyl, + int32_t akeyl, + int32_t skeyl, + int32_t tagLength); + + /** + * Destroy a ZSRTP wrapper Context + * + * @param ctx + * A ZSRTP wrapper context. + */ + void zsrtp_DestroyWrapper (ZsrtpContext* ctx); + + /** + * Encrypt the RTP payload and compute authentication code. + * + * The method requires a ready made RTP packet in the RTP packet data + * buffer. + * + * The method computes an authentication code and appends this code to the + * buffer and computes a new length. The RTP packet buffer must be large + * enough to hold this authentication code. + * + * @param ctx + * The ZsrtpContext + * + * @param buffer + * Pointer to the data that contains the RTP packet data. SRTP appends + * the authentication code to the encrypted RTP packet data. + * + * @param length + * Length of the RTP data buffer. + * + * @param newLength + * The new length of the RTP data buffer including authentication code + * + * @returns + * 0 if no active SRTP crypto context, 1 if data is encrypted. + */ + int32_t zsrtp_protect(ZsrtpContext* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength); + + /** + * Decrypt the RTP payload and check authentication code. + * + * The method requires a SRTP packet in the SRTP packet data + * buffer. + * + * SRTP checks SRTP packet replay, then it computes the authentication + * code and checks if the authentication code is correct. If the checks + * are ok then SRTP decrypts the payload data. + * + * @param ctx + * The ZsrtpContext + * + * @param buffer + * Pointer to the data that contains the SRTP packet data. SRTP removes + * the authentication code from the decrypted RTP packet data. + * + * @param length + * Length of the RTP data buffer. + * + * @param newLength + * The new length of the RTP data buffer excluding authentication code + * + * @returns + * 0 if no active SRTP crypto context, 1 if data is decrypted, + * -1 if data authentication failed, -2 if SRTP replay check failed + */ + int32_t zsrtp_unprotect(ZsrtpContext* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength); + + /** + * Derive a new Crypto Context for use with a new SSRC + * + * This method stores a new Crypto Context initialized with the data + * of this crypto context. Replacing the SSRC, Roll-over-Counter, and + * the key derivation rate the application cab use this Crypto Context + * to encrypt / decrypt a new stream (Synchronization source) inside + * one RTP session. + * + * Before the application can use this crypto context it must call + * the deriveSrtpKeys method. + * + * @param ctx + * The ZsrtpContext + * @param ssrc + * The SSRC for this context + * @param roc + * The Roll-Over-Counter for this context + * @param keyDerivRate + * The key derivation rate for this context + */ + void zsrtp_newCryptoContextForSSRC(ZsrtpContext* ctx, uint32_t ssrc, + int32_t roc, int64_t keyDerivRate); + + /** + * Perform key derivation according to SRTP specification + * + * This method computes the session key, session authentication key and the + * session salt key. This method must be called at least once after the + * SRTP Cryptograhic context was set up. + * + * @param ctx + * The ZsrtpContext + * @param index + * The 48 bit SRTP packet index. See the guessIndex + * method. + */ + void zsrtp_deriveSrtpKeys(ZsrtpContext* ctx, uint64_t index); + +#ifdef __cplusplus + typedef class CryptoContextCtrl CryptoContextCtrl; +#else + typedef struct CryptoContextCtrl CryptoContextCtrl; +#endif + + typedef struct zsrtcpContext + { + CryptoContextCtrl* srtcp; + void* userData; + uint32_t srtcpIndex; + } ZsrtpContextCtrl; + + /** + * Constructor for an active SRTP cryptographic context. + * + * This constructor creates an active SRTP cryptographic context were + * algorithms are enabled, keys are computed and so on. This SRTP + * cryptographic context can protect a RTP SSRC stream. + * + * @param ssrc + * The RTP SSRC that this SRTP cryptographic context protects. + * + * @param ealg + * The encryption algorithm to use. Possible values are + * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8 + * . See chapter 4.1.1 for AESCM (Counter mode) and 4.1.2 + * for AES F8 mode. + * + * @param aalg + * The authentication algorithm to use. Possible values are + * SrtpEncryptionNull, SrtpAuthenticationSha1Hmac. The only + * active algorithm here is SHA1 HMAC, a SHA1 based hashed message + * authentication code as defined in RFC 2104. + * + * @param masterKey + * Pointer to the master key for this SRTP cryptographic context. + * Must point to masterKeyLength bytes. Refer to chapter + * 3.2.1 of the RFC about the role of the master key. + * + * @param masterKeyLength + * The length in bytes of the master key in bytes. The length must + * match the selected encryption algorithm. Because SRTP uses AES + * based encryption only, then master key length may be 16 or 32 + * bytes (128 or 256 bit master key) + * + * @param masterSalt + * SRTP uses the master salt to computer the initialization vector + * that in turn is input to compute the session key, session + * authentication key and the session salt. + * + * @param masterSaltLength + * The length in bytes of the master salt data in bytes. SRTP uses + * AES as encryption algorithm. AES encrypts 16 byte blocks + * (independent of the key length). According to RFC3711 the standard + * value for the master salt length should be 112 bit (14 bytes). + * + * @param ekeyl + * The length in bytes of the session encryption key that SRTP shall + * compute and use. Usually the same length as for the master key + * length. But you may use a different length as well. Be carefull + * that the key management mechanisms supports different key lengths. + * + * @param akeyl + * The length in bytes of the session authentication key. SRTP + * computes this key and uses it as input to the authentication + * algorithm. + * The standard value is 160 bits (20 bytes). + * + * @param skeyl + * The length in bytes of the session salt. SRTP computes this salt + * key and uses it as input during encryption. The length usually + * is the same as the master salt length. + * + * @param tagLength + * The length is bytes of the authentication tag that SRTP appends + * to the RTP packet. Refer to chapter 4.2. in the RFC 3711. + */ + ZsrtpContextCtrl* zsrtp_CreateWrapperCtrl( uint32_t ssrc, + const int32_t ealg, + const int32_t aalg, + uint8_t* masterKey, + int32_t masterKeyLength, + uint8_t* masterSalt, + int32_t masterSaltLength, + int32_t ekeyl, + int32_t akeyl, + int32_t skeyl, + int32_t tagLength ); + + /** + * Destroy a ZSRTCP wrapper Context + * + * @param ctx + * A ZSRTCP wrapper context. + */ + void zsrtp_DestroyWrapperCtrl (ZsrtpContextCtrl* ctx); + + /** + * Encrypt the RTCP payload and compute authentication code. + * + * The method requires a ready made RTCP packet in the RTCP packet data + * buffer. + * + * The method computes an authentication code and appends this code to the + * buffer and computes a new length. The RTCP packet buffer must be large + * enough to hold this authentication code. + * + * @param ctx + * The ZsrtpContextCtrl + * + * @param buffer + * Pointer to the data that contains the RTP packet data. SRTP appends + * the authentication code to the encrypted RTP packet data. + * + * @param length + * Length of the RTCP data buffer. + * + * @param newLength + * The new length of the RTCP data buffer including authentication code + * + * @returns + * 0 if no active SRTCP crypto context, 1 if data is encrypted. + */ + int32_t zsrtp_protectCtrl(ZsrtpContextCtrl* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength); + + /** + * Decrypt the RTCP payload and check authentication code. + * + * The method requires a SRTCP packet in the SRTP packet data + * buffer. + * + * SRTP checks SRTP packet replay, then it computes the authentication + * code and checks if the authentication code is correct. If the checks + * are ok then SRTP decrypts the payload data. + * + * @param ctx + * The ZsrtpContextCtrl + * + * @param buffer + * Pointer to the data that contains the SRTCP packet data. SRTCP remove + * the authentication code from the decrypted RTCP packet data. + * + * @param length + * Length of the RTP data buffer. + * + * @param newLength + * The new length of the RTCP data buffer excluding authentication code + * + * @returns + * 0 if no active SRTCP crypto context, 1 if data is decrypted, + * -1 if data authentication failed, -2 if SRTCP replay check failed + */ + int32_t zsrtp_unprotectCtrl(ZsrtpContextCtrl* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength); + + /** + * Derive a new Crypto Context for use with a new SSRC + * + * This method stores a new Crypto Context initialized with the data + * of this crypto context. Replacing the SSRC, Roll-over-Counter, and + * the key derivation rate the application cab use this Crypto Context + * to encrypt / decrypt a new stream (Synchronization source) inside + * one RTP session. + * + * Before the application can use this crypto context it must call + * the deriveSrtpKeys method. + * + * @param ctx + * The ZsrtpContextCtrl + * @param ssrc + * The SSRC for this context + */ + void zsrtp_newCryptoContextForSSRCCtrl(ZsrtpContextCtrl* ctx, uint32_t ssrc); + + /** + * Perform key derivation according to SRTP specification + * + * This method computes the session key, session authentication key and the + * session salt key. This method must be called at least once after the + * SRTP Cryptograhic context was set up. + * + * @param ctx + * The ZsrtpContextCtrl + */ + void zsrtp_deriveSrtpKeysCtrl(ZsrtpContextCtrl* ctx); + + +#ifdef __cplusplus +} +#endif +/** + * @} + */ +#endif diff --git a/deps/zsrtp/include/openssl_compat.h b/deps/zsrtp/include/openssl_compat.h new file mode 100644 index 00000000..aebbf996 --- /dev/null +++ b/deps/zsrtp/include/openssl_compat.h @@ -0,0 +1,30 @@ +#ifndef _OPENSSL_COMPAT +#define _OPENSSL_COMPAT + +#include + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) +static HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(HMAC_CTX)); + if (ctx != NULL) + HMAC_CTX_init(ctx); + return ctx; +} + +static void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (ctx != NULL) { + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} + +static int HMAC_CTX_reset(HMAC_CTX *ctx) +{ + HMAC_CTX_init(ctx); + return 1; +} +#endif + +#endif diff --git a/deps/zsrtp/srtp/ZsrtpCWrapper.cpp b/deps/zsrtp/srtp/ZsrtpCWrapper.cpp new file mode 100644 index 00000000..ec43ed32 --- /dev/null +++ b/deps/zsrtp/srtp/ZsrtpCWrapper.cpp @@ -0,0 +1,363 @@ +/* + This file implements the ZRTP SRTP C-to-C++ wrapper. + Copyright (C) 2010 Werner Dittmann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +# include +#else +# include +#endif + +ZsrtpContext* zsrtp_CreateWrapper(uint32_t ssrc, int32_t roc, + int64_t keyDerivRate, + const int32_t ealg, + const int32_t aalg, + uint8_t* masterKey, + int32_t masterKeyLength, + uint8_t* masterSalt, + int32_t masterSaltLength, + int32_t ekeyl, + int32_t akeyl, + int32_t skeyl, + int32_t tagLength) +{ + ZsrtpContext* zc = new ZsrtpContext; + zc->srtp = new CryptoContext(ssrc, roc, keyDerivRate, ealg, aalg, + masterKey, masterKeyLength, masterSalt, + masterSaltLength, ekeyl, akeyl, skeyl, + tagLength); + return zc; +} + +void zsrtp_DestroyWrapper (ZsrtpContext* ctx) +{ + + if (ctx == NULL) + return; + + delete ctx->srtp; + ctx->srtp = NULL; + + delete ctx; +} + +/* + * Private RTP decoding, copied from rtp.c. Need this because of + * different padding handling for SRTP. + */ +#define RTP_VERSION 2 +static pj_status_t zsrtp_decode_rtp(uint8_t* pkt, int32_t pkt_len, + const pjmedia_rtp_hdr **hdr, + uint8_t** payload, + int32_t *payloadlen) +{ + int offset; + + + /* Assume RTP header at the start of packet. We'll verify this later. */ + *hdr = (pjmedia_rtp_hdr*)pkt; + + /* Check RTP header sanity. */ + if ((*hdr)->v != RTP_VERSION) { + return PJMEDIA_RTP_EINVER; + } + + /* Payload is located right after header plus CSRC */ + offset = sizeof(pjmedia_rtp_hdr) + ((*hdr)->cc * sizeof(pj_uint32_t)); + + /* Adjust offset if RTP extension is used. */ + if ((*hdr)->x) { + pjmedia_rtp_ext_hdr *ext = (pjmedia_rtp_ext_hdr*) + (((pj_uint8_t*)pkt) + offset); + offset += ((pj_ntohs(ext->length)+1) * sizeof(pj_uint32_t)); + } + + /* Check that offset is less than packet size */ + if (offset > pkt_len) + return PJMEDIA_RTP_EINLEN; + + /* Find and set payload. */ + *payload = pkt + offset; + *payloadlen = pkt_len - offset; + + return PJ_SUCCESS; +} + +int32_t zsrtp_protect(ZsrtpContext* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength) +{ + CryptoContext* pcc = ctx->srtp; + const pjmedia_rtp_hdr *hdr; + uint8_t* payload; + int32_t payloadlen; + uint16_t seqnum; + uint32_t ssrc; + + + if (pcc == NULL) { + return 0; + } + zsrtp_decode_rtp(buffer, length, &hdr, &payload, &payloadlen); + + seqnum = hdr->seq; + seqnum = ntohs(seqnum); + + /* Encrypt the packet */ + uint64_t index = ((uint64_t)pcc->getRoc() << 16) | (uint64_t)seqnum; + + ssrc = hdr->ssrc; + ssrc = ntohl(ssrc); + pcc->srtpEncrypt(buffer, payload, payloadlen, index, ssrc); + + // NO MKI support yet - here we assume MKI is zero. To build in MKI + // take MKI length into account when storing the authentication tag. + + /* Compute MAC and store at end of RTP packet data */ + pcc->srtpAuthenticate(buffer, length, pcc->getRoc(), buffer+length); + + *newLength = length + pcc->getTagLength(); + + /* Update the ROC if necessary */ + if (seqnum == 0xFFFF ) { + pcc->setRoc(pcc->getRoc() + 1); + } + return 1; +} + +int32_t zsrtp_unprotect(ZsrtpContext* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength) +{ + CryptoContext* pcc = ctx->srtp; + const pjmedia_rtp_hdr *hdr; + uint8_t* payload; + int32_t payloadlen; + uint16_t seqnum; + uint32_t ssrc; + + if (pcc == NULL) { + return 0; + } + + zsrtp_decode_rtp(buffer, length, &hdr, &payload, &payloadlen); + + /* + * This is the setting of the packet data when we come to this + * point: + * + * length: complete length of received data + * buffer: points to data as received from network + * hdrSize: length of header including header extension + * payloadlen: length of data excluding hdrSize and padding + * + * Because this is an SRTP packet we need to adjust some values here. + * The SRTP MKI and authentication data is always at the end of a + * packet. Thus compute the position of this data. + */ + + uint32_t srtpDataIndex = length - (pcc->getTagLength() + pcc->getMkiLength()); + + // now adjust length because some RTP functions rely on the fact that + // total is the full length of data without SRTP data. + length -= pcc->getTagLength() + pcc->getMkiLength(); + *newLength = length; + + // recompute payloadlen by subtracting SRTP data + payloadlen -= pcc->getTagLength() + pcc->getMkiLength(); + + // unused?? + // const uint8* mki = getRawPacket() + srtpDataIndex; + uint8_t* tag = buffer + srtpDataIndex + pcc->getMkiLength(); + + /* Replay control */ + seqnum = hdr->seq; + seqnum = ntohs(seqnum); + if (!pcc->checkReplay(seqnum)) { + return -2; + } + /* Guess the index */ + uint64_t guessedIndex = pcc->guessIndex(seqnum); + + uint32_t guessedRoc = guessedIndex >> 16; + uint8_t* mac = new uint8_t[pcc->getTagLength()]; + + pcc->srtpAuthenticate(buffer, length, guessedRoc, mac); + if (pj_memcmp(tag, mac, pcc->getTagLength()) != 0) { + delete[] mac; + return -1; + } + delete[] mac; + + /* Decrypt the content */ + ssrc = hdr->ssrc; + ssrc = ntohl(ssrc); + pcc->srtpEncrypt(buffer, payload, payloadlen, guessedIndex, ssrc); + + /* Update the Crypto-context */ + pcc->update(seqnum); + + return 1; +} + +void zsrtp_newCryptoContextForSSRC(ZsrtpContext* ctx, uint32_t ssrc, + int32_t roc, int64_t keyDerivRate) +{ + CryptoContext* newCrypto = ctx->srtp->newCryptoContextForSSRC(ssrc, 0, 0L); + ctx->srtp = newCrypto; +} + +void zsrtp_deriveSrtpKeys(ZsrtpContext* ctx, uint64_t index) +{ + ctx->srtp->deriveSrtpKeys(index); +} + + +/* + * Implement the wrapper for SRTCP crypto context + */ +ZsrtpContextCtrl* zsrtp_CreateWrapperCtrl( uint32_t ssrc, + const int32_t ealg, + const int32_t aalg, + uint8_t* masterKey, + int32_t masterKeyLength, + uint8_t* masterSalt, + int32_t masterSaltLength, + int32_t ekeyl, + int32_t akeyl, + int32_t skeyl, + int32_t tagLength ) +{ + ZsrtpContextCtrl* zc = new ZsrtpContextCtrl; + zc->srtcp = new CryptoContextCtrl(ssrc, ealg, aalg, masterKey, masterKeyLength, masterSalt, + masterSaltLength, ekeyl, akeyl, skeyl, tagLength ); + + zc->srtcpIndex = 0; + return zc; +} + + +void zsrtp_DestroyWrapperCtrl (ZsrtpContextCtrl* ctx) +{ + if (ctx == NULL) + return; + + delete ctx->srtcp; + ctx->srtcp = NULL; + + delete ctx; +} + +int32_t zsrtp_protectCtrl(ZsrtpContextCtrl* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength) +{ + CryptoContextCtrl* pcc = ctx->srtcp; + + if (pcc == NULL) { + return 0; + } + /* Encrypt the packet */ + uint32_t ssrc = *(reinterpret_cast(buffer + 4)); // always SSRC of sender + ssrc = ntohl(ssrc); + + pcc->srtcpEncrypt(buffer + 8, length - 8, ctx->srtcpIndex, ssrc); + + uint32_t encIndex = ctx->srtcpIndex | 0x80000000; // set the E flag + + // Fill SRTCP index as last word + uint32_t* ip = reinterpret_cast(buffer+length); + *ip = htonl(encIndex); + + // NO MKI support yet - here we assume MKI is zero. To build in MKI + // take MKI length into account when storing the authentication tag. + + // Compute MAC and store in packet after the SRTCP index field + pcc->srtcpAuthenticate(buffer, length, encIndex, buffer + length + sizeof(uint32_t)); + + ctx->srtcpIndex++; + ctx->srtcpIndex &= ~0x80000000; // clear possible overflow + *newLength = length + pcc->getTagLength() + sizeof(uint32_t); + + return 1; +} + +int32_t zsrtp_unprotectCtrl(ZsrtpContextCtrl* ctx, uint8_t* buffer, int32_t length, + int32_t* newLength) +{ + CryptoContextCtrl* pcc = ctx->srtcp; + + if (pcc == NULL) { + return 0; + } + + // Compute the total length of the payload + int32_t payloadLen = length - (pcc->getTagLength() + pcc->getMkiLength() + 4); + *newLength = payloadLen; + + // point to the SRTCP index field just after the real payload + const uint32_t* index = reinterpret_cast(buffer + payloadLen); + + uint32_t encIndex = ntohl(*index); + uint32_t remoteIndex = encIndex & ~0x80000000; // index without Encryption flag + + if (!pcc->checkReplay(remoteIndex)) { + return -2; + } + + uint8_t mac[20]; + + // Now get a pointer to the authentication tag field + const uint8_t* tag = buffer + (length - pcc->getTagLength()); + + // Authenticate includes the index, but not MKI and not (obviously) the tag itself + pcc->srtcpAuthenticate(buffer, payloadLen, encIndex, mac); + if (memcmp(tag, mac, pcc->getTagLength()) != 0) { + return -1; + } + + uint32_t ssrc = *(reinterpret_cast(buffer + 4)); // always SSRC of sender + ssrc = ntohl(ssrc); + + // Decrypt the content, exclude the very first SRTCP header (fixed, 8 bytes) + if (encIndex & 0x80000000) + pcc->srtcpEncrypt(buffer + 8, payloadLen - 8, remoteIndex, ssrc); + + // Update the Crypto-context + pcc->update(remoteIndex); + + return 1; +} + +void zsrtp_newCryptoContextForSSRCCtrl(ZsrtpContextCtrl* ctx, uint32_t ssrc) +{ + CryptoContextCtrl* newCrypto = ctx->srtcp->newCryptoContextForSSRC(ssrc); + ctx->srtcp = newCrypto; +} + +void zsrtp_deriveSrtpKeysCtrl(ZsrtpContextCtrl* ctx) +{ + ctx->srtcp->deriveSrtcpKeys(); +} + + + diff --git a/docs/Dependencies.txt b/docs/Dependencies.txt index a25381de..6938b3f7 100644 --- a/docs/Dependencies.txt +++ b/docs/Dependencies.txt @@ -1,29 +1,31 @@ SIP SIMPLE client SDK dependencies ---------------------------------- Home page: http://sipsimpleclient.org SIP SIMPLE SDK depends upon the following third party C sources: - PJSIP base revision 210 from 2020-02-14 https://github.com/pjsip/pjproject/archive/2.10.tar.gz - ZRTP tag 6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03 https://github.com/wernerd/ZRTPCPP.git +Fetch and patch the dependencies using get_dependencies.sh script + Python dependencies available from AG Projects repositories: * python3-application http://download.ag-projects.com/SipSimpleSDK/Python3/ * python3-eventlib http://download.ag-projects.com/SipSimpleSDK/Python3/ * python3-gnutls http://download.ag-projects.com/SipSimpleSDK/Python3/ * python3-otr http://download.ag-projects.com/SipSimpleSDK/Python3/ * python3-msrplib http://download.ag-projects.com/SipSimpleSDK/Python3/ * python3-xcaplib http://download.ag-projects.com/SipSimpleSDK/Python3/ The dependencies for each package can be found inside debian/control file On a Debian or Ubuntu based system you can install their dependencies using: sudo mk-build-deps --install debian/control diff --git a/docs/Install.linux b/docs/Install.linux index 475f4a15..f258c835 100644 --- a/docs/Install.linux +++ b/docs/Install.linux @@ -1,110 +1,112 @@ SIP SIMPLE SDK installation on Linux ------------------------------------ Home page: http://sipsimpleclient.org This document described the installation procedure on Linux operating systems. Step 1. Prerequisites --------------------- Install the C compiling environment, Python 3 and the development version for the following packages: * openssl * ffmpeg Step 2. Install system dependencies ----------------------------------- SIP SIMPLE SDK depends upon the following third party sources: - PJSIP base revision 210 from 2020-02-14 https://github.com/pjsip/pjproject/archive/2.10.tar.gz - ZRTP tag 6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03 https://github.com/wernerd/ZRTPCPP.git +Fetch and patch the dependencies using get_dependencies.sh script + See Dependencies.txt for detailed description of the required libraries and their minimum version number. Use the appropriate package manager for your Linux distribution to install the following packages, notice the minimum version numbers. You can use the easy_install script provided by the python-setuptools package to install the packages: sudo pip3 install -U cython dnspython lxml twisted python-dateutil \ greenlet zope.interface requests Step 3. Install AG Projects dependencies ---------------------------------------- - python3-application - python3-eventlib - python3-gnutls - python3-otr - python3-msrplib - python3-xcaplib For each of them, in the exact order as listed above, retrieve the packages as follows: Using darcs: darcs clone http://devel.ag-projects.com/repositories/PROJECT replace PROJECT with each of the names above As tar archives from: http://download.ag-projects.com/SipSimpleSDK/Python3/ Install these packages by going into each directory. Using pip3 inside your user environment: pip3 install --user . System-wide using setup.py: sudo python3 setup.py install As a debian package: ./makedeb.sh The debian package can be found inside ./dist folder sudo dpkg -i *.deb Step 4. Install the SDK ----------------------- First unpack pjsip archive (only needs to be done once): ./extract_pjsip.sh The SDK consists of two packages: - python3-sipsimple - sipclients3 (optional, for testing all SDK functions) Install them similar to the dependencies above. Step 5. Testing the SDK ----------------------- Use the command line tools provided by sipclients3 package, the executables start with sip- prefix diff --git a/extract_pjsip.sh b/extract_pjsip.sh deleted file mode 100755 index 3b0ceebf..00000000 --- a/extract_pjsip.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -if [ ! -d deps/pjsip ]; then - tar zxvf deps/pjsip-2.10.tgz -C deps/ -fi diff --git a/get_dependencies.sh b/get_dependencies.sh new file mode 100755 index 00000000..ca5218b1 --- /dev/null +++ b/get_dependencies.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# +# Update PJSIP +# +cd deps + +echo "Preparing PJSIP sources..." +if [ ! -f 2.10.tar.gz ]; then + echo Downloading PJSIP 2.10... + wget https://github.com/pjsip/pjproject/archive/2.10.tar.gz + if [ $? -eq 0 ]; then + echo "PJSIP downloaded" + else + echo Fail to download PJSIP + exit 1 + fi +fi + +tar xzf 2.10.tar.gz + +if [ -d pjsip ]; then + rm -r pjsip +fi + +mkdir pjsip +mv pjproject*/* ./pjsip/ + +# +# Update ZSRTP +# + +# Clone latest version from github +if [ ! -d ZRTPCPP ]; then + echo Downloading ZRTP... + git clone https://github.com/wernerd/ZRTPCPP.git + if [ $? -eq 0 ]; then + echo "ZRTP downloaded" + cd ZRTPCPP + git checkout 6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03 + cd .. + else + echo Fail to download ZRTP + exit 1 + fi +fi + +# Copy wrapper from old version to third_party/zsrtp/ +echo "Preparing ZRTP sources..." +mkdir ./pjsip/third_party/zsrtp +cp -r zsrtp/include ./pjsip/third_party/zsrtp/ +cp -r zsrtp/srtp ./pjsip/third_party/zsrtp/ +cp -r zsrtp/build ./pjsip/third_party/build/zsrtp + +# Copy new version to third_party/zsrtp/ +mkdir ./pjsip/third_party/zsrtp/zrtp +cp -r ZRTPCPP/bnlib ./pjsip/third_party/zsrtp/zrtp/ +cp -r ZRTPCPP/common ./pjsip/third_party/zsrtp/zrtp/ +cp -r ZRTPCPP/cryptcommon ./pjsip/third_party/zsrtp/zrtp/ +cp -r ZRTPCPP/srtp ./pjsip/third_party/zsrtp/zrtp/ +cp -r ZRTPCPP/zrtp ./pjsip/third_party/zsrtp/zrtp/ +cp ZRTPCPP/COPYING ./pjsip/third_party/zsrtp/zrtp/ +cp ZRTPCPP/README.md ./pjsip/third_party/zsrtp/zrtp/ + +for p in patches/*.patch; do + echo "Applying patch $p" + cat $p | patch -p0 > /dev/null +done + +cd - > /dev/null + diff --git a/makedeb.sh b/makedeb.sh index cf4cae7e..2e1b01b1 100755 --- a/makedeb.sh +++ b/makedeb.sh @@ -1,22 +1,25 @@ #!/bin/bash if [ -f dist ]; then rm -r dist fi +./get_dependencies.sh + sudo apt install equivs sudo mk-build-deps --install debian/control chmod +x deps/pjsip/configure chmod +x deps/pjsip/aconfigure python3 setup.py sdist cd dist tar zxvf *.tar.gz cd python3-sipsimple-?.?.? debuild --no-sign -ls +cd .. +ls