]> git.sesse.net Git - vlc/blob - libs/srtp/srtp.c
API cleanup
[vlc] / libs / srtp / srtp.c
1 /*
2  * Secure RTP with libgcrypt
3  * Copyright (C) 2007  RĂ©mi Denis-Courmont <rdenis # simphalempin , com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <stdint.h>
25 #include <stddef.h>
26
27 #include "srtp.h"
28
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 #include <errno.h>
33
34 #include <gcrypt.h>
35
36 #define debug( ... ) (void)0
37
38 /* TODO:
39  * Useful stuff:
40  * - ROC profile thingy (multicast really needs this)
41  *
42  * Useless stuff (because nothing depends on it):
43  * - non-nul key derivation rate
44  * - MKI payload
45  */
46
47 typedef struct srtp_proto_t
48 {
49     gcry_cipher_hd_t cipher;
50     gcry_md_hd_t     mac;
51     uint64_t         window;
52     uint32_t         salt[4];
53 } srtp_proto_t;
54
55 struct srtp_session_t
56 {
57     srtp_proto_t rtp;
58     srtp_proto_t rtcp;
59     unsigned flags;
60     unsigned kdr;
61     uint32_t rtcp_index;
62     uint32_t rtp_roc;
63     uint16_t rtp_seq;
64     uint16_t rtp_rcc;
65     uint8_t  tag_len;
66 };
67
68 enum
69 {
70     SRTP_CRYPT,
71     SRTP_AUTH,
72     SRTP_SALT,
73     SRTCP_CRYPT,
74     SRTCP_AUTH,
75     SRTCP_SALT
76 };
77
78
79 #ifdef WIN32
80 # include <winsock2.h>
81 #else
82 # include <netinet/in.h>
83 # include <pthread.h>
84 GCRY_THREAD_OPTION_PTHREAD_IMPL;
85 #endif
86
87 static bool libgcrypt_usable = false;
88
89 static void initonce_libgcrypt (void)
90 {
91     if ((gcry_check_version ("1.1.94") == NULL)
92      || gcry_control (GCRYCTL_DISABLE_SECMEM, 0)
93      || gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0)
94 #ifndef WIN32
95      || gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)
96 #endif
97        )
98         return;
99
100     libgcrypt_usable = true;
101 }
102
103 static int init_libgcrypt (void)
104 {
105     int retval;
106 #ifndef WIN32
107     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
108     static pthread_once_t once = PTHREAD_ONCE_INIT;
109
110     pthread_mutex_lock (&mutex);
111     pthread_once (&once, initonce_libgcrypt);
112     retval = -libgcrypt_usable;
113     pthread_mutex_unlock (&mutex);
114 #else
115 # warning FIXME: This is not thread-safe.
116     if (!libgcrypt_usable)
117         initonce_libgcrypt ();
118     retval = -libgcrypt_usable;
119 #endif
120
121     return retval;
122
123 }
124
125
126 static void proto_destroy (srtp_proto_t *p)
127 {
128     gcry_md_close (p->mac);
129     gcry_cipher_close (p->cipher);
130 }
131
132
133 /**
134  * Releases all resources associated with a Secure RTP session.
135  */
136 void srtp_destroy (srtp_session_t *s)
137 {
138     assert (s != NULL);
139
140     proto_destroy (&s->rtcp);
141     proto_destroy (&s->rtp);
142     free (s);
143 }
144
145
146 static int proto_create (srtp_proto_t *p, int gcipher, int gmd)
147 {
148     if (gcry_cipher_open (&p->cipher, gcipher, GCRY_CIPHER_MODE_CTR, 0) == 0)
149     {
150         if (gcry_md_open (&p->mac, gmd, GCRY_MD_FLAG_HMAC) == 0)
151             return 0;
152         gcry_cipher_close (p->cipher);
153     }
154     return -1;
155 }
156
157
158 /**
159  * Allocates a Secure RTP one-way session.
160  * The same session cannot be used both ways because this would confuse
161  * internal cryptographic counters; it is however of course feasible to open
162  * multiple simultaneous sessions with the same master key.
163  *
164  * @param encr encryption algorithm number
165  * @param auth authentication algortihm number
166  * @param tag_len authentication tag byte length (NOT including RCC)
167  * @param flags OR'ed optional flags.
168  *
169  * @return NULL in case of error
170  */
171 srtp_session_t *
172 srtp_create (int encr, int auth, unsigned tag_len, int prf, unsigned flags)
173 {
174     if ((flags & ~SRTP_FLAGS_MASK) || init_libgcrypt ())
175         return NULL;
176
177     int cipher, md;
178     switch (encr)
179     {
180         case SRTP_ENCR_NULL:
181             cipher = GCRY_CIPHER_NONE;
182             break;
183
184         case SRTP_ENCR_AES_CM:
185             cipher = GCRY_CIPHER_AES;
186             break;
187
188         default:
189             return NULL;
190     }
191
192     switch (auth)
193     {
194         case SRTP_AUTH_NULL:
195             md = GCRY_MD_NONE;
196             break;
197
198         case SRTP_AUTH_HMAC_SHA1:
199             md = GCRY_MD_SHA1;
200             break;
201
202         default:
203             return NULL;
204     }
205
206     if (tag_len > gcry_md_get_algo_dlen (auth))
207         return NULL;
208
209     if (prf != SRTP_PRF_AES_CM)
210         return NULL;
211
212     srtp_session_t *s = malloc (sizeof (*s));
213     if (s == NULL)
214         return NULL;
215
216     memset (s, 0, sizeof (*s));
217     s->flags = flags;
218     s->tag_len = tag_len;
219
220     if (proto_create (&s->rtp, cipher, md) == 0)
221     {
222         if (proto_create (&s->rtcp, cipher, md) == 0)
223             return s;
224         proto_destroy (&s->rtp);
225     }
226
227     free (s);
228     return NULL;
229 }
230
231
232 /**
233  * AES-CM key derivation (saltlen = 14 bytes)
234  */
235 static int
236 derive (gcry_cipher_hd_t prf, const void *salt,
237         const uint8_t *r, size_t rlen, uint8_t label,
238         void *out, size_t outlen)
239 {
240     uint8_t iv[16];
241
242     memcpy (iv, salt, 14);
243     iv[14] = iv[15] = 0;
244
245     assert (rlen < 14);
246     iv[13 - rlen] ^= label;
247     for (size_t i = 0; i < rlen; i++)
248         iv[sizeof (iv) - rlen + i] ^= r[i];
249
250     /* TODO: retry with CTR mode */
251     while (outlen >= sizeof (iv))
252     {
253         /* AES */
254         if (gcry_cipher_encrypt (prf, out, sizeof (iv), iv, sizeof (iv)))
255             return EINVAL;
256         outlen -= sizeof (iv);
257         out = ((uint8_t *)out) + sizeof (iv);
258
259         /* Increment IV in network byte order */
260         if (++iv[sizeof (iv) - 1] == 0)
261             ++iv[sizeof (iv) -2];
262     }
263
264     if (outlen > 0)
265     {
266         /* Truncated last AES output block */
267         if (gcry_cipher_encrypt (prf, iv, sizeof (iv), NULL, 0))
268             return -1;
269         memcpy (out, iv, outlen);
270     }
271
272     return 0;
273 }
274
275
276 static int
277 proto_derive (srtp_proto_t *p, gcry_cipher_hd_t prf,
278               const void *salt, size_t saltlen,
279               const uint8_t *r, size_t rlen, bool rtcp)
280 {
281     if (saltlen != 14)
282         return -1;
283
284     uint8_t keybuf[20];
285     uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT;
286
287     if (derive (prf, salt, r, rlen, label++, keybuf, 16)
288      || gcry_cipher_setkey (p->cipher, keybuf, 16)
289      || derive (prf, salt, r, rlen, label++, keybuf, 20)
290      || gcry_md_setkey (p->mac, keybuf, 20)
291      || derive (prf, salt, r, rlen, label, p->salt, 14))
292         return -1;
293
294     return 0;
295 }
296
297
298 /**
299  * SRTP/SRTCP cipher/salt/MAC keys derivation.
300  */
301 static int
302 srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
303              const void *salt, size_t saltlen)
304 {
305     gcry_cipher_hd_t prf;
306     uint8_t r[6];
307
308     /* TODO: retry with CTR mode */
309     if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0)
310      || gcry_cipher_setkey (prf, key, keylen))
311         return -1;
312
313     /* RTP key derivation */
314     if (s->kdr != 0)
315     {
316         uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
317         index /= s->kdr;
318
319         for (int i = sizeof (r) - 1; i >= 0; i--)
320         {
321             r[i] = index & 0xff;
322             index = index >> 8;
323         }
324     }
325     else
326         memset (r, 0, sizeof (r));
327
328     if (proto_derive (&s->rtp, prf, salt, saltlen, r, 6, false))
329         return -1;
330
331     /* RTCP key derivation */
332     memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
333     if (proto_derive (&s->rtcp, prf, salt, saltlen, r, 4, true))
334         return -1;
335
336     (void)gcry_cipher_close (prf);
337     return 0;
338 }
339
340
341 /**
342  * Sets (or resets) the master key and master salt for a SRTP session.
343  * This must be done at least once before using rtp_send(), rtp_recv(),
344  * rtcp_send() or rtcp_recv(). Also, rekeying is required every
345  * 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
346  * otherwise the protocol security might be broken.
347  *
348  * @return 0 on success, in case of error:
349  *  EINVAL  invalid or unsupported key/salt sizes combination
350  */
351 int
352 srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
353              const void *salt, size_t saltlen)
354 {
355     return srtp_derive (s, key, keylen, salt, saltlen) ? EINVAL : 0;
356 }
357
358
359 /**
360  * Sets Roll-over-Counter Carry (RCC) rate for the SRTP session. If not
361  * specified (through this function), the default rate of ONE is assumed
362  * (i.e. every RTP packets will carry the RoC). RCC rate is ignored if none
363  * of the RCC mode has been selected.
364  *
365  * The RCC mode is selected through one of these flags for srtp_create():
366  *  SRTP_RCC_MODE1: integrity protection only for RoC carrying packets
367  *  SRTP_RCC_MODE2: integrity protection for all packets
368  *  SRTP_RCC_MODE3: no integrity protection
369  *
370  * RCC mode 3 is insecure. Compared to plain RTP, it provides confidentiality
371  * (through encryption) but is much more prone to DoS. It can only be used if
372  * anti-spoofing protection is provided by lower network layers (e.g. IPsec,
373  * or trusted routers and proper source address filtering).
374  *
375  * If RCC rate is 1, RCC mode 1 and 2 are functionally identical.
376  *
377  * @param rate RoC Carry rate (MUST NOT be zero)
378  */
379 void srtp_setrcc_rate (srtp_session_t *s, uint16_t rate)
380 {
381     assert (rate != 0);
382     s->rtp_rcc = rate;
383 }
384
385
386 /** AES-CM encryption/decryption (ctr length = 16 bytes) */
387 static int
388 ctr_crypt (gcry_cipher_hd_t hd, uint32_t *ctr, uint8_t *data, size_t len)
389 {
390     const size_t ctrlen = 16;
391     while (len >= ctrlen)
392     {
393         if (gcry_cipher_setctr (hd, ctr, ctrlen)
394          || gcry_cipher_encrypt (hd, data, ctrlen, NULL, 0))
395             return -1;
396
397         data += ctrlen;
398         len -= ctrlen;
399         ctr[3] = htonl (ntohl (ctr[3]) + 1);
400     }
401
402     if (len > 0)
403     {
404         /* Truncated last block */
405         uint8_t dummy[ctrlen];
406         memcpy (dummy, data, len);
407         memset (dummy + len, 0, ctrlen - len);
408
409         if (gcry_cipher_setctr (hd, ctr, ctrlen)
410          || gcry_cipher_encrypt (hd, dummy, ctrlen, data, ctrlen))
411             return -1;
412         memcpy (data, dummy, len);
413     }
414
415     return 0;
416 }
417
418
419 /** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
420 static int
421 rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
422            const uint32_t *salt, uint8_t *data, size_t len)
423 {
424     /* Determines cryptographic counter (IV) */
425     uint32_t counter[4];
426     counter[0] = salt[0];
427     counter[1] = salt[1] ^ ssrc;
428     counter[2] = salt[2] ^ htonl (roc);
429     counter[3] = salt[3] ^ htonl (seq << 16);
430
431     /* Encryption */
432     return ctr_crypt (hd, counter, data, len);
433 }
434
435
436 /** Determines SRTP Roll-Over-Counter (in host-byte order) */
437 static uint32_t
438 srtp_compute_roc (const srtp_session_t *s, uint16_t seq)
439 {
440     uint32_t roc = s->rtp_roc;
441
442     if (((seq - s->rtp_seq) & 0xffff) < 0x8000)
443     {
444         /* Sequence is ahead, good */
445         if (seq < s->rtp_seq)
446             roc++; /* Sequence number wrap */
447     }
448     else
449     {
450         /* Sequence is late, bad */
451         if (seq > s->rtp_seq)
452             roc--; /* Wrap back */
453     }
454     return roc;
455 }
456
457
458 /** Returns RTP sequence (in host-byte order) */
459 static inline uint16_t rtp_seq (const uint8_t *buf)
460 {
461     return (buf[2] << 8) | buf[3];
462 }
463
464
465 /** Message Authentication and Integrity for RTP */
466 static const uint8_t *
467 rtp_digest (srtp_session_t *s, const uint8_t *data, size_t len)
468 {
469     const gcry_md_hd_t md = s->rtp.mac;
470     uint32_t roc = htonl (srtp_compute_roc (s, rtp_seq (data)));
471
472     gcry_md_reset (md);
473     gcry_md_write (md, data, len);
474     gcry_md_write (md, &roc, 4);
475     return gcry_md_read (md, 0);
476 }
477
478
479 /**
480  * Encrypts/decrypts a RTP packet and updates SRTP context
481  * (CTR block cypher mode of operation has identical encryption and
482  * decryption function).
483  *
484  * @param buf RTP packet to be en-/decrypted
485  * @param len RTP packet length
486  *
487  * @return 0 on success, in case of error:
488  *  EINVAL  malformatted RTP packet
489  *  EACCES  replayed packet or out-of-window or sync lost
490  */
491 static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
492 {
493     assert (s != NULL);
494
495     if ((len < 12) || ((buf[0] >> 6) != 2))
496         return EINVAL;
497
498     /* Computes encryption offset */
499     uint16_t offset = 12;
500     offset += (buf[0] & 0xf) * 4; // skips CSRC
501
502     if (buf[0] & 0x10)
503     {
504         uint16_t extlen;
505
506         offset += 4;
507         if (len < offset)
508             return EINVAL;
509
510         memcpy (&extlen, buf + offset - 2, 2);
511         offset += htons (extlen); // skips RTP extension header
512     }
513
514     if (len < offset)
515         return EINVAL;
516
517     /* Determines RTP 48-bits counter and SSRC */
518     uint16_t seq = rtp_seq (buf);
519     uint32_t roc = srtp_compute_roc (s, seq), ssrc;
520     memcpy (&ssrc, buf + 8, 4);
521
522     /* Updates ROC and sequence (it's safe now) */
523     int16_t diff = seq - s->rtp_seq;
524     if (diff > 0)
525     {
526         /* Sequence in the future, good */
527         s->rtp.window = s->rtp.window << diff;
528         s->rtp.window |= 1;
529         s->rtp_seq = seq, s->rtp_roc = roc;
530     }
531     else
532     {
533         /* Sequence in the past/present, bad */
534         diff = -diff;
535         if ((diff >= 64) || ((s->rtp.window >> diff) & 1))
536             return EACCES; /* Replay attack */
537         s->rtp.window |= 1 << diff;
538     }
539
540     /* Encrypt/Decrypt */
541     if (s->flags & SRTP_UNENCRYPTED)
542         return 0;
543
544     if (rtp_crypt (s->rtp.cipher, ssrc, roc, seq, s->rtp.salt,
545                    buf + offset, len - offset))
546         return EINVAL;
547
548     return 0;
549 }
550
551
552 /**
553  * Turns a RTP packet into a SRTP packet: encrypt it, then computes
554  * the authentication tag and appends it.
555  * Note that you can encrypt packet in disorder.
556  *
557  * @param buf RTP packet to be encrypted/digested
558  * @param lenp pointer to the RTP packet length on entry,
559  *             set to the SRTP length on exit (undefined in case of error)
560  * @param bufsize size (bytes) of the packet buffer
561  *
562  * @return 0 on success, in case of error:
563  *  EINVAL  malformatted RTP packet or internal error
564  *  ENOSPC  bufsize is too small (to add authentication tag)
565  *  EACCES  packet would trigger a replay error on receiver
566  */
567 int
568 srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
569 {
570     size_t len = *lenp;
571     int val = srtp_crypt (s, buf, len);
572     if (val)
573         return val;
574
575     if (!(s->flags & SRTP_UNAUTHENTICATED))
576     {
577         if (bufsize < (len + s->tag_len))
578             return ENOSPC;
579
580         const uint8_t *tag = rtp_digest (s, buf, len);
581         memcpy (buf + len, tag, s->tag_len);
582         *lenp = len + s->tag_len;
583     }
584
585     return 0;
586 }
587
588
589 /**
590  * Turns a SRTP packet into a RTP packet: authenticates the packet,
591  * then decrypts it.
592  *
593  * @param buf RTP packet to be digested/decrypted
594  * @param lenp pointer to the SRTP packet length on entry,
595  *             set to the RTP length on exit (undefined in case of error)
596  *
597  * @return 0 on success, in case of error:
598  *  EINVAL  malformatted SRTP packet
599  *  EACCES  authentication failed (spoofed packet or out-of-sync)
600  */
601 int
602 srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
603 {
604     size_t len = *lenp;
605
606     if (!(s->flags & SRTP_UNAUTHENTICATED))
607     {
608         if (len < (12u + s->tag_len))
609             return EINVAL;
610         len -= s->tag_len;
611
612         const uint8_t *tag = rtp_digest (s, buf, len);
613         if (memcmp (buf + len, tag, s->tag_len))
614             return EACCES;
615
616         *lenp = len;
617     }
618
619     return srtp_crypt (s, buf, len);
620 }
621
622
623 /** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
624 static int
625 rtcp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t index,
626             const uint32_t *salt, uint8_t *data, size_t len)
627 {
628     return rtp_crypt (hd, ssrc, index >> 16, index & 0xffff, salt, data, len);
629 }
630
631
632 /** Message Authentication and Integrity for RTCP */
633 static const uint8_t *
634 rtcp_digest (gcry_md_hd_t md, const void *data, size_t len)
635 {
636     gcry_md_reset (md);
637     gcry_md_write (md, data, len);
638     return gcry_md_read (md, 0);
639 }
640
641
642 /**
643  * Encrypts/decrypts a RTCP packet and updates SRTCP context
644  * (CTR block cypher mode of operation has identical encryption and
645  * decryption function).
646  *
647  * @param buf RTCP packet to be en-/decrypted
648  * @param len RTCP packet length
649  *
650  * @return 0 on success, in case of error:
651  *  EINVAL  malformatted RTCP packet
652  */
653 static int srtcp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
654 {
655     assert (s != NULL);
656
657     /* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
658     if ((len < 12) || ((buf[0] >> 6) != 2))
659         return EINVAL;
660
661     uint32_t index;
662     memcpy (&index, buf + len, 4);
663     index = ntohl (index);
664     if (((index >> 31) != 0) != ((s->flags & SRTCP_UNENCRYPTED) == 0))
665         return EINVAL; // E-bit mismatch
666
667     index &= ~(1 << 31); // clear E-bit for counter
668
669     /* Updates SRTCP index (safe here) */
670     int32_t diff = index - s->rtcp_index;
671     if (diff > 0)
672     {
673         /* Packet in the future, good */
674         s->rtcp.window = s->rtcp.window << diff;
675         s->rtcp.window |= 1;
676         s->rtcp_index = index;
677     }
678     else
679     {
680         /* Packet in the past/present, bad */
681         diff = -diff;
682         if ((diff >= 64) || ((s->rtcp.window >> diff) & 1))
683             return EACCES; // replay attack!
684         s->rtp.window |= 1 << diff;
685     }
686
687     /* Crypts SRTCP */
688     if (s->flags & SRTCP_UNENCRYPTED)
689         return 0;
690
691     uint32_t ssrc;
692     memcpy (&ssrc, buf + 4, 4);
693
694     if (rtcp_crypt (s->rtcp.cipher, ssrc, index, s->rtp.salt,
695                     buf + 8, len - 8))
696         return EINVAL;
697     return 0;
698 }
699
700
701 /**
702  * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
703  * the authentication tag and appends it.
704  *
705  * @param buf RTCP packet to be encrypted/digested
706  * @param lenp pointer to the RTCP packet length on entry,
707  *             set to the SRTCP length on exit (undefined in case of error)
708  * @param bufsize size (bytes) of the packet buffer
709  *
710  * @return 0 on success, in case of error:
711  *  EINVAL  malformatted RTCP packet or internal error
712  *  ENOSPC  bufsize is too small (to add index and authentication tag)
713  */
714 int
715 srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
716 {
717     size_t len = *lenp;
718     if (bufsize < (len + 4 + s->tag_len))
719         return ENOSPC;
720
721     uint32_t index = ++s->rtcp_index;
722     if (index >> 31)
723         s->rtcp_index = index = 0; /* 31-bit wrap */
724
725     if ((s->flags & SRTCP_UNENCRYPTED) == 0)
726         index |= 0x80000000; /* Set Encrypted bit */
727     memcpy (buf + len, &(uint32_t){ htonl (index) }, 4);
728
729     int val = srtcp_crypt (s, buf, len);
730     if (val)
731         return val;
732
733     len += 4; /* Digests SRTCP index too */
734
735     const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
736     memcpy (buf + len, tag, s->tag_len);
737     *lenp = len + s->tag_len;
738     return 0;
739 }
740
741
742 /**
743  * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
744  * then decrypts it.
745  *
746  * @param buf RTCP packet to be digested/decrypted
747  * @param lenp pointer to the SRTCP packet length on entry,
748  *             set to the RTCP length on exit (undefined in case of error)
749  *
750  * @return 0 on success, in case of error:
751  *  EINVAL  malformatted SRTCP packet
752  *  EACCES  authentication failed (spoofed packet or out-of-sync)
753  */
754 int
755 srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
756 {
757     size_t len = *lenp;
758
759     if (len < (4u + s->tag_len))
760         return EINVAL;
761     len -= s->tag_len;
762
763     const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
764     if (memcmp (buf + len, tag, s->tag_len))
765          return EACCES;
766
767     len -= 4; /* Remove SRTCP index before decryption */
768     *lenp = len;
769     return srtp_crypt (s, buf, len);
770 }
771