Git Product home page Git Product logo

libsrtp's Introduction

CMake Build Autotools Build Autotools Build Coverity Scan Build Status OSS-Fuzz Status

Introduction to libSRTP

This package provides an implementation of the Secure Real-time Transport Protocol (SRTP), the Universal Security Transform (UST), and a supporting cryptographic kernel. The SRTP API is documented in include/srtp.h, and the library is in libsrtp2.a (after compilation).

This document describes libSRTP, the Open Source Secure RTP library from Cisco Systems, Inc. RTP is the Real-time Transport Protocol, an IETF standard for the transport of real-time data such as telephony, audio, and video, defined by RFC 3550. Secure RTP (SRTP) is an RTP profile for providing confidentiality to RTP data and authentication to the RTP header and payload. SRTP is an IETF Standard, defined in RFC 3711, and was developed in the IETF Audio/Video Transport (AVT) Working Group. This library supports all of the mandatory features of SRTP, but not all of the optional features. See the Supported Features section for more detailed information.

This document is also used to generate the documentation files in the /doc/ folder where a more detailed reference to the libSRTP API and related functions can be created (requires installing doxygen.). The reference material is created automatically from comments embedded in some of the C header files. The documentation is organized into modules in order to improve its clarity. These modules do not directly correspond to files. An underlying cryptographic kernel provides much of the basic functionality of libSRTP but is mostly undocumented because it does its work behind the scenes.


Contact Us


Contents


License and Disclaimer

libSRTP is distributed under the following license, which is included in the source code distribution. It is reproduced in the manual in case you got the library from another source.

Copyright (c) 2001-2017 Cisco Systems, Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of the Cisco Systems, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


libSRTP Overview

libSRTP provides functions for protecting RTP and RTCP. RTP packets can be encrypted and authenticated (using the srtp_protect() function), turning them into SRTP packets. Similarly, SRTP packets can be decrypted and have their authentication verified (using the srtp_unprotect() function), turning them into RTP packets. Similar functions apply security to RTCP packets.

The typedef srtp_stream_t points to a structure holding all of the state associated with an SRTP stream, including the keys and parameters for cipher and message authentication functions and the anti-replay data. A particular srtp_stream_t holds the information needed to protect a particular RTP and RTCP stream. This datatype is intentionally opaque in order to better seperate the libSRTP API from its implementation.

Within an SRTP session, there can be multiple streams, each originating from a particular sender. Each source uses a distinct stream context to protect the RTP and RTCP stream that it is originating. The typedef srtp_t points to a structure holding all of the state associated with an SRTP session. There can be multiple stream contexts associated with a single srtp_t. A stream context cannot exist indepent from an srtp_t, though of course an srtp_t can be created that contains only a single stream context. A device participating in an SRTP session must have a stream context for each source in that session, so that it can process the data that it receives from each sender.

In libSRTP, a session is created using the function srtp_create(). The policy to be implemented in the session is passed into this function as an srtp_policy_t structure. A single one of these structures describes the policy of a single stream. These structures can also be linked together to form an entire session policy. A linked list of srtp_policy_t structures is equivalent to a session policy. In such a policy, we refer to a single srtp_policy_t as an element.

An srtp_policy_t structure contains two srtp_crypto_policy_t structures that describe the cryptograhic policies for RTP and RTCP, as well as the SRTP master key and the SSRC value. The SSRC describes what to protect (e.g. which stream), and the srtp_crypto_policy_t structures describe how to protect it. The key is contained in a policy element because it simplifies the interface to the library. In many cases, it is desirable to use the same cryptographic policies across all of the streams in a session, but to use a distinct key for each stream. A srtp_crypto_policy_t structure can be initialized by using either the srtp_crypto_policy_set_rtp_default() or srtp_crypto_policy_set_rtcp_default() functions, which set a crypto policy structure to the default policies for RTP and RTCP protection, respectively.


Secure RTP Background

In this section we review SRTP and introduce some terms that are used in libSRTP. An RTP session is defined by a pair of destination transport addresses, that is, a network address plus a pair of UDP ports for RTP and RTCP. RTCP, the RTP control protocol, is used to coordinate between the participants in an RTP session, e.g. to provide feedback from receivers to senders. An SRTP session is similarly defined; it is just an RTP session for which the SRTP profile is being used. An SRTP session consists of the traffic sent to the SRTP or SRTCP destination transport addresses. Each participant in a session is identified by a synchronization source (SSRC) identifier. Some participants may not send any SRTP traffic; they are called receivers, even though they send out SRTCP traffic, such as receiver reports.

RTP allows multiple sources to send RTP and RTCP traffic during the same session. The synchronization source identifier (SSRC) is used to distinguish these sources. In libSRTP, we call the SRTP and SRTCP traffic from a particular source a stream. Each stream has its own SSRC, sequence number, rollover counter, and other data. A particular choice of options, cryptographic mechanisms, and keys is called a policy. Each stream within a session can have a distinct policy applied to it. A session policy is a collection of stream policies.

A single policy can be used for all of the streams in a given session, though the case in which a single key is shared across multiple streams requires care. When key sharing is used, the SSRC values that identify the streams must be distinct. This requirement can be enforced by using the convention that each SRTP and SRTCP key is used for encryption by only a single sender. In other words, the key is shared only across streams that originate from a particular device (of course, other SRTP participants will need to use the key for decryption). libSRTP supports this enforcement by detecting the case in which a key is used for both inbound and outbound data.


Supported Features

This library supports all of the mandatory-to-implement features of SRTP (as defined in RFC 3711). Some of these features can be selected (or de-selected) at run time by setting an appropriate policy; this is done using the structure srtp_policy_t. Some other behaviors of the protocol can be adapted by defining an approriate event handler for the exceptional events; see the SRTPevents section in the generated documentation.

Some options that are described in the SRTP specification are not supported. This includes

  • key derivation rates other than zero,
  • the cipher F8,
  • the use of the packet index to select between master keys.

The user should be aware that it is possible to misuse this library, and that the result may be that the security level it provides is inadequate. If you are implementing a feature using this library, you will want to read the Security Considerations section of RFC 3711. In addition, it is important that you read and understand the terms outlined in the License and Disclaimer section.

This library also supports the AES-GCM Authenticated Encryption methods described in RFC 7714


