[vlc-commits] SRTP: refactor

Rémi Denis-Courmont git at videolan.org
Tue Jul 19 17:17:55 CEST 2011


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Jul 19 17:46:17 2011 +0300| [ad28a7f33d23de90a13c14a5ca19e9e4d826a9e4] | committer: Rémi Denis-Courmont

SRTP: refactor

Signed-off-by: Rémi Denis-Courmont <remi at remlab.net>

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=ad28a7f33d23de90a13c14a5ca19e9e4d826a9e4
---

 libs/srtp/srtp.c     |   98 +++++++++++++++++++-------------------------------
 libs/srtp/test-aes.c |    6 ++--
 2 files changed, 40 insertions(+), 64 deletions(-)

diff --git a/libs/srtp/srtp.c b/libs/srtp/srtp.c
index 324b14c..b4097d0 100644
--- a/libs/srtp/srtp.c
+++ b/libs/srtp/srtp.c
@@ -203,7 +203,7 @@ error:
  * with non-padded (truncated) text
  */
 static int
-ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len)
+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);
@@ -233,9 +233,9 @@ ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len)
  * AES-CM key derivation (saltlen = 14 bytes)
  */
 static int
-derive (gcry_cipher_hd_t prf, const void *salt,
-        const uint8_t *r, size_t rlen, uint8_t label,
-        void *out, size_t outlen)
+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];
 
@@ -248,48 +248,37 @@ derive (gcry_cipher_hd_t prf, const void *salt,
         iv[sizeof (iv) - rlen + i] ^= r[i];
 
     memset (out, 0, outlen);
-    return ctr_crypt (prf, iv, out, outlen);
-}
-
-
-static int
-proto_derive (srtp_proto_t *p, gcry_cipher_hd_t prf,
-              const void *salt, size_t saltlen,
-              const uint8_t *r, size_t rlen, bool rtcp)
-{
-    if (saltlen != 14)
-        return -1;
-
-    uint8_t keybuf[20];
-    uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT;
-
-    if (derive (prf, salt, r, rlen, label++, keybuf, 16)
-     || gcry_cipher_setkey (p->cipher, keybuf, 16)
-     || derive (prf, salt, r, rlen, label++, keybuf, 20)
-     || gcry_md_setkey (p->mac, keybuf, 20)
-     || derive (prf, salt, r, rlen, label, p->salt, 14))
-        return -1;
-
-    return 0;
+    return do_ctr_crypt (prf, iv, out, outlen);
 }
 
 
 /**
- * SRTP/SRTCP cipher/salt/MAC keys derivation.
+ * 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
  */
-static int
-srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
+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];
+    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 -1;
+        return EINVAL;
 
+    /* SRTP key derivation */
 #if 0
-    /* RTP key derivation */
     if (s->kdr != 0)
     {
         uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
@@ -304,37 +293,26 @@ srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
     else
 #endif
         memset (r, 0, sizeof (r));
-
-    if (proto_derive (&s->rtp, prf, salt, saltlen, r, 6, false))
+    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;
 
-    /* RTCP key derivation */
+    /* SRTCP key derivation */
     memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
-    if (proto_derive (&s->rtcp, prf, salt, saltlen, r, 4, true))
+    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;
 }
 
-
-/**
- * Sets (or resets) the master key and master salt for a SRTP session.
- * This must be done at least once before using rtp_send(), rtp_recv(),
- * rtcp_send() or rtcp_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)
-{
-    return srtp_derive (s, key, keylen, salt, saltlen) ? EINVAL : 0;
-}
-
 static int hexdigit (char c)
 {
     if ((c >= '0') && (c <= '9'))
@@ -423,7 +401,7 @@ rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
     counter[3] = salt[3] ^ htonl (seq << 16);
 
     /* Encryption */
-    return ctr_crypt (hd, counter, data, len);
+    return do_ctr_crypt (hd, counter, data, len);
 }
 
 
@@ -458,11 +436,9 @@ static inline uint16_t rtp_seq (const uint8_t *buf)
 
 /** Message Authentication and Integrity for RTP */
 static const uint8_t *
-rtp_digest (srtp_session_t *s, const uint8_t *data, size_t len,
+rtp_digest (gcry_md_hd_t md, const uint8_t *data, size_t len,
             uint32_t roc)
 {
-    const gcry_md_hd_t md = s->rtp.mac;
-
     gcry_md_reset (md);
     gcry_md_write (md, data, len);
     gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4);
@@ -579,7 +555,7 @@ srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
     if (!(s->flags & SRTP_UNAUTHENTICATED))
     {
         uint32_t roc = srtp_compute_roc (s, rtp_seq (buf));
-        const uint8_t *tag = rtp_digest (s, buf, len, roc);
+        const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, roc);
         if (rcc_mode (s))
         {
             assert (s->rtp_rcc);
@@ -664,7 +640,7 @@ srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
         else
             rcc = roc;
 
-        const uint8_t *tag = rtp_digest (s, buf, len, rcc);
+        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++)
diff --git a/libs/srtp/test-aes.c b/libs/srtp/test-aes.c
index ae55f34..6168434 100644
--- a/libs/srtp/test-aes.c
+++ b/libs/srtp/test-aes.c
@@ -67,21 +67,21 @@ static void test_derivation (void)
      || gcry_cipher_setkey (prf, key, sizeof (key)))
         fatal ("Internal PRF error");
 
-    if (derive (prf, salt, r, sizeof (r), SRTP_CRYPT, out, 16))
+    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 (derive (prf, salt, r, sizeof (r), SRTP_SALT, out, 14))
+    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 (derive (prf, salt, r, sizeof (r), SRTP_AUTH, out, 94))
+    if (do_derive (prf, salt, r, sizeof (r), SRTP_AUTH, out, 94))
         fatal ("Internal auth key derivation error");
     printf (" auth key:    ");
     printhex (out, 94);



More information about the vlc-commits mailing list