SRTP: fix srtp_send() buffer size with RCC
authorRémi Denis-Courmont <remi@remlab.net>
Wed, 20 Jul 2011 15:46:04 +0000 (18:46 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Wed, 20 Jul 2011 15:54:09 +0000 (18:54 +0300)
libs/srtp/srtp.c

index b4097d0..82bb83d 100644 (file)
@@ -461,8 +461,9 @@ rtp_digest (gcry_md_hd_t md, const uint8_t *data, size_t len,
 static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
 {
     assert (s != NULL);
+    assert (len >= 12u);
 
-    if ((len < 12) || ((buf[0] >> 6) != 2))
+    if ((buf[0] >> 6) != 2)
         return EINVAL;
 
     /* Computes encryption offset */
@@ -539,41 +540,60 @@ int
 srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
 {
     size_t len = *lenp;
-    size_t tag_len = s->tag_len;
-
-    if (!(s->flags & SRTP_UNAUTHENTICATED))
-    {
-        *lenp = len + tag_len;
-        if (bufsize < (len + tag_len))
-            return ENOSPC;
-    }
+    size_t tag_len;
+    size_t roc_len = 0;
 
-    int val = srtp_crypt (s, buf, len);
-    if (val)
-        return val;
+    /* Compute required buffer size */
+    if (len < 12u)
+        return EINVAL;
 
     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);
+        tag_len = s->tag_len;
+
         if (rcc_mode (s))
         {
-            assert (s->rtp_rcc);
+            assert (tag_len >= 4);
+            assert (s->rtp_rcc != 0);
             if ((rtp_seq (buf) % s->rtp_rcc) == 0)
             {
-                memcpy (buf + len, &(uint32_t){ htonl (s->rtp_roc) }, 4);
-                len += 4;
+                roc_len = 4;
                 if (rcc_mode (s) == 3)
-                    tag_len = 0;
+                    tag_len = 0; /* RCC mode 3 -> no auth*/
                 else
-                    tag_len -= 4;
+                    tag_len -= 4; /* RCC mode 1 or 2 -> auth*/
             }
             else
             {
                 if (rcc_mode (s) & 1)
-                    tag_len = 0;
+                    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");