Implementation Notes

  • It is possible to configure which 3rd party (ie openssl/nss/etc) crypto backend libSRTP will be built with. If no 3rd party backend is set then libSRTP provides an internal implementation of AES and Sha1. The internal implementation only supports AES-128 & AES-256, so to use AES-192 or the AES-GCM group of ciphers a 3rd party crypto backend must be configured. For this and performance reasons it is highly recommended to use a 3rd party crypto backend.

  • The srtp_protect() function assumes that the buffer holding the rtp packet has enough storage allocated that the authentication tag can be written to the end of that packet. If this assumption is not valid, memory corruption will ensue.

  • Automated tests for the crypto functions are provided through the cipher_type_self_test() and auth_type_self_test() functions. These functions should be used to test each port of this code to a new platform.

  • Replay protection is contained in the crypto engine, and tests for it are provided.

  • This implementation provides calls to initialize, protect, and unprotect RTP packets, and makes as few as possible assumptions about how these functions will be called. For example, the caller is not expected to provide packets in order (though if they're called more than 65k out of sequence, synchronization will be lost).

  • The sequence number in the rtp packet is used as the low 16 bits of the sender's local packet index. Note that RTP will start its sequence number in a random place, and the SRTP layer just jumps forward to that number at its first invocation. An earlier version of this library used initial sequence numbers that are less than 32,768; this trick is no longer required as the rdbx_estimate_index(...) function has been made smarter.

  • The replay window for (S)RTCP is hardcoded to 128 bits in length.


Installing and Building libSRTP

To install libSRTP, download the latest release of the distribution from https://github.com/cisco/libsrtp/releases. You probably want to get the most recent release. Unpack the distribution and extract the source files; the directory into which the source files will go is named libsrtp-A-B-C where A is the version number, B is the major release number and C is the minor release number.

libSRTP uses the GNU autoconf and make utilities (BSD make will not work; if both versions of make are on your platform, you can invoke GNU make as gmake.). In the libsrtp directory, run the configure script and then make:

./configure [ options ]
make

The configure script accepts the following options:

Option Description
--help -h Display help
--enable-debug-logging Enable debug logging in all modules
--enable-openssl Enable OpenSSL crypto engine
--enable-nss Enable NSS crypto engine
--enable-openssl-kdf Enable OpenSSL KDF algorithm
--enable-log-stdout Enable logging to stdout
--with-openssl-dir Location of OpenSSL installation
--with-nss-dir Location of NSS installation
--with-log-file Use file for logging

By default there is no log output, logging can be enabled to be output to stdout or a given file using the configure options.

This package has been tested on the following platforms: Mac OS X (powerpc-apple-darwin1.4), Cygwin (i686-pc-cygwin), Solaris (sparc-sun-solaris2.6), RedHat Linux 7.1 and 9 (i686-pc-linux), and OpenBSD (sparc-unknown-openbsd2.7).


Changing Build Configuration

To build the ./configure script mentioned above, libSRTP relies on the automake toolchain. Since ./configure is built from configure.in by automake, if you make changes in how ./configure works (e.g., to add a new library dependency), you will need to rebuild ./configure and commit the updated version. In addition to automake itself, you will need to have the pkgconfig tools installed as well.

For example, on macOS:

brew install automake pkgconfig
# Edit configure.in
autoremake -ivf

Using Visual Studio

On Windows one can use Visual Studio via CMake. CMake can be downloaded here: https://cmake.org/ . To create Visual Studio build files, for example run the following commands:

# Create build subdirectory
mkdir build
cd build

# Make project files
cmake .. -G "Visual Studio 15 2017"

# Or for 64 bit project files
cmake .. -G "Visual Studio 15 2017 Win64"

Using Meson

On all platforms including Windows, one can build using Meson. Steps to download Meson are here: https://mesonbuild.com/Getting-meson.html

To build with Meson, you can do something like:

# Setup the build subdirectory
meson setup --prefix=/path/to/prefix builddir

# Build the project
meson compile -C builddir

# Run tests
meson test -C builddir

# Optionally, install
meson install -C builddir

To build with Visual Studio, run the above commands from inside a Visual Studio command prompt, or run vcvarsall.bat with the appropriate arguments inside a Command Prompt.

Note that you can also replace the above commands with the appropriate ninja targets: ninja -C build, ninja -C build test, ninja -C build install.


Applications

Several test drivers and a simple and portable srtp application are included in the test/ subdirectory.

Test driver Function tested
kernel_driver crypto kernel (ciphers, auth funcs, rng)
srtp_driver srtp in-memory tests (does not use the network)
rdbx_driver rdbx (extended replay database)
roc_driver extended sequence number functions
replay_driver replay database
cipher_driver ciphers
auth_driver hash functions

The app rtpw is a simple rtp application which reads words from /usr/dict/words and then sends them out one at a time using [s]rtp. Manual srtp keying uses the -k option; automated key management using gdoi will be added later.

usage:

rtpw [[-d <debug>]* [-k|b <key> [-a][-e <key size>][-g]] [-s | -r] dest_ip dest_port] | [-l]

Either the -s (sender) or -r (receiver) option must be chosen. The values dest_ip, dest_port are the IP address and UDP port to which the dictionary will be sent, respectively.

The options are:

Option Description
-s (S)RTP sender - causes app to send words
-r (S)RTP receive - causes app to receive words
-k use SRTP master key , where the key is a hexadecimal (without the leading "0x")
-b same as -k but with base64 encoded key
-e encrypt/decrypt (for data confidentiality) (requires use of -k option as well) (use 128, 192, or 256 for keysize)
-g use AES-GCM mode (must be used with -e)
-a message authentication (requires use of -k option as well)
-l list the available debug modules
-d turn on debugging for module

In order to get random 30-byte values for use as key/salt pairs , you can use the following bash function to format the output of /dev/random (where that device is available).

function randhex() {
   cat /dev/random | od --read-bytes=32 --width=32 -x | awk '{ print $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 }'
}

An example of an SRTP session using two rtpw programs follows:

set k=c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451

[sh1]$ test/rtpw -s -k $k -e 128 -a 0.0.0.0 9999
Security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
setting SSRC to 2078917053
sending word: A
sending word: a
sending word: aa
sending word: aal
...

[sh2]$ test/rtpw -r -k $k -e 128 -a 0.0.0.0 9999
security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
19 octets received from SSRC 2078917053 word: A
19 octets received from SSRC 2078917053 word: a
20 octets received from SSRC 2078917053 word: aa
21 octets received from SSRC 2078917053 word: aal
...

Example Code

This section provides a simple example of how to use libSRTP. The example code lacks error checking, but is functional. Here we assume that the value ssrc is already set to describe the SSRC of the stream that we are sending, and that the functions get_rtp_packet() and send_srtp_packet() are available to us. The former puts an RTP packet into the buffer and returns the number of octets written to that buffer. The latter sends the RTP packet in the buffer, given the length as its second argument.

srtp_t session;
srtp_policy_t policy;

// Set key to predetermined value
uint8_t key[30] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                   0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                   0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
                   0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D};

// initialize libSRTP
srtp_init();

// default policy values
memset(&policy, 0x0, sizeof(srtp_policy_t));

// set policy to describe a policy for an SRTP stream
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
policy.ssrc = ssrc;
policy.key  = key;
policy.next = NULL;

// allocate and initialize the SRTP session
srtp_create(&session, &policy);

// main loop: get rtp packets, send srtp packets
while (1) {
  char rtp_buffer[2048];
  size_t len;

  len = get_rtp_packet(rtp_buffer);
  srtp_protect(session, rtp_buffer, &len);
  send_srtp_packet(rtp_buffer, len);
}

Credits

The original implementation and documentation of libSRTP was written by David McGrew of Cisco Systems, Inc. in order to promote the use, understanding, and interoperability of Secure RTP. Michael Jerris contributed support for building under MSVC. Andris Pavenis contributed many important fixes. Brian West contributed changes to enable dynamic linking. Yves Shumann reported documentation bugs. Randell Jesup contributed a working SRTCP implementation and other fixes. Steve Underwood contributed x86_64 portability changes. We also give thanks to Fredrik Thulin, Brian Weis, Mark Baugher, Jeff Chan, Bill Simon, Douglas Smith, Bill May, Richard Preistley, Joe Tardo and others for contributions, comments, and corrections.

This reference material, when applicable, in this documenation was generated using the doxygen utility for automatic documentation of source code.

Copyright 2001-2005 by David A. McGrew, Cisco Systems, Inc.


References

SRTP and ICM References September, 2005

