Move libs/srtp/* to modules/access/rtp/
authorRémi Denis-Courmont <remi@remlab.net>
Tue, 30 Aug 2011 17:02:50 +0000 (20:02 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Tue, 30 Aug 2011 18:36:22 +0000 (21:36 +0300)
16 files changed:
Makefile.am
configure.ac
libs/srtp/.gitignore [deleted file]
libs/srtp/Makefile.am [deleted file]
libs/srtp/recv.c [deleted file]
libs/srtp/srtp.c [deleted file]
libs/srtp/srtp.h [deleted file]
libs/srtp/test-aes.c [deleted file]
libs/srtp/test-recv.c [deleted file]
modules/access/rtp/.gitignore [new file with mode: 0644]
modules/access/rtp/Modules.am
modules/access/rtp/srtp-test-aes.c [new file with mode: 0644]
modules/access/rtp/srtp-test-recv.c [new file with mode: 0644]
modules/access/rtp/srtp.c [new file with mode: 0644]
modules/access/rtp/srtp.h [new file with mode: 0644]
modules/stream_out/Modules.am

index 2598ba4..0138389 100644 (file)
@@ -13,9 +13,6 @@ EXTRA_SUBDIRS = m4 \
 DIST_SUBDIRS = $(BASE_SUBDIRS) $(EXTRA_SUBDIRS)
 
 SUBDIRS = po compat src
-if HAVE_GCRYPT
-SUBDIRS += libs/srtp
-endif
 if BUILD_VLC
 SUBDIRS += bin
 endif
index 277e6e5..781db98 100644 (file)
@@ -4259,7 +4259,6 @@ AC_SUBST(FILE_LIBVLC_DLL)
 AC_CONFIG_FILES([
   Makefile
   doc/Makefile
-  libs/srtp/Makefile
   modules/Makefile
   m4/Makefile
   po/Makefile.in
diff --git a/libs/srtp/.gitignore b/libs/srtp/.gitignore
deleted file mode 100644 (file)
index 717a5e6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-test-aes
-test-recv
diff --git a/libs/srtp/Makefile.am b/libs/srtp/Makefile.am
deleted file mode 100644 (file)
index b90bed1..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# Secure RTP with libgcrypt
-# Copyright (C) 2007  Rémi Denis-Courmont
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-AM_CPPFLAGS = @GCRYPT_CFLAGS@
-
-noinst_HEADERS = srtp.h
-
-EXTRA_PROGRAMS = srtp
-noinst_LTLIBRARIES = libvlc_srtp.la
-check_PROGRAMS = test-aes test-recv
-TESTS = $(check_PROGRAMS)
-
-libvlc_srtp_la_SOURCES = srtp.c
-libvlc_srtp_la_LIBADD = @GCRYPT_LIBS@
-
-srtp_SOURCES = recv.c
-srtp_LDADD = libvlc_srtp.la
-test_recv_LDADD = libvlc_srtp.la
-test_aes_LDADD = @GCRYPT_LIBS@
-
-lcov-run:
-       rm -Rf *.gcda lcov
-       $(MAKE) $(AM_MAKEFLAGS) check
-
-lcov-pre.out:
-       lcov -c -d . -o lcov.tmp
-
-lcov.out: lcov-pre.out
-       lcov -r lcov.tmp '*test*' > lcov.out
-
-lcov: lcov.out
-       genhtml lcov.out -o lcov
-
-.PHONY: lcov-run
diff --git a/libs/srtp/recv.c b/libs/srtp/recv.c
deleted file mode 100644 (file)
index 5abac52..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Secure RTP with libgcrypt
- * Copyright (C) 2007  Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-#include "srtp.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <unistd.h>
-#include <netinet/in.h>
-
-int main (void)
-{
-    int fd = socket (AF_INET, SOCK_DGRAM, 0);
-    struct sockaddr_in addr;
-    memset (&addr, 0, sizeof (addr));
-    addr.sin_family = AF_INET;
-#ifdef HAVE_SA_LEN
-    addr.sin_len = sizeof (addr);
-#endif
-    addr.sin_port = htons (10000);
-    addr.sin_addr.s_addr = htonl (0x7f000001);
-    if (bind (fd, (struct sockaddr *)&addr, sizeof (addr)))
-        return 1;
-
-    static const uint8_t key[16] =
-        "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
-        "\x12\x34\x56\x78\x9A\xBC\xDE\xF0";
-    static const uint8_t salt[14] =
-        "\x12\x34\x56\x78\x90" "\x12\x34\x56\x78\x90" "\x12\x34\x56\x78";
-
-    srtp_session_t *s = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10,
-                                     SRTP_PRF_AES_CM, 0);
-    if (s == NULL)
-        return 1;
-    if (srtp_setkey (s, key, 16, salt, 14))
-        goto error;
-
-    uint8_t buf[1500];
-    size_t len;
-#if 0
-    memset (buf, 0, sizeof (buf));
-    buf[0] = 2 << 6;
-    buf[1] = 1;
-    memcpy (buf + 2, &(uint16_t){ htons (9527) }, 2);
-    memcpy (buf + 8, "\xde\xad\xbe\xef", 4);
-    memcpy (buf + 4, &(uint32_t){ htonl (1) }, 4);
-    strcpy ((char *)buf + 12, "a\n");
-    len = 12 + strlen ((char *)buf + 12) + 1;
-#endif
-    for (;;)
-    {
-        len = read (fd, buf, sizeof (buf));
-        int val = srtp_recv (s, buf, &len);
-        if (val)
-        {
-            fprintf (stderr, "Cannot decrypt: %s\n", strerror (val));
-            continue;
-        }
-
-        puts ((char *)buf + 12);
-        //if (srtp_send (s, buf, &len, sizeof (buf)) || srtp_recv (s, buf, &len))
-        //    break;
-        puts ((char *)buf + 12);
-    }
-
-error:
-    srtp_destroy (s);
-    close (fd);
-    return 0;
-}
diff --git a/libs/srtp/srtp.c b/libs/srtp/srtp.c
deleted file mode 100644 (file)
index 82bb83d..0000000
+++ /dev/null
@@ -1,837 +0,0 @@
-/*
- * Secure RTP with libgcrypt
- * Copyright (C) 2007  Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-/* TODO:
- * Useless stuff (because nothing depends on it):
- * - non-nul key derivation rate
- * - MKI payload
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-
-#include "srtp.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <gcrypt.h>
-
-#ifdef WIN32
-# include <winsock2.h>
-#else
-# include <netinet/in.h>
-#endif
-
-#define debug( ... ) (void)0
-
-typedef struct srtp_proto_t
-{
-    gcry_cipher_hd_t cipher;
-    gcry_md_hd_t     mac;
-    uint64_t         window;
-    uint32_t         salt[4];
-} srtp_proto_t;
-
-struct srtp_session_t
-{
-    srtp_proto_t rtp;
-    srtp_proto_t rtcp;
-    unsigned flags;
-    unsigned kdr;
-    uint32_t rtcp_index;
-    uint32_t rtp_roc;
-    uint16_t rtp_seq;
-    uint16_t rtp_rcc;
-    uint8_t  tag_len;
-};
-
-enum
-{
-    SRTP_CRYPT,
-    SRTP_AUTH,
-    SRTP_SALT,
-    SRTCP_CRYPT,
-    SRTCP_AUTH,
-    SRTCP_SALT
-};
-
-
-static inline unsigned rcc_mode (const srtp_session_t *s)
-{
-    return (s->flags >> 4) & 3;
-}
-
-
-static void proto_destroy (srtp_proto_t *p)
-{
-    gcry_md_close (p->mac);
-    gcry_cipher_close (p->cipher);
-}
-
-
-/**
- * Releases all resources associated with a Secure RTP session.
- */
-void srtp_destroy (srtp_session_t *s)
-{
-    assert (s != NULL);
-
-    proto_destroy (&s->rtcp);
-    proto_destroy (&s->rtp);
-    free (s);
-}
-
-
-static int proto_create (srtp_proto_t *p, int gcipher, int gmd)
-{
-    if (gcry_cipher_open (&p->cipher, gcipher, GCRY_CIPHER_MODE_CTR, 0) == 0)
-    {
-        if (gcry_md_open (&p->mac, gmd, GCRY_MD_FLAG_HMAC) == 0)
-            return 0;
-        gcry_cipher_close (p->cipher);
-    }
-    return -1;
-}
-
-
-/**
- * Allocates a Secure RTP one-way session.
- * The same session cannot be used both ways because this would confuse
- * internal cryptographic counters; it is however of course feasible to open
- * multiple simultaneous sessions with the same master key.
- *
- * @param encr encryption algorithm number
- * @param auth authentication algortihm number
- * @param tag_len authentication tag byte length (NOT including RCC)
- * @param flags OR'ed optional flags.
- *
- * @return NULL in case of error
- */
-srtp_session_t *
-srtp_create (int encr, int auth, unsigned tag_len, int prf, unsigned flags)
-{
-    if ((flags & ~SRTP_FLAGS_MASK))
-        return NULL;
-
-    int cipher, md;
-    switch (encr)
-    {
-        case SRTP_ENCR_NULL:
-            cipher = GCRY_CIPHER_NONE;
-            break;
-
-        case SRTP_ENCR_AES_CM:
-            cipher = GCRY_CIPHER_AES;
-            break;
-
-        default:
-            return NULL;
-    }
-
-    switch (auth)
-    {
-        case SRTP_AUTH_NULL:
-            md = GCRY_MD_NONE;
-            break;
-
-        case SRTP_AUTH_HMAC_SHA1:
-            md = GCRY_MD_SHA1;
-            break;
-
-        default:
-            return NULL;
-    }
-
-    if (tag_len > gcry_md_get_algo_dlen (md))
-        return NULL;
-
-    if (prf != SRTP_PRF_AES_CM)
-        return NULL;
-
-    srtp_session_t *s = malloc (sizeof (*s));
-    if (s == NULL)
-        return NULL;
-
-    memset (s, 0, sizeof (*s));
-    s->flags = flags;
-    s->tag_len = tag_len;
-    s->rtp_rcc = 1; /* Default RCC rate */
-    if (rcc_mode (s))
-    {
-        if (tag_len < 4)
-            goto error;
-    }
-
-    if (proto_create (&s->rtp, cipher, md) == 0)
-    {
-        if (proto_create (&s->rtcp, cipher, md) == 0)
-            return s;
-        proto_destroy (&s->rtp);
-    }
-
-error:
-    free (s);
-    return NULL;
-}
-
-
-/**
- * Counter Mode encryption/decryption (ctr length = 16 bytes)
- * with non-padded (truncated) text
- */
-static int
-do_ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len)
-{
-    const size_t ctrlen = 16;
-    div_t d = div (len, ctrlen);
-
-    if (gcry_cipher_setctr (hd, ctr, ctrlen)
-     || gcry_cipher_encrypt (hd, data, d.quot * ctrlen, NULL, 0))
-        return -1;
-
-    if (d.rem)
-    {
-        /* Truncated last block */
-        uint8_t dummy[ctrlen];
-        data += d.quot * ctrlen;
-        memcpy (dummy, data, d.rem);
-        memset (dummy + d.rem, 0, ctrlen - d.rem);
-
-        if (gcry_cipher_encrypt (hd, dummy, ctrlen, data, ctrlen))
-            return -1;
-        memcpy (data, dummy, d.rem);
-    }
-
-    return 0;
-}
-
-
-/**
- * AES-CM key derivation (saltlen = 14 bytes)
- */
-static int
-do_derive (gcry_cipher_hd_t prf, const void *salt,
-           const uint8_t *r, size_t rlen, uint8_t label,
-           void *out, size_t outlen)
-{
-    uint8_t iv[16];
-
-    memcpy (iv, salt, 14);
-    iv[14] = iv[15] = 0;
-
-    assert (rlen < 14);
-    iv[13 - rlen] ^= label;
-    for (size_t i = 0; i < rlen; i++)
-        iv[sizeof (iv) - rlen + i] ^= r[i];
-
-    memset (out, 0, outlen);
-    return do_ctr_crypt (prf, iv, out, outlen);
-}
-
-
-/**
- * Sets (or resets) the master key and master salt for a SRTP session.
- * This must be done at least once before using srtp_send(), srtp_recv(),
- * srtcp_send() or srtcp_recv(). Also, rekeying is required every
- * 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
- * otherwise the protocol security might be broken.
- *
- * @return 0 on success, in case of error:
- *  EINVAL  invalid or unsupported key/salt sizes combination
- */
-int
-srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
-             const void *salt, size_t saltlen)
-{
-    /* SRTP/SRTCP cipher/salt/MAC keys derivation */
-    gcry_cipher_hd_t prf;
-    uint8_t r[6], keybuf[20];
-
-    if (saltlen != 14)
-        return EINVAL;
-
-    if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0)
-     || gcry_cipher_setkey (prf, key, keylen))
-        return EINVAL;
-
-    /* SRTP key derivation */
-#if 0
-    if (s->kdr != 0)
-    {
-        uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
-        index /= s->kdr;
-
-        for (int i = sizeof (r) - 1; i >= 0; i--)
-        {
-            r[i] = index & 0xff;
-            index = index >> 8;
-        }
-    }
-    else
-#endif
-        memset (r, 0, sizeof (r));
-    if (do_derive (prf, salt, r, 6, SRTP_CRYPT, keybuf, 16)
-     || gcry_cipher_setkey (s->rtp.cipher, keybuf, 16)
-     || do_derive (prf, salt, r, 6, SRTP_AUTH, keybuf, 20)
-     || gcry_md_setkey (s->rtp.mac, keybuf, 20)
-     || do_derive (prf, salt, r, 6, SRTP_SALT, s->rtp.salt, 14))
-        return -1;
-
-    /* SRTCP key derivation */
-    memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
-    if (do_derive (prf, salt, r, 4, SRTCP_CRYPT, keybuf, 16)
-     || gcry_cipher_setkey (s->rtcp.cipher, keybuf, 16)
-     || do_derive (prf, salt, r, 4, SRTCP_AUTH, keybuf, 20)
-     || gcry_md_setkey (s->rtcp.mac, keybuf, 20)
-     || do_derive (prf, salt, r, 4, SRTCP_SALT, s->rtcp.salt, 14))
-        return -1;
-
-    (void)gcry_cipher_close (prf);
-    return 0;
-}
-
-static int hexdigit (char c)
-{
-    if ((c >= '0') && (c <= '9'))
-        return c - '0';
-    if ((c >= 'A') && (c <= 'F'))
-        return c - 'A' + 0xA;
-    if ((c >= 'a') && (c <= 'f'))
-        return c - 'a' + 0xa;
-    return -1;
-}
-
-static ssize_t hexstring (const char *in, uint8_t *out, size_t outlen)
-{
-    size_t inlen = strlen (in);
-
-    if ((inlen > (2 * outlen)) || (inlen & 1))
-        return -1;
-
-    for (size_t i = 0; i < inlen; i += 2)
-    {
-        int a = hexdigit (in[i]), b = hexdigit (in[i + 1]);
-        if ((a == -1) || (b == -1))
-            return -1;
-        out[i / 2] = (a << 4) | b;
-    }
-    return inlen / 2;
-}
-
-/**
- * Sets (or resets) the master key and master salt for a SRTP session
- * from hexadecimal strings. See also srtp_setkey().
- *
- * @return 0 on success, in case of error:
- *  EINVAL  invalid or unsupported key/salt sizes combination
- */
-int
-srtp_setkeystring (srtp_session_t *s, const char *key, const char *salt)
-{
-    uint8_t bkey[16]; /* TODO/NOTE: hard-coded for AES */
-    uint8_t bsalt[14]; /* TODO/NOTE: hard-coded for the PRF-AES-CM */
-    ssize_t bkeylen = hexstring (key, bkey, sizeof (bkey));
-    ssize_t bsaltlen = hexstring (salt, bsalt, sizeof (bsalt));
-
-    if ((bkeylen == -1) || (bsaltlen == -1))
-        return EINVAL;
-    return srtp_setkey (s, bkey, bkeylen, bsalt, bsaltlen) ? EINVAL : 0;
-}
-
-/**
- * Sets Roll-over-Counter Carry (RCC) rate for the SRTP session. If not
- * specified (through this function), the default rate of ONE is assumed
- * (i.e. every RTP packets will carry the RoC). RCC rate is ignored if none
- * of the RCC mode has been selected.
- *
- * The RCC mode is selected through one of these flags for srtp_create():
- *  SRTP_RCC_MODE1: integrity protection only for RoC carrying packets
- *  SRTP_RCC_MODE2: integrity protection for all packets
- *  SRTP_RCC_MODE3: no integrity protection
- *
- * RCC mode 3 is insecure. Compared to plain RTP, it provides confidentiality
- * (through encryption) but is much more prone to DoS. It can only be used if
- * anti-spoofing protection is provided by lower network layers (e.g. IPsec,
- * or trusted routers and proper source address filtering).
- *
- * If RCC rate is 1, RCC mode 1 and 2 are functionally identical.
- *
- * @param rate RoC Carry rate (MUST NOT be zero)
- */
-void srtp_setrcc_rate (srtp_session_t *s, uint16_t rate)
-{
-    assert (rate != 0);
-    s->rtp_rcc = rate;
-}
-
-
-/** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
-static int
-rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
-           const uint32_t *salt, uint8_t *data, size_t len)
-{
-    /* Determines cryptographic counter (IV) */
-    uint32_t counter[4];
-    counter[0] = salt[0];
-    counter[1] = salt[1] ^ ssrc;
-    counter[2] = salt[2] ^ htonl (roc);
-    counter[3] = salt[3] ^ htonl (seq << 16);
-
-    /* Encryption */
-    return do_ctr_crypt (hd, counter, data, len);
-}
-
-
-/** Determines SRTP Roll-Over-Counter (in host-byte order) */
-static uint32_t
-srtp_compute_roc (const srtp_session_t *s, uint16_t seq)
-{
-    uint32_t roc = s->rtp_roc;
-
-    if (((seq - s->rtp_seq) & 0xffff) < 0x8000)
-    {
-        /* Sequence is ahead, good */
-        if (seq < s->rtp_seq)
-            roc++; /* Sequence number wrap */
-    }
-    else
-    {
-        /* Sequence is late, bad */
-        if (seq > s->rtp_seq)
-            roc--; /* Wrap back */
-    }
-    return roc;
-}
-
-
-/** Returns RTP sequence (in host-byte order) */
-static inline uint16_t rtp_seq (const uint8_t *buf)
-{
-    return (buf[2] << 8) | buf[3];
-}
-
-
-/** Message Authentication and Integrity for RTP */
-static const uint8_t *
-rtp_digest (gcry_md_hd_t md, const uint8_t *data, size_t len,
-            uint32_t roc)
-{
-    gcry_md_reset (md);
-    gcry_md_write (md, data, len);
-    gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4);
-    return gcry_md_read (md, 0);
-}
-
-
-/**
- * Encrypts/decrypts a RTP packet and updates SRTP context
- * (CTR block cypher mode of operation has identical encryption and
- * decryption function).
- *
- * @param buf RTP packet to be en-/decrypted
- * @param len RTP packet length
- *
- * @return 0 on success, in case of error:
- *  EINVAL  malformatted RTP packet
- *  EACCES  replayed packet or out-of-window or sync lost
- */
-static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
-{
-    assert (s != NULL);
-    assert (len >= 12u);
-
-    if ((buf[0] >> 6) != 2)
-        return EINVAL;
-
-    /* Computes encryption offset */
-    uint16_t offset = 12;
-    offset += (buf[0] & 0xf) * 4; // skips CSRC
-
-    if (buf[0] & 0x10)
-    {
-        uint16_t extlen;
-
-        offset += 4;
-        if (len < offset)
-            return EINVAL;
-
-        memcpy (&extlen, buf + offset - 2, 2);
-        offset += htons (extlen); // skips RTP extension header
-    }
-
-    if (len < offset)
-        return EINVAL;
-
-    /* Determines RTP 48-bits counter and SSRC */
-    uint16_t seq = rtp_seq (buf);
-    uint32_t roc = srtp_compute_roc (s, seq), ssrc;
-    memcpy (&ssrc, buf + 8, 4);
-
-    /* Updates ROC and sequence (it's safe now) */
-    int16_t diff = seq - s->rtp_seq;
-    if (diff > 0)
-    {
-        /* Sequence in the future, good */
-        s->rtp.window = s->rtp.window << diff;
-        s->rtp.window |= 1;
-        s->rtp_seq = seq, s->rtp_roc = roc;
-    }
-    else
-    {
-        /* Sequence in the past/present, bad */
-        diff = -diff;
-        if ((diff >= 64) || ((s->rtp.window >> diff) & 1))
-            return EACCES; /* Replay attack */
-        s->rtp.window |= 1 << diff;
-    }
-
-    /* Encrypt/Decrypt */
-    if (s->flags & SRTP_UNENCRYPTED)
-        return 0;
-
-    if (rtp_crypt (s->rtp.cipher, ssrc, roc, seq, s->rtp.salt,
-                   buf + offset, len - offset))
-        return EINVAL;
-
-    return 0;
-}
-
-
-/**
- * Turns a RTP packet into a SRTP packet: encrypt it, then computes
- * the authentication tag and appends it.
- * Note that you can encrypt packet in disorder.
- *
- * @param buf RTP packet to be encrypted/digested
- * @param lenp pointer to the RTP packet length on entry,
- *             set to the SRTP length on exit (undefined on non-ENOSPC error)
- * @param bufsize size (bytes) of the packet buffer
- *
- * @return 0 on success, in case of error:
- *  EINVAL  malformatted RTP packet or internal error
- *  ENOSPC  bufsize is too small to add authentication tag
- *          (<lenp> will hold the required byte size)
- *  EACCES  packet would trigger a replay error on receiver
- */
-int
-srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
-{
-    size_t len = *lenp;
-    size_t tag_len;
-    size_t roc_len = 0;
-
-    /* Compute required buffer size */
-    if (len < 12u)
-        return EINVAL;
-
-    if (!(s->flags & SRTP_UNAUTHENTICATED))
-    {
-        tag_len = s->tag_len;
-
-        if (rcc_mode (s))
-        {
-            assert (tag_len >= 4);
-            assert (s->rtp_rcc != 0);
-            if ((rtp_seq (buf) % s->rtp_rcc) == 0)
-            {
-                roc_len = 4;
-                if (rcc_mode (s) == 3)
-                    tag_len = 0; /* RCC mode 3 -> no auth*/
-                else
-                    tag_len -= 4; /* RCC mode 1 or 2 -> auth*/
-            }
-            else
-            {
-                if (rcc_mode (s) & 1)
-                    tag_len = 0; /* RCC mode 1 or 3 -> no auth */
-            }
-        }
-
-        *lenp = len + roc_len + tag_len;
-    }
-    else
-        tag_len = 0;
-
-    if (bufsize < *lenp)
-        return ENOSPC;
-
-    /* Encrypt payload */
-    int val = srtp_crypt (s, buf, len);
-    if (val)
-        return val;
-
-    /* Authenticate payload */
-    if (!(s->flags & SRTP_UNAUTHENTICATED))
-    {
-        uint32_t roc = srtp_compute_roc (s, rtp_seq (buf));
-        const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, roc);
-
-        if (roc_len)
-        {
-            memcpy (buf + len, &(uint32_t){ htonl (s->rtp_roc) }, 4);
-            len += 4;
-        }
-        memcpy (buf + len, tag, tag_len);
-#if 0
-        printf ("Sent    : 0x");
-        for (unsigned i = 0; i < tag_len; i++)
-            printf ("%02x", tag[i]);
-        puts ("");
-#endif
-    }
-
-    return 0;
-}
-
-
-/**
- * Turns a SRTP packet into a RTP packet: authenticates the packet,
- * then decrypts it.
- *
- * @param buf RTP packet to be digested/decrypted
- * @param lenp pointer to the SRTP packet length on entry,
- *             set to the RTP length on exit (undefined in case of error)
- *
- * @return 0 on success, in case of error:
- *  EINVAL  malformatted SRTP packet
- *  EACCES  authentication failed (spoofed packet or out-of-sync)
- */
-int
-srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
-{
-    size_t len = *lenp;
-    if (len < 12u)
-        return EINVAL;
-
-    if (!(s->flags & SRTP_UNAUTHENTICATED))
-    {
-        size_t tag_len = s->tag_len, roc_len = 0;
-        if (rcc_mode (s))
-        {
-            if ((rtp_seq (buf) % s->rtp_rcc) == 0)
-            {
-                roc_len = 4;
-                if (rcc_mode (s) == 3)
-                    tag_len = 0;
-                else
-                    tag_len -= 4;
-            }
-            else
-            {
-                if (rcc_mode (s) & 1)
-                    tag_len = 0; // RCC mode 1 or 3: no auth
-            }
-        }
-
-        if (len < (12u + roc_len + tag_len))
-            return EINVAL;
-        len -= roc_len + tag_len;
-
-        uint32_t roc = srtp_compute_roc (s, rtp_seq (buf)), rcc;
-        if (roc_len)
-        {
-            assert (roc_len == 4);
-            memcpy (&rcc, buf + len, 4);
-            rcc = ntohl (rcc);
-        }
-        else
-            rcc = roc;
-
-        const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, rcc);
-#if 0
-        printf ("Computed: 0x");
-        for (unsigned i = 0; i < tag_len; i++)
-            printf ("%02x", tag[i]);
-        printf ("\nReceived: 0x");
-        for (unsigned i = 0; i < tag_len; i++)
-            printf ("%02x", buf[len + roc_len + i]);
-        puts ("");
-#endif
-        if (memcmp (buf + len + roc_len, tag, tag_len))
-            return EACCES;
-
-        if (roc_len)
-        {
-            /* Authenticated packet carried a Roll-Over-Counter */
-            s->rtp_roc += rcc - roc;
-            assert (srtp_compute_roc (s, rtp_seq (buf)) == rcc);
-        }
-        *lenp = len;
-    }
-
-    return srtp_crypt (s, buf, len);
-}
-
-
-/** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
-static int
-rtcp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t index,
-            const uint32_t *salt, uint8_t *data, size_t len)
-{
-    return rtp_crypt (hd, ssrc, index >> 16, index & 0xffff, salt, data, len);
-}
-
-
-/** Message Authentication and Integrity for RTCP */
-static const uint8_t *
-rtcp_digest (gcry_md_hd_t md, const void *data, size_t len)
-{
-    gcry_md_reset (md);
-    gcry_md_write (md, data, len);
-    return gcry_md_read (md, 0);
-}
-
-
-/**
- * Encrypts/decrypts a RTCP packet and updates SRTCP context
- * (CTR block cypher mode of operation has identical encryption and
- * decryption function).
- *
- * @param buf RTCP packet to be en-/decrypted
- * @param len RTCP packet length
- *
- * @return 0 on success, in case of error:
- *  EINVAL  malformatted RTCP packet
- */
-static int srtcp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
-{
-    assert (s != NULL);
-
-    /* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
-    if ((len < 12) || ((buf[0] >> 6) != 2))
-        return EINVAL;
-
-    uint32_t index;
-    memcpy (&index, buf + len, 4);
-    index = ntohl (index);
-    if (((index >> 31) != 0) != ((s->flags & SRTCP_UNENCRYPTED) == 0))
-        return EINVAL; // E-bit mismatch
-
-    index &= ~(1 << 31); // clear E-bit for counter
-
-    /* Updates SRTCP index (safe here) */
-    int32_t diff = index - s->rtcp_index;
-    if (diff > 0)
-    {
-        /* Packet in the future, good */
-        s->rtcp.window = s->rtcp.window << diff;
-        s->rtcp.window |= 1;
-        s->rtcp_index = index;
-    }
-    else
-    {
-        /* Packet in the past/present, bad */
-        diff = -diff;
-        if ((diff >= 64) || ((s->rtcp.window >> diff) & 1))
-            return EACCES; // replay attack!
-        s->rtp.window |= 1 << diff;
-    }
-
-    /* Crypts SRTCP */
-    if (s->flags & SRTCP_UNENCRYPTED)
-        return 0;
-
-    uint32_t ssrc;
-    memcpy (&ssrc, buf + 4, 4);
-
-    if (rtcp_crypt (s->rtcp.cipher, ssrc, index, s->rtp.salt,
-                    buf + 8, len - 8))
-        return EINVAL;
-    return 0;
-}
-
-
-/**
- * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
- * the authentication tag and appends it.
- *
- * @param buf RTCP packet to be encrypted/digested
- * @param lenp pointer to the RTCP packet length on entry,
- *             set to the SRTCP length on exit (undefined in case of error)
- * @param bufsize size (bytes) of the packet buffer
- *
- * @return 0 on success, in case of error:
- *  EINVAL  malformatted RTCP packet or internal error
- *  ENOSPC  bufsize is too small (to add index and authentication tag)
- */
-int
-srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
-{
-    size_t len = *lenp;
-    if (bufsize < (len + 4 + s->tag_len))
-        return ENOSPC;
-
-    uint32_t index = ++s->rtcp_index;
-    if (index >> 31)
-        s->rtcp_index = index = 0; /* 31-bit wrap */
-
-    if ((s->flags & SRTCP_UNENCRYPTED) == 0)
-        index |= 0x80000000; /* Set Encrypted bit */
-    memcpy (buf + len, &(uint32_t){ htonl (index) }, 4);
-
-    int val = srtcp_crypt (s, buf, len);
-    if (val)
-        return val;
-
-    len += 4; /* Digests SRTCP index too */
-
-    const uint8_t *tag = rtcp_digest (s->rtcp.mac, buf, len);
-    memcpy (buf + len, tag, s->tag_len);
-    *lenp = len + s->tag_len;
-    return 0;
-}
-
-
-/**
- * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
- * then decrypts it.
- *
- * @param buf RTCP packet to be digested/decrypted
- * @param lenp pointer to the SRTCP packet length on entry,
- *             set to the RTCP length on exit (undefined in case of error)
- *
- * @return 0 on success, in case of error:
- *  EINVAL  malformatted SRTCP packet
- *  EACCES  authentication failed (spoofed packet or out-of-sync)
- */
-int
-srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
-{
-    size_t len = *lenp;
-
-    if (len < (4u + s->tag_len))
-        return EINVAL;
-    len -= s->tag_len;
-
-    const uint8_t *tag = rtcp_digest (s->rtcp.mac, buf, len);
-    if (memcmp (buf + len, tag, s->tag_len))
-         return EACCES;
-
-    len -= 4; /* Remove SRTCP index before decryption */
-    *lenp = len;
-    return srtp_crypt (s, buf, len);
-}
-
diff --git a/libs/srtp/srtp.h b/libs/srtp/srtp.h
deleted file mode 100644 (file)
index 67e8026..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Secure RTP with libgcrypt
- * Copyright (C) 2007  Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef LIBVLC_SRTP_H
-# define LIBVLC_SRTP_H 1
-
-typedef struct srtp_session_t srtp_session_t;
-
-enum
-{
-    SRTP_UNENCRYPTED=0x1,   //< do not encrypt SRTP packets
-    SRTCP_UNENCRYPTED=0x2,  //< do not encrypt SRTCP packets
-    SRTP_UNAUTHENTICATED=0x4, //< authenticate only SRTCP packets
-
-    SRTP_RCC_MODE1=0x10,    //< use Roll-over-Counter Carry mode 1
-    SRTP_RCC_MODE2=0x20,    //< use Roll-over-Counter Carry mode 2
-    SRTP_RCC_MODE3=0x30,    //< use Roll-over-Counter Carry mode 3 (insecure)
-
-    SRTP_FLAGS_MASK=0x37    //< mask for valid flags
-};
-
-/** SRTP encryption algorithms (ciphers); same values as MIKEY */
-enum
-{
-    SRTP_ENCR_NULL=0,   //< no encryption
-    SRTP_ENCR_AES_CM=1, //< AES counter mode
-    SRTP_ENCR_AES_F8=2, //< AES F8 mode (not implemented)
-};
-
-/** SRTP authenticaton algorithms; same values as MIKEY */
-enum
-{
-    SRTP_AUTH_NULL=0,      //< no authentication code
-    SRTP_AUTH_HMAC_SHA1=1, //< HMAC-SHA1
-};
-
-/** SRTP pseudo random function; same values as MIKEY */
-enum
-{
-    SRTP_PRF_AES_CM=0, //< AES counter mode
-};
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-srtp_session_t *srtp_create (int encr, int auth, unsigned tag_len, int prf,
-                             unsigned flags);
-void srtp_destroy (srtp_session_t *s);
-
-int srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
-                 const void *salt, size_t saltlen);
-int srtp_setkeystring (srtp_session_t *s, const char *key, const char *salt);
-
-void srtp_setrcc_rate (srtp_session_t *s, uint16_t rate);
-
-int srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t maxsize);
-int srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp);
-int srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t maxsiz);
-int srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp);
-
-# ifdef __cplusplus
-}
-# endif
-#endif
-
diff --git a/libs/srtp/test-aes.c b/libs/srtp/test-aes.c
deleted file mode 100644 (file)
index 6168434..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Secure RTP with libgcrypt
- * Copyright (C) 2007  Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <stdio.h>
-#include "srtp.c"
-
-static void printhex (const void *buf, size_t len)
-{
-    for (size_t i = 0; i < len; i++)
-        printf ("%02X", ((uint8_t *)buf)[i]);
-    fputc ('\n', stdout);
-}
-
-static void fatal (const char *msg)
-{
-    puts (msg);
-    exit (1);
-}
-
-/** AES-CM key derivation test vectors */
-static void test_derivation (void)
-{
-    static const uint8_t key[16] =
-        "\xE1\xF9\x7A\x0D\x3E\x01\x8B\xE0\xD6\x4F\xA3\x2C\x06\xDE\x41\x39";
-    static const uint8_t salt[14] =
-        "\x0E\xC6\x75\xAD\x49\x8A\xFE\xEB\xB6\x96\x0B\x3A\xAB\xE6";
-
-    static const uint8_t good_cipher[16] =
-        "\xC6\x1E\x7A\x93\x74\x4F\x39\xEE\x10\x73\x4A\xFE\x3F\xF7\xA0\x87";
-    static const uint8_t good_salt[14] =
-        "\x30\xCB\xBC\x08\x86\x3D\x8C\x85\xD4\x9D\xB3\x4A\x9A\xE1";
-    static const uint8_t good_auth[94] =
-        "\xCE\xBE\x32\x1F\x6F\xF7\x71\x6B\x6F\xD4\xAB\x49\xAF\x25\x6A\x15"
-        "\x6D\x38\xBA\xA4\x8F\x0A\x0A\xCF\x3C\x34\xE2\x35\x9E\x6C\xDB\xCE"
-        "\xE0\x49\x64\x6C\x43\xD9\x32\x7A\xD1\x75\x57\x8E\xF7\x22\x70\x98"
-        "\x63\x71\xC1\x0C\x9A\x36\x9A\xC2\xF9\x4A\x8C\x5F\xBC\xDD\xDC\x25"
-        "\x6D\x6E\x91\x9A\x48\xB6\x10\xEF\x17\xC2\x04\x1E\x47\x40\x35\x76"
-        "\x6B\x68\x64\x2C\x59\xBB\xFC\x2F\x34\xDB\x60\xDB\xDF\xB2";
-
-    static const uint8_t r[6] = { 0, 0, 0, 0, 0, 0 };
-    gcry_cipher_hd_t prf;
-    uint8_t out[94];
-
-    puts ("AES-CM key derivation test...");
-    printf (" master key:  ");
-    printhex (key, sizeof (key));
-    printf (" master salt: ");
-    printhex (salt, sizeof (salt));
-
-    if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0)
-     || gcry_cipher_setkey (prf, key, sizeof (key)))
-        fatal ("Internal PRF error");
-
-    if (do_derive (prf, salt, r, sizeof (r), SRTP_CRYPT, out, 16))
-        fatal ("Internal cipher derivation error");
-    printf (" cipher key:  ");
-    printhex (out, 16);
-    if (memcmp (out, good_cipher, 16))
-        fatal ("Test failed");
-
-    if (do_derive (prf, salt, r, sizeof (r), SRTP_SALT, out, 14))
-        fatal ("Internal salt derivation error");
-    printf (" cipher salt: ");
-    printhex (out, 14);
-    if (memcmp (out, good_salt, 14))
-        fatal ("Test failed");
-
-    if (do_derive (prf, salt, r, sizeof (r), SRTP_AUTH, out, 94))
-        fatal ("Internal auth key derivation error");
-    printf (" auth key:    ");
-    printhex (out, 94);
-    if (memcmp (out, good_auth, 94))
-        fatal ("Test failed");
-
-    gcry_cipher_close (prf);
-}
-
-/** AES-CM key derivation test vectors */
-static void test_keystream (void)
-{
-    static const uint8_t key[16] =
-        "\x2B\x7E\x15\x16\x28\xAE\xD2\xA6\xAB\xF7\x15\x88\x09\xCF\x4F\x3C";
-    const uint32_t salt[4]=
-        { htonl (0xf0f1f2f3), htonl (0xf4f5f6f7),
-          htonl (0xf8f9fafb), htonl (0xfcfd0000) };
-
-    puts ("AES-CM key stream test...");
-    uint8_t *buf = calloc (0xff02, 16);
-    if (buf == NULL)
-    {
-        fputs ("Not enough memory for test\n", stderr);
-        return;
-    }
-
-    printf (" session key: ");
-    printhex (key, sizeof (key));
-
-    gcry_cipher_hd_t hd;
-    if (gcry_cipher_open (&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0))
-        fatal ("Cipher initialization error");
-    if (gcry_cipher_setkey (hd, key, sizeof (key)))
-        fatal ("Cipher key error");
-
-    if (rtp_crypt (hd, 0, 0, 0, salt, buf, 0xff020))
-        fatal ("Encryption failure");
-    gcry_cipher_close (hd);
-
-    static const uint8_t good_start[48] =
-        "\xE0\x3E\xAD\x09\x35\xC9\x5E\x80\xE1\x66\xB1\x6D\xD9\x2B\x4E\xB4"
-        "\xD2\x35\x13\x16\x2B\x02\xD0\xF7\x2A\x43\xA2\xFE\x4A\x5F\x97\xAB"
-        "\x41\xE9\x5B\x3B\xB0\xA2\xE8\xDD\x47\x79\x01\xE4\xFC\xA8\x94\xC0";
-    static const uint8_t good_end[48] =
-        "\xEC\x8C\xDF\x73\x98\x60\x7C\xB0\xF2\xD2\x16\x75\xEA\x9E\xA1\xE4"
-        "\x36\x2B\x7C\x3C\x67\x73\x51\x63\x18\xA0\x77\xD7\xFC\x50\x73\xAE"
-        "\x6A\x2C\xC3\x78\x78\x89\x37\x4F\xBE\xB4\xC8\x1B\x17\xBA\x6C\x44";
-
-    printf (" key stream:  ");
-    printhex (buf, sizeof (good_start));
-    printf (" ... cont'd : ");
-    printhex (buf + 0xff020 - sizeof (good_end), sizeof (good_end));
-    if (memcmp (buf, good_start, sizeof (good_start))
-     || memcmp (buf + 0xff020 - sizeof (good_end), good_end,
-                sizeof (good_end)))
-        fatal ("Key stream test failed");
-    free (buf);
-}
-
-static void srtp_test (void)
-{
-    test_derivation ();
-    test_keystream ();
-}
-
-int main (void)
-{
-    srtp_test ();
-    return 0;
-}
diff --git a/libs/srtp/test-recv.c b/libs/srtp/test-recv.c
deleted file mode 100644 (file)
index 0b60fea..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Secure RTP with libgcrypt
- * Copyright (C) 2007  Rémi Denis-Courmont
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-#include "srtp.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#undef NDEBUG
-#include <assert.h>
-
-
-int main (void)
-{
-    static const char key[] =
-        "123456789ABCDEF0" "123456789ABCDEF0";
-    static const char salt[] =
-        "1234567890" "1234567890" "12345678";
-    int val;
-    srtp_session_t *sd, *se;
-
-    /* Too big tag length */
-    se = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 21,
-                      SRTP_PRF_AES_CM, 0);
-    assert (se == NULL);
-
-    /* Too short tag length */
-    se = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 3,
-                      SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
-    assert (se == NULL);
-
-    /* Initializes encryption and decryption contexts */
-    se = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 20,
-                      SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
-    assert (se != NULL);
-
-    sd = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 20,
-                      SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
-    assert (sd != NULL);
-
-    srtp_setrcc_rate (se, 1);
-    srtp_setrcc_rate (sd, 1);
-
-    val = srtp_setkeystring (se, key, salt);
-    assert (val == 0);
-    val = srtp_setkeystring (sd, key, salt);
-    assert (val == 0);
-
-    uint8_t buf[1500], buf2[1500];
-    size_t len;
-
-    /* Invalid SRTP packet */
-    len = 12;
-    memset (buf, 0, len);
-    val = srtp_send (se, buf, &len, sizeof (buf));
-    assert (val == EINVAL);
-
-    len = 32;
-    memset (buf, 0, len);
-    srtp_recv (sd, buf, &len);
-    assert (val == EINVAL);
-
-    /* Too short packet */
-    len = 11;
-    buf[0] = 0x80;
-    val = srtp_send (se, buf, &len, sizeof (buf));
-    assert (val == EINVAL);
-
-    len = 11;
-    val = srtp_recv (sd, buf, &len);
-    assert (val == EINVAL);
-
-    /* Too short when taking tag into account */
-    len = 31;
-    val = srtp_recv (sd, buf, &len);
-    assert (val == EINVAL);
-
-    /* Too short when taking RTP extensions into account */
-    len = 15;
-    buf[0] = 0x90;
-    val = srtp_send (se, buf, &len, sizeof (buf));
-    assert (val == EINVAL);
-
-    len = 16;
-    buf[0] = 0x90;
-    buf[15] = 1;
-    val = srtp_send (se, buf, &len, sizeof (buf));
-    assert (val == EINVAL);
-
-    /* Too small buffer (seq=1) */
-    len = 20;
-    memset (buf, 0, len);
-    buf[0] = 0x80;
-    buf[3] = 1;
-    val = srtp_send (se, buf, &len, 39);
-    assert (val == ENOSPC);
-    assert (len == 40);
-
-    len = 31;
-    val = srtp_recv (sd, buf, &len);
-    assert (val == EINVAL);
-
-    /* OK (seq=3) */
-    buf[0] = 0x80;
-    buf[3] = 3;
-    for (unsigned i = 0; i < 256; i++)
-        buf[i + 12] = i;
-    len = 0x10c;
-    val = srtp_send (se, buf, &len, 0x120);
-    assert (val == 0);
-    assert (len == 0x120);
-
-    memcpy (buf2, buf, len);
-    val = srtp_recv (sd, buf2, &len);
-    assert (val == 0);
-    assert (len == 0x10c);
-    assert (!memcmp (buf2, "\x80\x00\x00\x03" "\x00\x00\x00\x00"
-                           "\x00\x00\x00\x00", 12));
-    for (unsigned i = 0; i < 256; i++)
-        assert (buf2[i + 12] == i); // test actual decryption
-
-    /* Replay attack (seq=3) */
-    len = 0x120;
-    val = srtp_recv (sd, buf, &len);
-    assert (val == EACCES);
-    assert (len == 0x10c);
-
-    /* OK but late (seq=2) */
-    buf[0] = 0x80;
-    buf[3] = 2;
-    val = srtp_send (se, buf, &len, 0x120);
-    assert (val == 0);
-    assert (len == 0x120);
-
-    memcpy (buf2, buf, len);
-    val = srtp_recv (sd, buf2, &len);
-    assert (val == 0);
-    assert (len == 0x10c);
-
-    /* Late replay attack (seq=3) */
-    len = 0x120;
-    val = srtp_recv (sd, buf, &len);
-    assert (val == EACCES);
-    assert (len == 0x10c);
-
-    srtp_destroy (se);
-    srtp_destroy (sd);
-    return 0;
-}
diff --git a/modules/access/rtp/.gitignore b/modules/access/rtp/.gitignore
new file mode 100644 (file)
index 0000000..c41c5cb
--- /dev/null
@@ -0,0 +1,2 @@
+srtp-test-aes
+srtp-test-recv
index cbb4736..824cff2 100644 (file)
@@ -11,10 +11,40 @@ librtp_plugin_la_CFLAGS = $(AM_CFLAGS)
 librtp_plugin_la_LIBADD = $(AM_LIBADD) $(SOCKET_LIBS)
 librtp_plugin_la_DEPENDENCIES =
 