Secure RTP is defined in RFC 3711. The counter mode definition is in Section 4.1.1.

SHA-1 is defined in FIPS PUB 180-4.

HMAC is defined in RFC 2104 and HMAC-SHA1 test vectors are available in RFC 2202.

AES-GCM usage in SRTP is defined in RFC 7714

libsrtp's People

Contributors

bernardotorres avatar bifurcation avatar coien avatar davidmcgrew avatar fancycode avatar fluffy avatar guidovranken avatar jaapkeuter avatar jfigus avatar jmillan avatar lastique avatar mfroeschl avatar mildsunrise avatar mmdriley avatar nils-ohlmeier avatar nirbheek avatar pabuhler avatar palerikm avatar paulej avatar rsith71 avatar saghul avatar sobomax avatar sparkidev avatar thisisg avatar tp-m avatar traud avatar traviscross avatar tvsriram avatar ulfolsson avatar ycyang1229 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libsrtp's Issues

application build break on libsrtp

when compiling doubango with latest libsrtp,
svn checkout http://doubango.googlecode.com/svn/branches/2.0/doubango doubango
cd ./doubango && ./autogen.sh && ./configure --with-speexdsp --with-ffmpeg && make && make install

In file included from /usr/local/include/srtp/datatypes.h:50:0,
from /usr/local/include/srtp/err.h:49,
from /usr/local/include/srtp/rand_source.h:49,
from /usr/local/include/srtp/crypto_kernel.h:49,
from /usr/local/include/srtp/srtp.h:55,
from include/tinyrtp/trtp_srtp.h:30,
from include/tinyrtp/rtcp/trtp_rtcp_session.h:33,
from include/tinyrtp/trtp_manager.h:30,
from src/trtp_manager.c:25:
/usr/local/include/srtp/integers.h:102:16: error: conflicting types for 'uint64_t'
typedef double uint64_t;

In file included from ../tinyNET/src/tnet_types.h:40:0,
from include/tinyrtp/rtcp/trtp_rtcp_session.h:35,
from include/tinyrtp/trtp_manager.h:30,
from src/trtp_manager.c:25:
/usr/include/netinet/in.h:367:17: error: conflicting types for 'htonl'
extern uint32_t htonl (uint32_t __hostlong)

Reading arbitrary stack memory in aes_gcm_openssl_set_aad()

OpenSSL function call at aes_gcm_ossl.c:261 can sometimes read more than is pointed by aad function argument. For example, if called from srtp.c:2415. In this case tseq is 4 bytes long, but 8 bytes is read.

Fix could be to use aad_len instead of c->tag_len when calling EVP_CIPHER_CTX_ctrl, but I'm not sure about it.

failure when RTP sequence number switches from 65535 -> 0

See here https://issues.asterisk.org/jira/browse/ASTERISK-16898
This issue still exists and the claim is that it is caused by libsrtp. In my case I'm using the latest wheezy libsrtp 1.4.4+20100615~dfsg-2 on i386. As described in the link above there is a loss of audio on average around 10 min mark (depending on the initial sequence number) with Nokia phones <-> Asterisk that uses libsrtp. The audio is lost one way, the Nokia still receives and plays audio but Asterisk rejects incoming SRTP packets.
Can this be fixed in your release? Thanks.

Intermittent stat_driver failure on sparc 64 target

This issue was reported by Daniel Pocock while troubleshooting the following bug reported on the Debian distro:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=628583

The problem is stat_driver doesn't initialize the nonce value to zero. Whatever memory happens to reside in the nonce value is used for the test. The following patch resolves the problem.

diff --git a/crypto/test/stat_driver.c b/crypto/test/stat_driver.c
index f9d75b7..145cd02 100644
--- a/crypto/test/stat_driver.c
+++ b/crypto/test/stat_driver.c
@@ -51,6 +51,7 @@ main (int argc, char *argv[]) {

printf("statistical tests driver\n");

  • v128_set_to_zero(&nonce);
    for (i=0; i < 2500; i++)
    buffer[i] = 0;

char assumed signed in testsuite drivers

http://sourceforge.net/tracker/?func=detail&aid=1911854&group_id=38894&atid=423799

There is a bug in test/rdbx_driver.c and test/srtp_driver.c which makes the testsuite always fail on architectures where char is unsigned by default. This breaks the Debian builds for all such architectures (arm in my case).

The symptom is that test/rdbx_driver and test/srtp_driver always output their usage message and fail because

main (int argc, char *argv[]) {
char q;

/* process input arguments */
while (1) {
q = getopt_s(argc, argv, "tv");
if (q == -1)
break;

That should be "int q;"

sha1_update function name conflict

This is not an issue, just a suggestion to change the function name "sha1_update()" and "sha1()" in "crypto/hash/sha1.c" as it conflicts with a system library.

Thanks for the wonderful soffware.
YM

Random failures of srtp_init()

http://sourceforge.net/tracker/?func=detail&aid=1428214&group_id=38894&atid=423799

srtp_init() randomly fails to initialize. If libsrtp.a
and test program is compiled with profiling enabled,
failures happen much more often.

System information:
Linux, Fedora Core 4, gcc-4.0.2 (compiling libsrtp with
gcc-3.2 does not help)
libsrtp-1.4.1 (similar problems also with recent CVS
version)

Test script (sources inside it) is included below


! /bin/sh

echo '#include <srtp/srtp.h>

include <stdio.h>

int main(void)
{
err_status_t status;
status = srtp_init();
printf ("srtp_init %s\n", status ? "failed" :
"suceeded");
return status;
}' | gcc -O2 -x c - -lsrtp -o srtp_bad || exit 1
tests=0
bad=0
while true; do
tests=$(($tests+1))
if ./srtp_bad | grep -q failed ; then
bad=$(($bad+1))
echo "$bad errors of $tests tests"
fi
done

crypto/kernel/alloc.c:102:5: warning: suggest braces around - ID: 3591521

http://sourceforge.net/tracker/?func=detail&aid=3591521&group_id=38894&atid=423799

If ENABLE_DEBUGGING isn't turned on, then this chunk of code ends up with an empty un-braced "else" statement:
http://srtp.cvs.sourceforge.net/viewvc/srtp/srtp/crypto/kernel/alloc.c?view=annotate#l101

and it triggers this build warning:
crypto/kernel/alloc.c:102:5: warning: suggest braces around empty body in an โ€˜elseโ€™ statement [-Wempty-body]

Filing this bug on adding braces around the "else" condition, to fix that build warning.

receive err_status_auth_fail on new Cisco phone pcap.

I use this libsrtp to decode stream from older Cisco phone (CP-7961G, CP-7962G and CP-7941G) without error.
But receive err_status_auth_fail when decoding stream for newer Cisco phone (CP-6921).

crypto suite: AES_CM_128_HMAC_SHA1_32

here is the old phone pcap sample:
masterkey: 23EBBC24A350FD0F9B8278FB2E35445AA1F3B20C594293EF6411ECB1847D
pcap:
8000614B6A6A12B601A7A0865357C37CC109A10A2CBF7CA3F13BD27FD223C697FDAD1858598CA234AA755F9071E7D4B64BCC514D2001E2BF0A3E36720BFB297BBB75FA8154899FE46E9A205B0818AD841A69AFA34D74FF0AF093391CD7484A7A5A1F2E1591CB75BC66873EA1B613FDCC48AC90458C5A5D2DA889117E06B1D9F48AEC846C9194B85FD5E35ADD14C787D93F49BD1C5717C33E99E8F04D48FC384366E21C483CCB6ACA7F1CE484D6A6AE30

here is the new phone pcap:
masterkey0: 8C11DE9AEA08ECE9253ECC78BFFE0BFB2C900B011994ED5A9F8BB5B03729
pcap from port 7000:
800030A8002BE06066E6C56E777A7576787579FDFCFBF5F2F1EDECECECEFEFEFF3F0F2F5F6FCFCFDFFFDFCF9F6F6F5F9F8F77D7CFE7A7A736B6A6B6A6C7170757E7E79787C7974757A7FFCFBFCF8FB7C7A7877797DFDF9F7FBFDFCF8F9FAFA7F7A77787A7A7BFDF8F6F2F4F9FF7879777274747577797977797A797A7E7F7C7D7D787C7F7B7A797879797C7FFEFAF6F3F2F8FCF6FA7C78707073717578797A7AFFFCFEFDFDFDFF7C7C7A787BE189E33F

masterkey1:
C8AD29D871420A23113DEF9C053AAA388C90A086C345925061C06F98F69C
pcap from port 7001:
80002F34552AD97B66E6C5797B7B7B7DFFFEFDFEFDFDFCFBFBFBFBFDFDFDFDFDFEFEFDFCFCFDFEFDFEFF7E7E7E7D7D7C7B7D7E7E7E7D7E7F7E7C7A797979797A7C7E7F7E7EFFFE7E7D7C7C7D7D7D7E7EFFFCFBFBFBFAFBFDFEFEFDFE7F7E7EFFFEFFFEFEFEFDFBFCFDFE7E7E7F7D7C7E7E7D7E7D7EFF7E7E7E7E7D7C7C7D7D7E7E7FFEFEFDFDFDFCFEFEFDFDFEFEFEFEFDFEFFFEFF7E7D7DFFFE7F7E7D7FFDFCFCFCFCFCFCFCFDFDFDFCFCFE1D6C4671

masterkey2:
EE34892BFC583C5D32FD72C3E646434F3322865AFA457A8EF5DDB87E3061
pcap from port 7002:
8000C9AD552C331B939A8EFAFDFCFCFBFCFCFCFDFDFCFD7E7D7D7E7FFEFDFCFCFCFEFFFF7FFF7F7E7E7D7D7D7C7C7D7F7E7DFFFDFEFF7D7E7F7E7E7EFFFEFEFEFEFFFFFF7E7D7E7F7D7D7E7E7F7F7EFEFEFE7E7E7E7DFF7F7E7D7D7E7D7D7D7DFEFF7D7E7F7F7E7C7C7C7E7E7EFEFEFF7E7E7E7E7D7B7A7A7A7A7A797A7C7FFEFFFFFEFDFDFEFEFEFF7E7E7FFDFCFEFEFEFE7E7EFEFCFCFCFCFCFDFEFEFE7FFEFCFBFBFBFCFDFE7F7E7E7E7F90DCC7AD

masterkey3:
503AA422B7BEF689EE38AE22555D44484EB84AA94E60EAC2CE1251D4D26E
pcap from port 7003:
8000C59A002D6AC0939A8F056E6E6D71777AFDFDFDFAFBFCFFFEFEFE7D7FFA7F7D7A767C797775767EFBF3F0F1F2F4F97E787478776E6D6E7270707574767C7FFDFAFC7B79777575777977787EFEF7F5F7EEEBECECE9E9EBEDF0F6FE7D76737C78747672797EFDF4F4F6F9FDFE746F716F716F6E7374706F6F75756F6F6D6D7376797A7BFCF8F6F9F6F2F5F2F2F6F3EFECEDEFF4F9FAF9F9FCFBFCFFFAFCFBFA7D7B7EFF7DFFFE7D78777872BB453870

I have tried all 4 keys for decoding a same pcap. All receive err_status_auth_fail.
according to the rfc3711: "If the result is "AUTHENTICATION FAILURE" (see Section 4.2), the packet MUST be discarded from further processing and the event SHOULD be logged."

But the rest of the pcaps also returns err_status_auth_fail.

testsuite violates 32-bit-alignment assumption -

http://sourceforge.net/tracker/?func=detail&aid=1912057&group_id=38894&atid=423799

The testsuite fails on architectures where 32-bit accesses must be 32-bit aligned because test/srtp_driver.c hands unaligned data to srtp_protect() and srtp_unprotect(). This makes the testsuite fail on arm.

There are #ifdef ALIGNMENT_32BIT_REQUIRED macros for word access in crypto/include/integers.h, but these are never used anywhere. Instead the srtp_*protect() routines say they require 32bit-aligned data in the commentary.

As a quick fix for the Debian arm variants, I've made the minimal change (patch attached), simply aligning the test character arrays used in the test program, which solves the problem.

A more robust solution would be to lift the alignment requirement by using the GET_32 and PUT_32 macros and enabling ALIGNMENT_32BIT_REQUIRED in the header #ifdef arm - that way other people's unaligned code using these functions that seems to work for them would not break mysteriously on arm.

Crash on short SRTCP packet

If srtp_unprotect_rtcp is called for a packet with a valid SSRC, but a length shorter than the configured tag length, it will crash when auth_len becomes negative and wraps around, so auth_compute is called with a length slightly less than UINT_MAX.

I havenโ€™t worked through the other code paths, but it looks like the same thing can happen in other unprotect code paths as well.

Allow testing with pcap file or capture

A good test would be allowing to capture on the wire or offline a SRTP stream.

I have derived code from https://github.com/gteissier/srtp-decrypt (which caused me a few headaches because it didn't work in all cases) and joined it with rtpw test code to make it possible.

There is room for improvement, if you have any particular request or opinion, please express so I can improve the code for it to be approved.

Thanks for libsrtp, btw.

Makefile:
CFLAGS=-g -Os -Wall

all:
$(CC) -g decrypt-srtp.c -o decrypt-srtp -I /usr/local/include/srtp/ -l pcap -lgcrypt -lsrtp
check:
./decrypt-srtp -k aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz < ./marseillaise-srtp.pcap | text2pcap -t "%M:%S." -u 10000,10000 - - > ./marseillaise-rtp.pcap

The code is below:

include <sys/types.h>

include <stdint.h>

include <stdlib.h>

include <string.h>

include <unistd.h>

include <stdio.h>

include <arpa/inet.h>

include <getopt.h>

include <assert.h>

include "rtp.h"

include "rtp_priv.h"

include "srtp.h"

include <pcap.h>

define PRINT_DEBUG 1

define VERBOSE_DEBUG 1

define DICT_FILE "/usr/share/dict/words"

define USEC_RATE (5e5)

define MAX_WORD_LEN 128

define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))

define MAX_KEY_LEN 96

srtp_t srtp_ctx = NULL;

rtp_msg_t message;

/*

  • srtp_print_packet(...) is for debugging only
  • it prints an RTP packet to the stdout
    *
  • note that this function is not threadsafe
    */

include <stdio.h>

define MTU 2048

static const char b64chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static unsigned char shiftb64(unsigned char c) {
char *p = strchr(b64chars, c);
assert(p);
return p-b64chars;
}

static void decode_block(unsigned char *in, unsigned char *out) {
unsigned char shifts[4];
int i;

for (i = 0; i < 4; i++) {
shifts[i] = shiftb64(in[i]);
}

out[0] = (shifts[0]<<2)|(shifts[1]>>4);
out[1] = (shifts[1]<<4)|(shifts[2]>>2);
out[2] = (shifts[2]<<6)|shifts[3];
}

char packet_string[MTU];

char *
srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) {
int octets_in_rtp_header = 12;
uint8_t *data = ((uint8_t *)hdr)+octets_in_rtp_header;
int hex_len = pkt_octet_len-octets_in_rtp_header;

/* sanity checking */
if ((hdr == NULL) || (pkt_octet_len > MTU))
return NULL;

/* write packet into string */
sprintf(packet_string,
"(s)rtp packet: {\n"
" version:\t%d\n"
" p:\t\t%d\n"
" x:\t\t%d\n"
" cc:\t\t%d\n"
" m:\t\t%d\n"
" pt:\t\t%x\n"
" seq:\t\t%x\n"
" ts:\t\t%x\n"
" ssrc:\t%x\n"
" data:\t%s\n"
"} (%d octets in total)\n",
hdr->version,
hdr->p,
hdr->x,
hdr->cc,
hdr->m,
hdr->pt,
hdr->seq,
hdr->ts,
hdr->ssrc,
octet_string_hex_string(data, hex_len),
pkt_octet_len);

return packet_string;
}