+# Secure RTP library
+libvlc_srtp_la_SOURCES = srtp.c
+libvlc_srtp_la_CPPFLAGS =
+libvlc_srtp_la_CFLAGS = $(GCRYPT_CFLAGS)
+libvlc_srtp_la_LDFLAGS =
+libvlc_srtp_la_LIBADD = $(GCRYPT_LIBS)
+srtp_test_recv_CPPFLAGS =
+srtp_test_recv_LDADD = libvlc_srtp.la
+srtp_test_aes_CPPFLAGS =
+srtp_test_aes_LDADD = $(GCRYPT_LIBS)
+
 if HAVE_GCRYPT
-librtp_plugin_la_CFLAGS += -DHAVE_SRTP -I$(top_srcdir)/libs/srtp \
-       $(GCRYPT_CFLAGS)
-librtp_plugin_la_LIBADD += $(top_builddir)/libs/srtp/libvlc_srtp.la \
-       $(GCRYPT_LIBS)
-librtp_plugin_la_DEPENDENCIES += $(top_builddir)/libs/srtp/libvlc_srtp.la
+noinst_HEADERS = srtp.h
+noinst_LTLIBRARIES = libvlc_srtp.la
+
+check_PROGRAMS = srtp-test-aes srtp-test-recv
+TESTS = $(check_PROGRAMS)
+
+librtp_plugin_la_CFLAGS += -DHAVE_SRTP $(GCRYPT_CFLAGS)
+librtp_plugin_la_LIBADD += libvlc_srtp.la $(GCRYPT_LIBS)
+librtp_plugin_la_DEPENDENCIES += libvlc_srtp.la
 endif