void
usage(char *string) {

printf("usage: %s [-d ]* [-k [-a][-e]]\n"
"or %s -l\n"
"where -a use message authentication\n"
" -e use encryption (use 128 or 256 for key size)\n"
" -g Use AES-GCM mode (must be used with -e)\n"
" -k sets the srtp master key\n"
" -l list debug modules\n"
" -d turn on debugging for module \n",
string, string);
exit(1);

}

static void decode_sdes(unsigned char *in,
unsigned char *key) {
int i;
size_t len = strlen((char *) in);
assert(len == 40);
unsigned char raw[30];

for (i = 0; 4_i < len; i++) {
decode_block(in+4_i, raw+3*i);
}

memcpy(key, octet_string_hex_string(raw, 30), 60);
}

static void hexdump(const void *ptr, size_t size) {
int i, j;
const unsigned char *cptr = ptr;

for (i = 0; i < size; i += 16) {
printf("%04x ", i);
for (j = 0; j < 16 && i+j < size; j++) {
printf("%02x ", cptr[i+j]);
}
printf("\n");
}
}

static int rtp_offset = 42; /* 14 + 20 + 8 */;
static int frame_nr = -1;
static struct timeval start_tv = {0, 0};

static void handle_pkt(u_char *arg, const struct pcap_pkthdr *hdr,
const u_char *bytes) {
int pktsize;
struct timeval delta;
int octets_recvd;
err_status_t stat;
int *len = NULL;
void *msg = NULL;
frame_nr += 1;
if (start_tv.tv_sec == 0 && start_tv.tv_sec == 0) {
start_tv = hdr->ts;
}

if (hdr->caplen < rtp_offset) {
fprintf(stderr, "frame %d dropped: too short\n", frame_nr);
return;
}
void *rtp_packet = bytes + rtp_offset;

//memcpy(buffer, bytes + rtp_offset, hdr->caplen - rtp_offset);
memcpy((void )&message, rtp_packet, hdr->caplen - rtp_offset);
/

message.header.seq = htons(message.header.seq);
message.header.ssrc = htonl(message.header.ssrc);
message.header.ts = htonl(message.header.ts);
*/
pktsize = hdr->caplen - rtp_offset;
octets_recvd = pktsize;

if (octets_recvd == -1) {
printf("octects less than 1.\n");
//*len = 0;
//return -1;
return;
}

/* verify rtp header _/
if (message.header.version != 2) {
printf("rtp version is not 2.\n");
//_len = 0;
return; //return -1;
}

if PRINT_DEBUG

// printf("%d octets received from SSRC %u\n",
// octets_recvd, message.header.ssrc);

endif

if VERBOSE_DEBUG

//printf("PACKET: %s\n", );
// hexdump(bytes + rtp_offset, octets_recvd);
// printf(srtp_packet_to_string(&message.header, octets_recvd));

endif

/* apply srtp */
stat = srtp_unprotect(srtp_ctx, &message.header, &octets_recvd);
if (stat) {
fprintf(stderr,
"error: srtp unprotection failed with code %d%s\n", stat,
stat == err_status_replay_fail ? " (replay check failed)" :
stat == err_status_bad_param ? " (bad param)" :
stat == err_status_no_ctx ? " (no context)" :
stat == err_status_cipher_fail ? " (cipher failed)" :
stat == err_status_key_expired ? " (key expired)" :
stat == err_status_auth_fail ? " (auth check failed)" : "");
//return -1;
return;
}
//strncpy(msg, rtp_packet, octets_recvd);

//printf(srtp_packet_to_string(&message.header, octets_recvd));
timersub(&hdr->ts, &start_tv, &delta);
printf("%02ld:%02ld.%06lu\n", delta.tv_sec/60, delta.tv_sec%60, delta.tv_usec);
hexdump(&message.header, pktsize);
}

int main(int argc, char **argv) {
int c;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *pcap;

char dictfile = DICT_FILE;
FILE *dict;
char word[MAX_WORD_LEN];
int sock, ret;
struct in_addr rcvr_addr;
struct sockaddr_in name;
struct ip_mreq mreq;
struct sockaddr_in local;
sec_serv_t sec_servs = sec_serv_none;
unsigned char ttl = 5;
int key_size = 128;
int gcm_on = 0;
char *input_key = malloc(MAX_KEY_LEN);
char *address = NULL;
char key[MAX_KEY_LEN];
unsigned short port = 0;
rtp_sender_t snd;
srtp_policy_t policy;
// const struct srtp_policy_t policy;
err_status_t status;
int len;
int do_list_mods = 0;
uint32_t ssrc = 0xdeadbeef; /
ssrc value hardcoded for now */

status = srtp_init();

/* check args */
while (1) {
c = getopt(argc, argv, "b:k:rsae:ld:");
if (c == -1) {
break;
}
switch (c) {
case 'b':
//input_key = (unsigned char *) optarg;
decode_sdes(optarg, input_key);
break;
case 'k':
input_key = (unsigned char *) optarg;
break;
case 'e':
key_size = atoi(optarg);
if (key_size != 128 && key_size != 256) {
printf("error: encryption key size must be 128 or 256 (%d)\n", key_size);
exit(1);
}
sec_servs |= sec_serv_conf;
break;
case 'a':
sec_servs |= sec_serv_auth;
break;
case 'd':
status = crypto_kernel_set_debug_module(optarg, 1);
if (status) {
printf("error: set debug module (%s) failed\n", optarg);
exit(1);
}
break;
case 'l':
do_list_mods = 1;
break;
default:
usage(argv[0]);
}
}

if (do_list_mods) {
status = crypto_kernel_list_debug_modules();
if (status) {
printf("error: list of debug modules failed\n");
exit(1);
}
return 0;
}
if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
/*
* a key must be provided if and only if security services have
* been requested
*/
fprintf(stderr, "Key was not provided!\n");
usage(argv[0]);
}

/* report security services selected on the command line */
printf("security services: ");
if (sec_servs & sec_serv_conf)
printf("confidentiality ");
if (sec_servs & sec_serv_auth)
printf("message authentication");
if (sec_servs == sec_serv_none)
printf("none");
printf("\n");