+
+lcov-run:
+       rm -Rf *.gcda lcov
+       $(MAKE) $(AM_MAKEFLAGS) check
+
+lcov-pre.out:
+       lcov -c -d . -o lcov.tmp
+
+lcov.out: lcov-pre.out
+       lcov -r lcov.tmp '*test*' > lcov.out
+
+lcov: lcov.out
+       genhtml lcov.out -o lcov
+
+.PHONY: lcov-run
diff --git a/modules/access/rtp/srtp-test-aes.c b/modules/access/rtp/srtp-test-aes.c
new file mode 100644 (file)
index 0000000..6168434
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Secure RTP with libgcrypt
+ * Copyright (C) 2007  Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include "srtp.c"
+
+static void printhex (const void *buf, size_t len)
+{
+    for (size_t i = 0; i < len; i++)
+        printf ("%02X", ((uint8_t *)buf)[i]);
+    fputc ('\n', stdout);
+}
+
+static void fatal (const char *msg)
+{
+    puts (msg);
+    exit (1);
+}
+
+/** AES-CM key derivation test vectors */
+static void test_derivation (void)
+{
+    static const uint8_t key[16] =
+        "\xE1\xF9\x7A\x0D\x3E\x01\x8B\xE0\xD6\x4F\xA3\x2C\x06\xDE\x41\x39";
+    static const uint8_t salt[14] =
+        "\x0E\xC6\x75\xAD\x49\x8A\xFE\xEB\xB6\x96\x0B\x3A\xAB\xE6";
+
+    static const uint8_t good_cipher[16] =
+        "\xC6\x1E\x7A\x93\x74\x4F\x39\xEE\x10\x73\x4A\xFE\x3F\xF7\xA0\x87";
+    static const uint8_t good_salt[14] =
+        "\x30\xCB\xBC\x08\x86\x3D\x8C\x85\xD4\x9D\xB3\x4A\x9A\xE1";
+    static const uint8_t good_auth[94] =
+        "\xCE\xBE\x32\x1F\x6F\xF7\x71\x6B\x6F\xD4\xAB\x49\xAF\x25\x6A\x15"
+        "\x6D\x38\xBA\xA4\x8F\x0A\x0A\xCF\x3C\x34\xE2\x35\x9E\x6C\xDB\xCE"
+        "\xE0\x49\x64\x6C\x43\xD9\x32\x7A\xD1\x75\x57\x8E\xF7\x22\x70\x98"
+        "\x63\x71\xC1\x0C\x9A\x36\x9A\xC2\xF9\x4A\x8C\x5F\xBC\xDD\xDC\x25"
+        "\x6D\x6E\x91\x9A\x48\xB6\x10\xEF\x17\xC2\x04\x1E\x47\x40\x35\x76"
+        "\x6B\x68\x64\x2C\x59\xBB\xFC\x2F\x34\xDB\x60\xDB\xDF\xB2";
+
+    static const uint8_t r[6] = { 0, 0, 0, 0, 0, 0 };
+    gcry_cipher_hd_t prf;
+    uint8_t out[94];
+
+    puts ("AES-CM key derivation test...");
+    printf (" master key:  ");
+    printhex (key, sizeof (key));
+    printf (" master salt: ");
+    printhex (salt, sizeof (salt));
+
+    if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0)
+     || gcry_cipher_setkey (prf, key, sizeof (key)))
+        fatal ("Internal PRF error");
+
+    if (do_derive (prf, salt, r, sizeof (r), SRTP_CRYPT, out, 16))
+        fatal ("Internal cipher derivation error");
+    printf (" cipher key:  ");
+    printhex (out, 16);
+    if (memcmp (out, good_cipher, 16))
+        fatal ("Test failed");
+
+    if (do_derive (prf, salt, r, sizeof (r), SRTP_SALT, out, 14))
+        fatal ("Internal salt derivation error");
+    printf (" cipher salt: ");
+    printhex (out, 14);
+    if (memcmp (out, good_salt, 14))
+        fatal ("Test failed");
+
+    if (do_derive (prf, salt, r, sizeof (r), SRTP_AUTH, out, 94))
+        fatal ("Internal auth key derivation error");
+    printf (" auth key:    ");
+    printhex (out, 94);
+    if (memcmp (out, good_auth, 94))
+        fatal ("Test failed");
+
+    gcry_cipher_close (prf);
+}
+
+/** AES-CM key derivation test vectors */
+static void test_keystream (void)
+{
+    static const uint8_t key[16] =
+        "\x2B\x7E\x15\x16\x28\xAE\xD2\xA6\xAB\xF7\x15\x88\x09\xCF\x4F\x3C";
+    const uint32_t salt[4]=
+        { htonl (0xf0f1f2f3), htonl (0xf4f5f6f7),
+          htonl (0xf8f9fafb), htonl (0xfcfd0000) };
+
+    puts ("AES-CM key stream test...");
+    uint8_t *buf = calloc (0xff02, 16);
+    if (buf == NULL)
+    {
+        fputs ("Not enough memory for test\n", stderr);
+        return;
+    }
+
+    printf (" session key: ");
+    printhex (key, sizeof (key));
+
+    gcry_cipher_hd_t hd;
+    if (gcry_cipher_open (&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0))
+        fatal ("Cipher initialization error");
+    if (gcry_cipher_setkey (hd, key, sizeof (key)))
+        fatal ("Cipher key error");
+
+    if (rtp_crypt (hd, 0, 0, 0, salt, buf, 0xff020))
+        fatal ("Encryption failure");
+    gcry_cipher_close (hd);
+
+    static const uint8_t good_start[48] =
+        "\xE0\x3E\xAD\x09\x35\xC9\x5E\x80\xE1\x66\xB1\x6D\xD9\x2B\x4E\xB4"
+        "\xD2\x35\x13\x16\x2B\x02\xD0\xF7\x2A\x43\xA2\xFE\x4A\x5F\x97\xAB"
+        "\x41\xE9\x5B\x3B\xB0\xA2\xE8\xDD\x47\x79\x01\xE4\xFC\xA8\x94\xC0";
+    static const uint8_t good_end[48] =
+        "\xEC\x8C\xDF\x73\x98\x60\x7C\xB0\xF2\xD2\x16\x75\xEA\x9E\xA1\xE4"
+        "\x36\x2B\x7C\x3C\x67\x73\x51\x63\x18\xA0\x77\xD7\xFC\x50\x73\xAE"
+        "\x6A\x2C\xC3\x78\x78\x89\x37\x4F\xBE\xB4\xC8\x1B\x17\xBA\x6C\x44";
+
+    printf (" key stream:  ");
+    printhex (buf, sizeof (good_start));
+    printf (" ... cont'd : ");
+    printhex (buf + 0xff020 - sizeof (good_end), sizeof (good_end));
+    if (memcmp (buf, good_start, sizeof (good_start))
+     || memcmp (buf + 0xff020 - sizeof (good_end), good_end,
+                sizeof (good_end)))
+        fatal ("Key stream test failed");
+    free (buf);
+}
+
+static void srtp_test (void)
+{
+    test_derivation ();
+    test_keystream ();
+}
+
+int main (void)
+{
+    srtp_test ();
+    return 0;
+}
diff --git a/modules/access/rtp/srtp-test-recv.c b/modules/access/rtp/srtp-test-recv.c
new file mode 100644 (file)
index 0000000..0b60fea
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Secure RTP with libgcrypt
+ * Copyright (C) 2007  Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "srtp.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#undef NDEBUG
+#include <assert.h>
+
+
+int main (void)
+{
+    static const char key[] =
+        "123456789ABCDEF0" "123456789ABCDEF0";
+    static const char salt[] =
+        "1234567890" "1234567890" "12345678";
+    int val;
+    srtp_session_t *sd, *se;
+
+    /* Too big tag length */
+    se = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 21,
+                      SRTP_PRF_AES_CM, 0);
+    assert (se == NULL);
+
+    /* Too short tag length */
+    se = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 3,
+                      SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
+    assert (se == NULL);
+
+    /* Initializes encryption and decryption contexts */
+    se = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 20,
+                      SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
+    assert (se != NULL);
+
+    sd = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 20,
+                      SRTP_PRF_AES_CM, SRTP_RCC_MODE1);
+    assert (sd != NULL);
+
+    srtp_setrcc_rate (se, 1);
+    srtp_setrcc_rate (sd, 1);
+
+    val = srtp_setkeystring (se, key, salt);
+    assert (val == 0);
+    val = srtp_setkeystring (sd, key, salt);
+    assert (val == 0);
+
+    uint8_t buf[1500], buf2[1500];
+    size_t len;
+
+    /* Invalid SRTP packet */
+    len = 12;
+    memset (buf, 0, len);
+    val = srtp_send (se, buf, &len, sizeof (buf));
+    assert (val == EINVAL);
+
+    len = 32;
+    memset (buf, 0, len);
+    srtp_recv (sd, buf, &len);
+    assert (val == EINVAL);
+
+    /* Too short packet */
+    len = 11;
+    buf[0] = 0x80;
+    val = srtp_send (se, buf, &len, sizeof (buf));
+    assert (val == EINVAL);
+
+    len = 11;
+    val = srtp_recv (sd, buf, &len);
+    assert (val == EINVAL);
+
+    /* Too short when taking tag into account */
+    len = 31;
+    val = srtp_recv (sd, buf, &len);
+    assert (val == EINVAL);
+
+    /* Too short when taking RTP extensions into account */
+    len = 15;
+    buf[0] = 0x90;
+    val = srtp_send (se, buf, &len, sizeof (buf));
+    assert (val == EINVAL);
+
+    len = 16;
+    buf[0] = 0x90;
+    buf[15] = 1;
+    val = srtp_send (se, buf, &len, sizeof (buf));
+    assert (val == EINVAL);
+
+    /* Too small buffer (seq=1) */
+    len = 20;
+    memset (buf, 0, len);
+    buf[0] = 0x80;
+    buf[3] = 1;
+    val = srtp_send (se, buf, &len, 39);
+    assert (val == ENOSPC);
+    assert (len == 40);
+
+    len = 31;
+    val = srtp_recv (sd, buf, &len);
+    assert (val == EINVAL);
+
+    /* OK (seq=3) */
+    buf[0] = 0x80;
+    buf[3] = 3;
+    for (unsigned i = 0; i < 256; i++)
+        buf[i + 12] = i;
+    len = 0x10c;
+    val = srtp_send (se, buf, &len, 0x120);
+    assert (val == 0);
+    assert (len == 0x120);
+
+    memcpy (buf2, buf, len);
+    val = srtp_recv (sd, buf2, &len);
+    assert (val == 0);
+    assert (len == 0x10c);
+    assert (!memcmp (buf2, "\x80\x00\x00\x03" "\x00\x00\x00\x00"
+                           "\x00\x00\x00\x00", 12));
+    for (unsigned i = 0; i < 256; i++)
+        assert (buf2[i + 12] == i); // test actual decryption
+
+    /* Replay attack (seq=3) */
+    len = 0x120;
+    val = srtp_recv (sd, buf, &len);
+    assert (val == EACCES);
+    assert (len == 0x10c);
+
+    /* OK but late (seq=2) */
+    buf[0] = 0x80;
+    buf[3] = 2;
+    val = srtp_send (se, buf, &len, 0x120);
+    assert (val == 0);
+    assert (len == 0x120);
+
+    memcpy (buf2, buf, len);
+    val = srtp_recv (sd, buf2, &len);
+    assert (val == 0);
+    assert (len == 0x10c);
+
+    /* Late replay attack (seq=3) */
+    len = 0x120;
+    val = srtp_recv (sd, buf, &len);
+    assert (val == EACCES);
+    assert (len == 0x10c);
+
+    srtp_destroy (se);
+    srtp_destroy (sd);
+    return 0;
+}
diff --git a/modules/access/rtp/srtp.c b/modules/access/rtp/srtp.c
new file mode 100644 (file)
index 0000000..82bb83d
--- /dev/null
@@ -0,0 +1,837 @@
+/*
+ * Secure RTP with libgcrypt
+ * Copyright (C) 2007  Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* TODO:
+ * Useless stuff (because nothing depends on it):
+ * - non-nul key derivation rate
+ * - MKI payload
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "srtp.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <gcrypt.h>
+
+#ifdef WIN32
+# include <winsock2.h>
+#else
+# include <netinet/in.h>
+#endif
+
+#define debug( ... ) (void)0
+
+typedef struct srtp_proto_t
+{
+    gcry_cipher_hd_t cipher;
+    gcry_md_hd_t     mac;
+    uint64_t         window;
+    uint32_t         salt[4];
+} srtp_proto_t;
+
+struct srtp_session_t
+{
+    srtp_proto_t rtp;
+    srtp_proto_t rtcp;
+    unsigned flags;
+    unsigned kdr;
+    uint32_t rtcp_index;
+    uint32_t rtp_roc;
+    uint16_t rtp_seq;
+    uint16_t rtp_rcc;
+    uint8_t  tag_len;
+};
+
+enum
+{
+    SRTP_CRYPT,
+    SRTP_AUTH,
+    SRTP_SALT,
+    SRTCP_CRYPT,
+    SRTCP_AUTH,
+    SRTCP_SALT
+};
+
+
+static inline unsigned rcc_mode (const srtp_session_t *s)
+{
+    return (s->flags >> 4) & 3;
+}
+
+
+static void proto_destroy (srtp_proto_t *p)
+{
+    gcry_md_close (p->mac);
+    gcry_cipher_close (p->cipher);
+}
+
+
+/**
+ * Releases all resources associated with a Secure RTP session.
+ */
+void srtp_destroy (srtp_session_t *s)
+{
+    assert (s != NULL);
+
+    proto_destroy (&s->rtcp);
+    proto_destroy (&s->rtp);
+    free (s);
+}
+
+
+static int proto_create (srtp_proto_t *p, int gcipher, int gmd)
+{
+    if (gcry_cipher_open (&p->cipher, gcipher, GCRY_CIPHER_MODE_CTR, 0) == 0)
+    {
+        if (gcry_md_open (&p->mac, gmd, GCRY_MD_FLAG_HMAC) == 0)
+            return 0;
+        gcry_cipher_close (p->cipher);
+    }
+    return -1;
+}
+
+
+/**
+ * Allocates a Secure RTP one-way session.
+ * The same session cannot be used both ways because this would confuse
+ * internal cryptographic counters; it is however of course feasible to open
+ * multiple simultaneous sessions with the same master key.
+ *
+ * @param encr encryption algorithm number
+ * @param auth authentication algortihm number
+ * @param tag_len authentication tag byte length (NOT including RCC)
+ * @param flags OR'ed optional flags.
+ *
+ * @return NULL in case of error
+ */
+srtp_session_t *
+srtp_create (int encr, int auth, unsigned tag_len, int prf, unsigned flags)
+{
+    if ((flags & ~SRTP_FLAGS_MASK))
+        return NULL;
+
+    int cipher, md;
+    switch (encr)
+    {
+        case SRTP_ENCR_NULL:
+            cipher = GCRY_CIPHER_NONE;
+            break;
+
+        case SRTP_ENCR_AES_CM:
+            cipher = GCRY_CIPHER_AES;
+            break;
+
+        default:
+            return NULL;
+    }
+
+    switch (auth)
+    {
+        case SRTP_AUTH_NULL:
+            md = GCRY_MD_NONE;
+            break;
+
+        case SRTP_AUTH_HMAC_SHA1:
+            md = GCRY_MD_SHA1;
+            break;
+
+        default:
+            return NULL;
+    }
+
+    if (tag_len > gcry_md_get_algo_dlen (md))
+        return NULL;
+
+    if (prf != SRTP_PRF_AES_CM)
+        return NULL;
+
+    srtp_session_t *s = malloc (sizeof (*s));
+    if (s == NULL)
+        return NULL;
+
+    memset (s, 0, sizeof (*s));
+    s->flags = flags;
+    s->tag_len = tag_len;
+    s->rtp_rcc = 1; /* Default RCC rate */
+    if (rcc_mode (s))
+    {
+        if (tag_len < 4)
+            goto error;
+    }
+
+    if (proto_create (&s->rtp, cipher, md) == 0)
+    {
+        if (proto_create (&s->rtcp, cipher, md) == 0)
+            return s;
+        proto_destroy (&s->rtp);
+    }
+
+error:
+    free (s);
+    return NULL;
+}
+
+
+/**
+ * Counter Mode encryption/decryption (ctr length = 16 bytes)
+ * with non-padded (truncated) text
+ */
+static int
+do_ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len)
+{
+    const size_t ctrlen = 16;
+    div_t d = div (len, ctrlen);
+
+    if (gcry_cipher_setctr (hd, ctr, ctrlen)
+     || gcry_cipher_encrypt (hd, data, d.quot * ctrlen, NULL, 0))
+        return -1;
+
+    if (d.rem)
+    {
+        /* Truncated last block */
+        uint8_t dummy[ctrlen];
+        data += d.quot * ctrlen;
+        memcpy (dummy, data, d.rem);
+        memset (dummy + d.rem, 0, ctrlen - d.rem);
+
+        if (gcry_cipher_encrypt (hd, dummy, ctrlen, data, ctrlen))
+            return -1;
+        memcpy (data, dummy, d.rem);
+    }
+
+    return 0;
+}
+
+
+/**
+ * AES-CM key derivation (saltlen = 14 bytes)
+ */
+static int
+do_derive (gcry_cipher_hd_t prf, const void *salt,
+           const uint8_t *r, size_t rlen, uint8_t label,
+           void *out, size_t outlen)
+{
+    uint8_t iv[16];
+
+    memcpy (iv, salt, 14);
+    iv[14] = iv[15] = 0;
+
+    assert (rlen < 14);
+    iv[13 - rlen] ^= label;
+    for (size_t i = 0; i < rlen; i++)
+        iv[sizeof (iv) - rlen + i] ^= r[i];
+
+    memset (out, 0, outlen);
+    return do_ctr_crypt (prf, iv, out, outlen);
+}
+
+
+/**
+ * Sets (or resets) the master key and master salt for a SRTP session.
+ * This must be done at least once before using srtp_send(), srtp_recv(),
+ * srtcp_send() or srtcp_recv(). Also, rekeying is required every
+ * 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
+ * otherwise the protocol security might be broken.
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  invalid or unsupported key/salt sizes combination
+ */
+int
+srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
+             const void *salt, size_t saltlen)
+{
+    /* SRTP/SRTCP cipher/salt/MAC keys derivation */
+    gcry_cipher_hd_t prf;
+    uint8_t r[6], keybuf[20];
+
+    if (saltlen != 14)
+        return EINVAL;
+
+    if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0)
+     || gcry_cipher_setkey (prf, key, keylen))
+        return EINVAL;
+
+    /* SRTP key derivation */
+#if 0
+    if (s->kdr != 0)
+    {
+        uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
+        index /= s->kdr;
+
+        for (int i = sizeof (r) - 1; i >= 0; i--)
+        {
+            r[i] = index & 0xff;
+            index = index >> 8;
+        }
+    }
+    else
+#endif
+        memset (r, 0, sizeof (r));
+    if (do_derive (prf, salt, r, 6, SRTP_CRYPT, keybuf, 16)
+     || gcry_cipher_setkey (s->rtp.cipher, keybuf, 16)
+     || do_derive (prf, salt, r, 6, SRTP_AUTH, keybuf, 20)
+     || gcry_md_setkey (s->rtp.mac, keybuf, 20)
+     || do_derive (prf, salt, r, 6, SRTP_SALT, s->rtp.salt, 14))
+        return -1;
+
+    /* SRTCP key derivation */
+    memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
+    if (do_derive (prf, salt, r, 4, SRTCP_CRYPT, keybuf, 16)
+     || gcry_cipher_setkey (s->rtcp.cipher, keybuf, 16)
+     || do_derive (prf, salt, r, 4, SRTCP_AUTH, keybuf, 20)
+     || gcry_md_setkey (s->rtcp.mac, keybuf, 20)
+     || do_derive (prf, salt, r, 4, SRTCP_SALT, s->rtcp.salt, 14))
+        return -1;
+
+    (void)gcry_cipher_close (prf);
+    return 0;
+}
+
+static int hexdigit (char c)
+{
+    if ((c >= '0') && (c <= '9'))
+        return c - '0';
+    if ((c >= 'A') && (c <= 'F'))
+        return c - 'A' + 0xA;
+    if ((c >= 'a') && (c <= 'f'))
+        return c - 'a' + 0xa;
+    return -1;
+}
+
+static ssize_t hexstring (const char *in, uint8_t *out, size_t outlen)
+{
+    size_t inlen = strlen (in);
+
+    if ((inlen > (2 * outlen)) || (inlen & 1))
+        return -1;
+
+    for (size_t i = 0; i < inlen; i += 2)
+    {
+        int a = hexdigit (in[i]), b = hexdigit (in[i + 1]);
+        if ((a == -1) || (b == -1))
+            return -1;
+        out[i / 2] = (a << 4) | b;
+    }
+    return inlen / 2;
+}
+
+/**
+ * Sets (or resets) the master key and master salt for a SRTP session
+ * from hexadecimal strings. See also srtp_setkey().
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  invalid or unsupported key/salt sizes combination
+ */
+int
+srtp_setkeystring (srtp_session_t *s, const char *key, const char *salt)
+{
+    uint8_t bkey[16]; /* TODO/NOTE: hard-coded for AES */
+    uint8_t bsalt[14]; /* TODO/NOTE: hard-coded for the PRF-AES-CM */
+    ssize_t bkeylen = hexstring (key, bkey, sizeof (bkey));
+    ssize_t bsaltlen = hexstring (salt, bsalt, sizeof (bsalt));
+
+    if ((bkeylen == -1) || (bsaltlen == -1))
+        return EINVAL;
+    return srtp_setkey (s, bkey, bkeylen, bsalt, bsaltlen) ? EINVAL : 0;
+}
+
+/**
+ * Sets Roll-over-Counter Carry (RCC) rate for the SRTP session. If not
+ * specified (through this function), the default rate of ONE is assumed
+ * (i.e. every RTP packets will carry the RoC). RCC rate is ignored if none
+ * of the RCC mode has been selected.
+ *
+ * The RCC mode is selected through one of these flags for srtp_create():
+ *  SRTP_RCC_MODE1: integrity protection only for RoC carrying packets
+ *  SRTP_RCC_MODE2: integrity protection for all packets
+ *  SRTP_RCC_MODE3: no integrity protection
+ *
+ * RCC mode 3 is insecure. Compared to plain RTP, it provides confidentiality
+ * (through encryption) but is much more prone to DoS. It can only be used if
+ * anti-spoofing protection is provided by lower network layers (e.g. IPsec,
+ * or trusted routers and proper source address filtering).
+ *
+ * If RCC rate is 1, RCC mode 1 and 2 are functionally identical.
+ *
+ * @param rate RoC Carry rate (MUST NOT be zero)
+ */
+void srtp_setrcc_rate (srtp_session_t *s, uint16_t rate)
+{
+    assert (rate != 0);
+    s->rtp_rcc = rate;
+}
+
+
+/** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
+static int
+rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
+           const uint32_t *salt, uint8_t *data, size_t len)
+{
+    /* Determines cryptographic counter (IV) */
+    uint32_t counter[4];
+    counter[0] = salt[0];
+    counter[1] = salt[1] ^ ssrc;
+    counter[2] = salt[2] ^ htonl (roc);
+    counter[3] = salt[3] ^ htonl (seq << 16);
+
+    /* Encryption */
+    return do_ctr_crypt (hd, counter, data, len);
+}
+
+
+/** Determines SRTP Roll-Over-Counter (in host-byte order) */
+static uint32_t
+srtp_compute_roc (const srtp_session_t *s, uint16_t seq)
+{
+    uint32_t roc = s->rtp_roc;
+
+    if (((seq - s->rtp_seq) & 0xffff) < 0x8000)
+    {
+        /* Sequence is ahead, good */
+        if (seq < s->rtp_seq)
+            roc++; /* Sequence number wrap */
+    }
+    else
+    {
+        /* Sequence is late, bad */
+        if (seq > s->rtp_seq)
+            roc--; /* Wrap back */
+    }
+    return roc;
+}
+
+
+/** Returns RTP sequence (in host-byte order) */
+static inline uint16_t rtp_seq (const uint8_t *buf)
+{
+    return (buf[2] << 8) | buf[3];
+}
+
+
+/** Message Authentication and Integrity for RTP */
+static const uint8_t *
+rtp_digest (gcry_md_hd_t md, const uint8_t *data, size_t len,
+            uint32_t roc)
+{
+    gcry_md_reset (md);
+    gcry_md_write (md, data, len);
+    gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4);
+    return gcry_md_read (md, 0);
+}
+
+
+/**
+ * Encrypts/decrypts a RTP packet and updates SRTP context
+ * (CTR block cypher mode of operation has identical encryption and
+ * decryption function).
+ *
+ * @param buf RTP packet to be en-/decrypted
+ * @param len RTP packet length
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  malformatted RTP packet
+ *  EACCES  replayed packet or out-of-window or sync lost
+ */
+static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
+{
+    assert (s != NULL);
+    assert (len >= 12u);
+
+    if ((buf[0] >> 6) != 2)
+        return EINVAL;
+
+    /* Computes encryption offset */
+    uint16_t offset = 12;
+    offset += (buf[0] & 0xf) * 4; // skips CSRC
+
+    if (buf[0] & 0x10)
+    {
+        uint16_t extlen;
+
+        offset += 4;
+        if (len < offset)
+            return EINVAL;
+
+        memcpy (&extlen, buf + offset - 2, 2);
+        offset += htons (extlen); // skips RTP extension header
+    }
+
+    if (len < offset)
+        return EINVAL;
+
+    /* Determines RTP 48-bits counter and SSRC */
+    uint16_t seq = rtp_seq (buf);
+    uint32_t roc = srtp_compute_roc (s, seq), ssrc;
+    memcpy (&ssrc, buf + 8, 4);
+
+    /* Updates ROC and sequence (it's safe now) */
+    int16_t diff = seq - s->rtp_seq;
+    if (diff > 0)
+    {
+        /* Sequence in the future, good */
+        s->rtp.window = s->rtp.window << diff;
+        s->rtp.window |= 1;
+        s->rtp_seq = seq, s->rtp_roc = roc;
+    }
+    else
+    {
+        /* Sequence in the past/present, bad */
+        diff = -diff;
+        if ((diff >= 64) || ((s->rtp.window >> diff) & 1))
+            return EACCES; /* Replay attack */
+        s->rtp.window |= 1 << diff;
+    }
+
+    /* Encrypt/Decrypt */
+    if (s->flags & SRTP_UNENCRYPTED)
+        return 0;
+
+    if (rtp_crypt (s->rtp.cipher, ssrc, roc, seq, s->rtp.salt,
+                   buf + offset, len - offset))
+        return EINVAL;
+
+    return 0;
+}
+
+
+/**
+ * Turns a RTP packet into a SRTP packet: encrypt it, then computes
+ * the authentication tag and appends it.
+ * Note that you can encrypt packet in disorder.
+ *
+ * @param buf RTP packet to be encrypted/digested
+ * @param lenp pointer to the RTP packet length on entry,
+ *             set to the SRTP length on exit (undefined on non-ENOSPC error)
+ * @param bufsize size (bytes) of the packet buffer
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  malformatted RTP packet or internal error
+ *  ENOSPC  bufsize is too small to add authentication tag
+ *          (<lenp> will hold the required byte size)
+ *  EACCES  packet would trigger a replay error on receiver
+ */
+int
+srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
+{
+    size_t len = *lenp;
+    size_t tag_len;
+    size_t roc_len = 0;
+
+    /* Compute required buffer size */
+    if (len < 12u)
+        return EINVAL;
+
+    if (!(s->flags & SRTP_UNAUTHENTICATED))
+    {
+        tag_len = s->tag_len;
+
+        if (rcc_mode (s))
+        {
+            assert (tag_len >= 4);
+            assert (s->rtp_rcc != 0);
+            if ((rtp_seq (buf) % s->rtp_rcc) == 0)
+            {
+                roc_len = 4;
+                if (rcc_mode (s) == 3)
+                    tag_len = 0; /* RCC mode 3 -> no auth*/
+                else
+                    tag_len -= 4; /* RCC mode 1 or 2 -> auth*/
+            }
+            else
+            {
+                if (rcc_mode (s) & 1)
+                    tag_len = 0; /* RCC mode 1 or 3 -> no auth */
+            }
+        }
+
+        *lenp = len + roc_len + tag_len;
+    }
+    else
+        tag_len = 0;
+
+    if (bufsize < *lenp)
+        return ENOSPC;
+
+    /* Encrypt payload */
+    int val = srtp_crypt (s, buf, len);
+    if (val)
+        return val;
+
+    /* Authenticate payload */
+    if (!(s->flags & SRTP_UNAUTHENTICATED))
+    {
+        uint32_t roc = srtp_compute_roc (s, rtp_seq (buf));
+        const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, roc);
+
+        if (roc_len)
+        {
+            memcpy (buf + len, &(uint32_t){ htonl (s->rtp_roc) }, 4);
+            len += 4;
+        }
+        memcpy (buf + len, tag, tag_len);
+#if 0
+        printf ("Sent    : 0x");
+        for (unsigned i = 0; i < tag_len; i++)
+            printf ("%02x", tag[i]);
+        puts ("");
+#endif
+    }
+
+    return 0;
+}
+
+
+/**
+ * Turns a SRTP packet into a RTP packet: authenticates the packet,
+ * then decrypts it.
+ *
+ * @param buf RTP packet to be digested/decrypted
+ * @param lenp pointer to the SRTP packet length on entry,
+ *             set to the RTP length on exit (undefined in case of error)
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  malformatted SRTP packet
+ *  EACCES  authentication failed (spoofed packet or out-of-sync)
+ */
+int
+srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
+{
+    size_t len = *lenp;
+    if (len < 12u)
+        return EINVAL;
+
+    if (!(s->flags & SRTP_UNAUTHENTICATED))
+    {
+        size_t tag_len = s->tag_len, roc_len = 0;
+        if (rcc_mode (s))
+        {
+            if ((rtp_seq (buf) % s->rtp_rcc) == 0)
+            {
+                roc_len = 4;
+                if (rcc_mode (s) == 3)
+                    tag_len = 0;
+                else
+                    tag_len -= 4;
+            }
+            else
+            {
+                if (rcc_mode (s) & 1)
+                    tag_len = 0; // RCC mode 1 or 3: no auth
+            }
+        }
+
+        if (len < (12u + roc_len + tag_len))
+            return EINVAL;
+        len -= roc_len + tag_len;
+
+        uint32_t roc = srtp_compute_roc (s, rtp_seq (buf)), rcc;
+        if (roc_len)
+        {
+            assert (roc_len == 4);
+            memcpy (&rcc, buf + len, 4);
+            rcc = ntohl (rcc);
+        }
+        else
+            rcc = roc;
+
+        const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, rcc);
+#if 0
+        printf ("Computed: 0x");
+        for (unsigned i = 0; i < tag_len; i++)
+            printf ("%02x", tag[i]);
+        printf ("\nReceived: 0x");
+        for (unsigned i = 0; i < tag_len; i++)
+            printf ("%02x", buf[len + roc_len + i]);
+        puts ("");
+#endif
+        if (memcmp (buf + len + roc_len, tag, tag_len))
+            return EACCES;
+
+        if (roc_len)
+        {
+            /* Authenticated packet carried a Roll-Over-Counter */
+            s->rtp_roc += rcc - roc;
+            assert (srtp_compute_roc (s, rtp_seq (buf)) == rcc);
+        }
+        *lenp = len;
+    }
+
+    return srtp_crypt (s, buf, len);
+}
+
+
+/** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
+static int
+rtcp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t index,
+            const uint32_t *salt, uint8_t *data, size_t len)
+{
+    return rtp_crypt (hd, ssrc, index >> 16, index & 0xffff, salt, data, len);
+}
+
+
+/** Message Authentication and Integrity for RTCP */
+static const uint8_t *
+rtcp_digest (gcry_md_hd_t md, const void *data, size_t len)
+{
+    gcry_md_reset (md);
+    gcry_md_write (md, data, len);
+    return gcry_md_read (md, 0);
+}
+
+
+/**
+ * Encrypts/decrypts a RTCP packet and updates SRTCP context
+ * (CTR block cypher mode of operation has identical encryption and
+ * decryption function).
+ *
+ * @param buf RTCP packet to be en-/decrypted
+ * @param len RTCP packet length
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  malformatted RTCP packet
+ */
+static int srtcp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
+{
+    assert (s != NULL);
+
+    /* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
+    if ((len < 12) || ((buf[0] >> 6) != 2))
+        return EINVAL;
+
+    uint32_t index;
+    memcpy (&index, buf + len, 4);
+    index = ntohl (index);
+    if (((index >> 31) != 0) != ((s->flags & SRTCP_UNENCRYPTED) == 0))
+        return EINVAL; // E-bit mismatch
+
+    index &= ~(1 << 31); // clear E-bit for counter
+
+    /* Updates SRTCP index (safe here) */
+    int32_t diff = index - s->rtcp_index;
+    if (diff > 0)
+    {
+        /* Packet in the future, good */
+        s->rtcp.window = s->rtcp.window << diff;
+        s->rtcp.window |= 1;
+        s->rtcp_index = index;
+    }
+    else
+    {
+        /* Packet in the past/present, bad */
+        diff = -diff;
+        if ((diff >= 64) || ((s->rtcp.window >> diff) & 1))
+            return EACCES; // replay attack!
+        s->rtp.window |= 1 << diff;
+    }
+
+    /* Crypts SRTCP */
+    if (s->flags & SRTCP_UNENCRYPTED)
+        return 0;
+
+    uint32_t ssrc;
+    memcpy (&ssrc, buf + 4, 4);
+
+    if (rtcp_crypt (s->rtcp.cipher, ssrc, index, s->rtp.salt,
+                    buf + 8, len - 8))
+        return EINVAL;
+    return 0;
+}
+
+
+/**
+ * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
+ * the authentication tag and appends it.
+ *
+ * @param buf RTCP packet to be encrypted/digested
+ * @param lenp pointer to the RTCP packet length on entry,
+ *             set to the SRTCP length on exit (undefined in case of error)
+ * @param bufsize size (bytes) of the packet buffer
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  malformatted RTCP packet or internal error
+ *  ENOSPC  bufsize is too small (to add index and authentication tag)
+ */
+int
+srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
+{
+    size_t len = *lenp;
+    if (bufsize < (len + 4 + s->tag_len))
+        return ENOSPC;
+
+    uint32_t index = ++s->rtcp_index;
+    if (index >> 31)
+        s->rtcp_index = index = 0; /* 31-bit wrap */
+
+    if ((s->flags & SRTCP_UNENCRYPTED) == 0)
+        index |= 0x80000000; /* Set Encrypted bit */
+    memcpy (buf + len, &(uint32_t){ htonl (index) }, 4);
+
+    int val = srtcp_crypt (s, buf, len);
+    if (val)
+        return val;
+
+    len += 4; /* Digests SRTCP index too */
+
+    const uint8_t *tag = rtcp_digest (s->rtcp.mac, buf, len);
+    memcpy (buf + len, tag, s->tag_len);
+    *lenp = len + s->tag_len;
+    return 0;
+}
+
+
+/**
+ * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
+ * then decrypts it.
+ *
+ * @param buf RTCP packet to be digested/decrypted
+ * @param lenp pointer to the SRTCP packet length on entry,
+ *             set to the RTCP length on exit (undefined in case of error)
+ *
+ * @return 0 on success, in case of error:
+ *  EINVAL  malformatted SRTCP packet
+ *  EACCES  authentication failed (spoofed packet or out-of-sync)
+ */
+int
+srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
+{
+    size_t len = *lenp;
+
+    if (len < (4u + s->tag_len))
+        return EINVAL;
+    len -= s->tag_len;
+
+    const uint8_t *tag = rtcp_digest (s->rtcp.mac, buf, len);
+    if (memcmp (buf + len, tag, s->tag_len))
+         return EACCES;
+
+    len -= 4; /* Remove SRTCP index before decryption */
+    *lenp = len;
+    return srtp_crypt (s, buf, len);
+}
+
diff --git a/modules/access/rtp/srtp.h b/modules/access/rtp/srtp.h
new file mode 100644 (file)
index 0000000..67e8026
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Secure RTP with libgcrypt
+ * Copyright (C) 2007  Rémi Denis-Courmont
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef LIBVLC_SRTP_H
+# define LIBVLC_SRTP_H 1
+
+typedef struct srtp_session_t srtp_session_t;
+
+enum
+{
+    SRTP_UNENCRYPTED=0x1,   //< do not encrypt SRTP packets
+    SRTCP_UNENCRYPTED=0x2,  //< do not encrypt SRTCP packets
+    SRTP_UNAUTHENTICATED=0x4, //< authenticate only SRTCP packets
+
+    SRTP_RCC_MODE1=0x10,    //< use Roll-over-Counter Carry mode 1
+    SRTP_RCC_MODE2=0x20,    //< use Roll-over-Counter Carry mode 2
+    SRTP_RCC_MODE3=0x30,    //< use Roll-over-Counter Carry mode 3 (insecure)
+
+    SRTP_FLAGS_MASK=0x37    //< mask for valid flags
+};
+
+/** SRTP encryption algorithms (ciphers); same values as MIKEY */
+enum
+{
+    SRTP_ENCR_NULL=0,   //< no encryption
+    SRTP_ENCR_AES_CM=1, //< AES counter mode
+    SRTP_ENCR_AES_F8=2, //< AES F8 mode (not implemented)
+};
+
+/** SRTP authenticaton algorithms; same values as MIKEY */
+enum
+{
+    SRTP_AUTH_NULL=0,      //< no authentication code
+    SRTP_AUTH_HMAC_SHA1=1, //< HMAC-SHA1
+};
+
+/** SRTP pseudo random function; same values as MIKEY */
+enum
+{
+    SRTP_PRF_AES_CM=0, //< AES counter mode
+};
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+srtp_session_t *srtp_create (int encr, int auth, unsigned tag_len, int prf,
+                             unsigned flags);
+void srtp_destroy (srtp_session_t *s);
+
+int srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
+                 const void *salt, size_t saltlen);
+int srtp_setkeystring (srtp_session_t *s, const char *key, const char *salt);
+
+void srtp_setrcc_rate (srtp_session_t *s, uint16_t rate);
+
+int srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t maxsize);
+int srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp);
+int srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t maxsiz);
+int srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp);
+
+# ifdef __cplusplus
+}
+# endif
+#endif
+
index b1fa089..8c24a49 100644 (file)
@@ -47,8 +47,8 @@ libstream_out_rtp_plugin_la_CFLAGS = $(AM_CFLAGS)
 libstream_out_rtp_plugin_la_LIBADD = $(AM_LIBADD) $(SOCKET_LIBS)
 libstream_out_rtp_plugin_la_DEPENDENCIES =
 if HAVE_GCRYPT
-SRTP_CFLAGS = -I$(top_srcdir)/libs/srtp
-SRTP_LIBS = $(top_builddir)/libs/srtp/libvlc_srtp.la
+SRTP_CFLAGS = -I$(top_srcdir)/modules/access/rtp
+SRTP_LIBS = $(top_builddir)/modules/access/rtp/libvlc_srtp.la
 libstream_out_rtp_plugin_la_CFLAGS += -DHAVE_SRTP $(SRTP_CFLAGS) \
        $(GCRYPT_CFLAGS)
 libstream_out_rtp_plugin_la_LIBADD += $(SRTP_LIBS) $(GCRYPT_LIBS)