/* set up the srtp policy and master key /
if (sec_servs) {
/

* create policy structure, using the default mechanisms but
* with only the security services requested on the command line,
* using the right SSRC value
*/
switch (sec_servs) {
case sec_serv_conf_and_auth:
if (gcm_on) {

ifdef OPENSSL

    switch (key_size) {
    case 128:
      crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
      crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
      break;
    case 256:
      crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
      crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
      break;
    }

else

    printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n");
    return 0;

endif

  } else {
    switch (key_size) {
    case 128:
      printf("Setting default aes_cm_128_hmac_sha1_80 policy\n");
      crypto_policy_set_rtp_default(&policy.rtp);
      crypto_policy_set_rtcp_default(&policy.rtcp);
      break;
    case 256:
      crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
      crypto_policy_set_rtcp_default(&policy.rtcp);
      break;
    }
  }
  break;
case sec_serv_conf:
  if (gcm_on) {
      printf("error: GCM mode must always be used with auth enabled\n");
      return -1;
  } else {
    switch (key_size) {
    case 128:
      crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
      crypto_policy_set_rtcp_default(&policy.rtcp);
      break;
    case 256:
      crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
      crypto_policy_set_rtcp_default(&policy.rtcp);
      break;
    }
  }
  break;
case sec_serv_auth:
  if (gcm_on) {

ifdef OPENSSL

    switch (key_size) {
    case 128:
      crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
      crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp);
      break;
    case 256:
      crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
      crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp);
      break;
    }

else

    printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n");
    return 0;

endif

  } else {
    printf("Setting null_cipher_hmac_sha1_80 policy.\n");
    crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
    crypto_policy_set_rtcp_default(&policy.rtcp);
  }
  break;
default:
  printf("error: unknown security service requested\n");
  return -1;
}
}
policy.ssrc.type  = ssrc_specific;
policy.ssrc.value = 1479099981;
policy.key  = (uint8_t *) key;
policy.ekt  = NULL;
policy.next = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.rtp.sec_serv = sec_servs;
policy.rtp.auth_tag_len = 0;
policy.rtcp.sec_serv = sec_servs;  /* we don't do RTCP anyway */

/*
 * read key from hexadecimal on command line into an octet string
 */
len = hex_string_to_octet_string(key, input_key, policy.rtp.cipher_key_len*2);

/* check that hex string is the right length */
if (len < policy.rtp.cipher_key_len*2) {
  fprintf(stderr,
          "error: too few digits in key/salt "
          "(should be %d hexadecimal digits, found %d)\n",
          policy.rtp.cipher_key_len*2, len);
  exit(1);
}
if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
  fprintf(stderr,
          "error: too many digits in key/salt "
          "(should be %d hexadecimal digits, found %u)\n",
          policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key));
  exit(1);
}

printf("set master key/salt to %s/", octet_string_hex_string(key, 16));
printf("%s\n", octet_string_hex_string(key+16, 14));

/* set header values */

/*
rcvr->message.header.ssrc = htonl(ssrc);
rcvr->message.header.ts = 0;
rcvr->message.header.seq = 0;
rcvr->message.header.m = 0;
rcvr->message.header.pt = 0x1;
rcvr->message.header.version = 2;
rcvr->message.header.p = 0;
rcvr->message.header.x = 0;
rcvr->message.header.cc = 0;
*/

printf("Creating.\n");
srtp_create(&srtp_ctx, &policy);
printf("Created.\n");

pcap = pcap_open_offline("-", errbuf);
if (!pcap) {
    fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
    exit(1);
}
assert(pcap != NULL);

pcap_loop(pcap, 0, handle_pkt, NULL);


return 0;

}

Allow RNG code to be compiled out

If all keys are generated externally, there's no need for the built-in RNG. It would be nice to allow libsrtp to be compiled without any RNG to a) reduce code size and b) ensure that a weak RNG is not used accidentally.

What is the purpose of srtp_event_data_t->stream if srtp_stream_t is opaque?

The event emitter provides a single argument of type srtp_event_data_t which contains a srtp_stream_t member. Why? It is 100% useless given that it is an opaque struct:

typedef struct srtp_stream_ctx_t *srtp_stream_t;

and srtp_stream_ctx_t is defined in the private file include/srtp_priv.h. So being in an event callback function I cannot even get the SSRC value of the affected stream:

void on_srtp_event(srtp_event_data_t* data) {
    uint32_t ssrc = data->stream->ssrc;
}


=> it produces:

error: member access into incomplete type 'struct srtp_stream_ctx_t'
        uint32_t ssrc = data->stream->ssrc;
                                    ^
/usr/local/include/srtp/srtp.h:275:16: note: forward declaration of 'srtp_stream_ctx_t'
typedef struct srtp_stream_ctx_t *srtp_stream_t;

so what is the purpose of the stream field in the event data? is there any way to get the SSRC value of the affected stream?

Add a libsrtp_get_version() function

Add functions int libsrtp_get_version() and const char* libsrtp_get_version_string().

Please make libsrtp a modern library. We need to know which version is installed when libsrtp is dynamically loaded.

aes_icm_encrypt_ismacryp returns err_status_terminus

http://sourceforge.net/tracker/?func=detail&aid=3568831&group_id=38894&atid=423799

If I understand correctly, aes_icm_encrypt_ismacryp incorrectly examines the 128 bit counter to determine if it would roll over. This can cause the function to return err_status_terminus prematurely, which among other things seriously breaks crypto_gen_random, and, in turn, SRTP on Asterisk (SRTP calls stop working and the server logs "Can't provide secure audio requested in SDP offer"; Asterisk needs to be restarted to fix it). I have attached a patch with the fix we're using internally, let me know if it's correct

ldd does not show deb on -lcrypto

This problem was reported by Alexander Traud...

libsrtp.so has missing references to the OpenSSL AES-GCM symbols. This is
because -lcrypto is not referenced by the library. The attached patch adds
the reference to those symbols in that library.

Step to reproduce

  1. Ubuntu 14.04 LTS (32bit and 64bit tested, does not matter)
  2. sudo apt-get update
  3. sudo apt-get install git build-essential libssl-dev libncurses-dev
    libnewt-dev libxml2-dev linux-headers-$(uname -r) libsqlite3-dev uuid-dev
    libjansson-dev
    (these are my packages, because I compile Asterisk in the next step)
  4. git clone https://github.com/cisco/libsrtp.git
  5. cd ./libsrtp*
  6. ./configure --prefix=/usr --enable-openssl
  7. make libsrtp.so
  8. sudo make install
  9. ldd /usr/lib/libsrtp.so

Expected behavior
ldd should show a dependency on -lcrypto

Actual behavior
ldd does not show that at all

Regression
If I create a small app which calls srtp_init, linking fails because the
EVP_* symbols (AES-GCM) are not referenced. Furthermore, the configure
script of Asterisk (and the one of PJSIP with --enabled-shared
--with-external-srtp) are not able to detect libSRTP because they try to
load srtp_init as well. With the above patch, my own app, Asterisk and PJSIP
are happy.

Notes
Solution is based on (see parameter library_list):
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html.

I do not know how to report issues within the libSRTP project and/or GitHub.
If there is another formal process, please, point me to that. Because you
added both the AES-GCM and the libsrtp.so code to the main branch, I
contacted just you.

libsrtpSharedLibraryWithDep.patch

--- Makefile.in (revision 29b152e)
+++ Makefile.in (working copy)
@@ -117,8 +117,8 @@
$(RANLIB) libsrtp.a

libsrtp.so: $(srtpobj) $(cryptobj) $(gdoi)

  • $(CC) -shared -Wl,-soname,libsrtp.so $(LDFLAGS) \
  •   -o libsrtp.so $^
    
  • $(CC) -shared -Wl,-soname,libsrtp.so \
  •   -o libsrtp.so $^ $(LDFLAGS)
    

    libcryptomath.a contains general-purpose routines that are used to

    generate tables and verify cryptoalgorithm implementations - this

ERR_REPORTING_SYSLOG is never defined

Does the --enable-syslog work? I read in the code:

  • Errors will be reported to ERR_REPORTING_FILE, if defined, and to
  • syslog, if ERR_REPORTING_SYSLOG is defined.

But the fact is that ERR_REPORTING_SYSLOG is never defined, so I don't know how syslog is supposed to work.

configure fails in Linux 64 and OSX (since removal of config.h)

Since 8376a64 ./configure fails. This is config.log in OSX with clang (it also fails in Linux Debian with GCC 4.8):

configure:4494: checking for uint64_t
configure:4494: gcc -c -fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops  conftest.c >&5
clang: warning: -O4 is equivalent to -O3
configure:4494: $? = 0
configure:4494: gcc -c -fPIC -Wall -O4 -fexpensive-optimizations -funroll-loops  conftest.c >&5
clang: warning: -O4 is equivalent to -O3
conftest.c:75:23: error: expected expression
if (sizeof ((uint64_t)))
                      ^
1 error generated.
configure:4494: $? = 1
configure: failed program was:

When later libsrtp header is included into a project which already includes <stdint.h> (in C) or <cstdint> (in C++), it fails:

In file included from /usr/local/include/srtp/srtp.h:53:
In file included from /usr/local/include/srtp/crypto_kernel.h:49:
In file included from /usr/local/include/srtp/rand_source.h:49:
In file included from /usr/local/include/srtp/err.h:49:
In file included from /usr/local/include/srtp/datatypes.h:50:
/usr/local/include/srtp/integers.h:102:16: error: typedef redefinition with different types ('double' vs 'unsigned long long')
typedef double uint64_t;
               ^
/usr/include/_types/_uint64_t.h:31:28: note: previous definition is here
typedef unsigned long long uint64_t;
                           ^

Must the key given to srtp_policy_t be allocated?

void setSRTP(uint8_t* key, size_t key_len) {
  srtp_t session;
  srtp_policy_t policy;

  memset(&policy, 0, sizeof(srtp_policy_t));
  crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
  crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
  policy.key = key;  // <---------------is it OK?
  policy.next = NULL;

  srtp_create(&session, &policy);

  [...]
}

I wonder whether policy.key = key is correct or not (assuming that the buffer pointed by the given key is deallocated once the function setSRTP() returns).

Is the code above safe? or must I keep the key allocated while the SRTP session exists?

Allow storing void* data into the strp_t session.

When libsrtp fires a provisioned callback it calls it with a srtp_event_data_t struct as argument. The struct contains some fields, including the srtp_t session the event belongs to.

The problem is that I cannot associate my "application SRTP handler" with such a srtp_t session so when the callback is fired I do not know which of my SRTP handlers the session belongs to.

I suggest adding a void* user_data into the srtp_t struct, and two new functions:

void srtp_set_user_data(srtp_t session, void* data);
void* srtp_get_user_data(srtp_t session);

NOTE: This is similar to what other C libraries do. For example OpenSSL provides some functions for this same purpose:

int SSL_set_ex_data(SSL *ssl, int idx, void *arg);
void *SSL_get_ex_data(const SSL *ssl, int idx);

libsrtp header validation fails when header extensions are present

https://codereview.chromium.org/19678006/

This was a patch submit to chromium.

Index: srtp/srtp/srtp.c

--- srtp/srtp/srtp.c (revision 212142)
+++ srtp/srtp/srtp.c (working copy)
@@ -68,6 +68,7 @@
#define uint32s_in_rtp_header 3
#define octets_in_rtcp_header 8
#define uint32s_in_rtcp_header 2
+#define octets_in_rtp_extn_hdr 4

err_status_t
@@ -733,6 +734,12 @@
if (*pkt_octet_len < octets_in_rtp_header)
return err_status_bad_param;

  • /* Check RTP header length */
  • int rtp_header_len = octets_in_rtp_header + 4 * hdr->cc +
  •   (hdr->x == 1) ? octents_in_rtp_extn_hdr : 0;
    
  • if (*pkt_octet_len < rtp_header_len)
  • return err_status_bad_param;

/*

  • look up ssrc in srtp_stream list, and process the packet with
  • the appropriate stream. if we haven't seen this stream before,
    @@ -977,6 +984,12 @@
    if (*pkt_octet_len < octets_in_rtp_header)
    return err_status_bad_param;
  • /* Check RTP header length */
  • int rtp_header_len = octets_in_rtp_header + 4 * hdr->cc +
  •  (hdr->x == 1) ? octents_in_rtp_extn_hdr : 0;
    
  • if (*pkt_octet_len < rtp_header_len)
  • return err_status_bad_param;

/*

  • look up ssrc in srtp_stream list, and process the packet with
  • the appropriate stream. if we haven't seen this stream before,

cipher_t algorithm not set for non-openssl ciphers

The algorithm member of the cipher_t structure is not set on cipher alloc, neither on aes_gcm.c nor aes_icm.c (as opposed to aes_icm_ossl.c aes_gcm_ossl.c).

That causes, among other possible issues, srtp_protect and srtp_unprotect to ramdonly fail with cipher_fail error because in srtp.c the following check is done:

if (stream->rtp_cipher->algorithm == AES_128_GCM ||
stream->rtp_cipher->algorithm == AES_256_GCM) {
return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, pkt_octet_len);
}

but set_aad function pointer of the aes icm ciphet type causing cipher_set_aad to fail.

Does libsrtp keep a static list of managed streams identified by their SSRC?

I create two srtp_t sessions, set policy.ssrc.type = ssrc_any_outbound in both of them, and then call to srtp_protect() to both of them by passing the same RTP packet/data with the same SSRC value in both calls (note that before calling srtp_protect() I do a memcpy of the original RTP data, so the original one remains unchanged when the second call to srtp_protect() takes place in the second session).

In this scenario I get lot of err_status_replay_old errors ("replay check failed (index too old)").

So I wonder: may be libsrtp handles a global/static list of streams so two different and independent srtp_t sessions should NEVER try to protect the same RTP packet?

If this is true, please confirm it. Thanks a lot.

AES GCM mode using wrong SALT size

The Master SALT for GCM mode should be 96 bits. Currently the GCM mode uses the same SALT_SIZE directive as ICM mode, which is set to a value of 14 (112 bits). As a result, the values derived from the KDF are wrong. Additionally, applications that use GCM mode are required to provide 30 bytes of key/salt material, where only 28 bytes should be required.

Remove xfm.c from the tree

The source file xfm.c is not referenced in any of the Makefiles and should be removed from the tree. This appears to be stale code.

crypto_get_random prematurely fails with err_status_terminus -

http://sourceforge.net/tracker/?func=detail&aid=3568912&group_id=38894&atid=423799

ctr_prng_get_octet_string (internal implementation of crypto_get_random) uses the AES CTR keystream generator incorrectly. The keystream generator, being made for SRTP packets, is limited to generating 2^16 blocks of 2^128 random bits, i.e 1 MB, while ctr_prng_get_octet_string only reinitializes the PRNG after 4 GB of random data. Either this is a misuse of the keystream generator (my guess), or the crypto_get_random function has a misleading name

bug in srtp_remove_stream

http://sourceforge.net/tracker/?func=detail&aid=2192597&group_id=38894&atid=423799

I found a bug in srtp_remove_stream.

This:
/* remove stream from the list */
last_stream->next = stream->next;

Does not work if there is only one stream in the list. You need something like:
/* remove stream from the list */
if (last_stream == stream){
// only one stream in list
session->stream_list = stream->next;
} else {
last_stream->next = stream->next;
}

The following pseudo-code uncovered this problem:
srtp_t srtpSession;
srtp_policy_t srtpPolicy;
srtp_init();
srtp_create(&srtpSession, NULL);
srtp_add_stream(srtpSession, &srtpPolicy);
srtp_remove_stream(srtpSession, the_ssrc);
srtp_dealloc(srtpSession);
Memory fault

Linking SRTP from C++ in MSVC

I found a problem when linking from C++ application with libsrtp ( I don't know if it's categorized as a problem), the default config #define inline as blank, this is due to MSVC lack of C99 support while C89 doesn't have it. It works fine with C applications. Once you link from C++, it will violate one definition rule. My work around was to define inline __inline; this way the C++ will have no problem linking to the C library.

A better solution would be to include a pre-processor

if defined(MSVC) && defined(__cplusplus) #define inline _inline

I hope someone finds this useful.

Potential buffer overflow in srtp_protect()

Applications invoking srtp_protect() need to ensure the write buffer has additional memory available at the end to hold the authentication tag. The documentation should be updated to warn users of this potential problem.

Use AC_MSG_RESULT to output enable_openssl flag

This problem was reported by Alexander Traud...

When I start configure in Ubuntu 14.04 LTS, there is a single line just with
'no' or 'yes', depending on the --enable-openssl flag. The attached patch
fixed this for me.

libsrtpConfigureRemoveSillyEcho.patch

--- configure.in (revision b90f1ba)
+++ configure.in (working copy)
@@ -143,7 +143,7 @@
[compile in OpenSSL crypto engine])],
[], enable_openssl=no)
if test "$enable_openssl" = "yes"; then

  • echo $enable_openssl
  • AC_MSG_RESULT($enable_openssl)
    LDFLAGS="$LDFLAGS $(pkg-config --libs openssl)";
    CFLAGS="$CFLAGS $(pkg-config --cflags openssl)";

@@ -160,7 +160,7 @@
USE_OPENSSL=1
AC_SUBST(USE_OPENSSL)
else

  • echo $enable_openssl
  • AC_MSG_RESULT($enable_openssl)
    AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o crypto/cipher/aes_cbc.o"
    AC_MSG_CHECKING(which random device to use)
    if test "$enable_kernel_linux" = "yes"; then
    @@ -182,7 +182,6 @@
    AC_SUBST(RNG_OBJS)
    AC_SUBST(RNG_EXTRA_OBJS)
    AC_SUBST(HMAC_OBJS)
    -AC_MSG_RESULT($enable_openssl)

AC_MSG_CHECKING(whether to use syslog for error reporting)
AC_ARG_ENABLE(syslog,

Please clarify license of RFC text

Hi,

What is the license of the RFC file ?

I suppose it is according to Trust Legal Provisions (TLP) 3.C distribbuting here means that you have relicenced your own work as BSD ?

care to confirm ?

Bastien

Data race in aes_icm_openssl_alloc

This issue is for openssl branch.

Field ref_count in cipher_type_t struct for aes_icm, aes_icm_192 and aes_icm_256 global instances is incremented in aes_icm_openssl_alloc, e.g. aes_icm_ossl.c:141:

aes_icm.ref_count++;

This causes data race when someone creates srtp contexts in different threads. I know it's pretty harmless, but it's undefined behavior anyway, so better be fixed.

Core dump is caused by SRTCP packets -

http://sourceforge.net/tracker/?func=detail&aid=3280295&group_id=38894&atid=423799

There is an invalid index access in rdb.c when adding an index. When the sequence number of the SRTCP packet is outside of window by more then window size, a bit is set outside of the window bitmap. When sequence number is outside of the window size by more then one, a wrong bit is set. This bug was also reported in srtp implementation of Asterisk (https://issues.asterisk.org/bug_view_page.php?bug_id=17976&history=1). Here is the proposed fix.

In the current code in rdb.c:
err_status_t
rdb_add_index(rdb_t *rdb, uint32_t index) {
uint32_t delta;

/* here we assume that index > rdb->window_start */

delta = (index - rdb->window_start);
if (delta < rdb_bits_in_bitmask) {

/* if the index is within the window, set the appropriate bit */
v128_set_bit(&rdb->bitmask, delta);

} else {

delta -= rdb_bits_in_bitmask - 1;

/* shift the window forward by delta bits*/
v128_left_shift(&rdb->bitmask, delta);
v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask-delta);
rdb->window_start += delta;

}

return err_status_ok;
}

It should be:

err_status_t
rdb_add_index(rdb_t *rdb, uint32_t index) {
uint32_t delta;

/* here we assume that index > rdb->window_start */

delta = (index - rdb->window_start);
if (delta < rdb_bits_in_bitmask) {

/* if the index is within the window, set the appropriate bit */
v128_set_bit(&rdb->bitmask, delta);

} else {

delta -= rdb_bits_in_bitmask - 1;

/* shift the window forward by delta bits*/
v128_left_shift(&rdb->bitmask, delta);
v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask-1);
rdb->window_start += delta;

}

return err_status_ok;
}

test/cipher_driver -v dumps core on solaris

http://sourceforge.net/tracker/?func=detail&aid=1942778&group_id=38894&atid=423800

I attempted libsrtp (srtp-1.4.2 and srtp-1.4.4.)build on solaris 10 but had some problems running the tests. The compile was ok after adding -lnsl to LIBS in Makefile but when I ran test/cipher_driver -v I got a core dump (bus error).

I have seen similar issue in mailing list and some patch was provided for that, can I get the same patch to make it working on solaris.

email add:
[email protected]

Problem using cygwin on windowsxp

http://sourceforge.net/tracker/?func=detail&aid=1812238&group_id=38894&atid=423800

version 1.4.2
i'm using cygwin on windowsxp
After configure and correct make and makeruntest.
When I try to run the test, from the receiver instance I have this error continuosly

"error: srtp unprotection failed with code 2".


version downloaded from cvs.
I have the same error
"error: srtp unprotection failed with code 2".
but now when I run makeruntest
The last lines of shell are those

CPU set to little-endian (WORDS_BIGENDIAN == 0)
CPU set to CISC (CPU_CISC == 1)
using native 64-bit type (NO_64_BIT_MATH == 0)
using stdout for error reporting (ERR_REPORTING_STDOUT == 1)
using as a random source (DEV_URANDOM == )
warning: configuration is probably in error (found 1 problems)
make[1]: *** [runtest] Error 1
make[1]: Leaving directory `/home/srtp144/crypto'
make: *** [runtest] Error 2

Could yoy help me ?
Tanks in advance
lorenzo

[email protected]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.