]> git.sesse.net Git - vlc/blob - libs/srtp/srtp.c
SRTP/SRTCP receive window for replay attack protection
[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     uint8_t  tag_len;
65 };
66
67 enum
68 {
69     SRTP_CRYPT,
70     SRTP_AUTH,
71     SRTP_SALT,
72     SRTCP_CRYPT,
73     SRTCP_AUTH,
74     SRTCP_SALT
75 };
76
77 #ifdef WIN32
78 # include <winsock2.h>
79 #else
80 # include <netinet/in.h>
81 # include <pthread.h>
82 GCRY_THREAD_OPTION_PTHREAD_IMPL;
83 #endif
84
85 static bool libgcrypt_usable = false;
86
87 static void initonce_libgcrypt (void)
88 {
89     if ((gcry_check_version ("1.1.94") == NULL)
90      || gcry_control (GCRYCTL_DISABLE_SECMEM, 0)
91      || gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0)
92 #ifndef WIN32
93      || gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)
94 #endif
95        )
96         return;
97
98     libgcrypt_usable = true;
99 }
100
101 static int init_libgcrypt (void)
102 {
103     int retval;
104 #ifndef WIN32
105     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
106     static pthread_once_t once = PTHREAD_ONCE_INIT;
107
108     pthread_mutex_lock (&mutex);
109     pthread_once (&once, initonce_libgcrypt);
110     retval = -libgcrypt_usable;
111     pthread_mutex_unlock (&mutex);
112 #else
113 # warning FIXME: This is not thread-safe.
114     if (!libgcrypt_usable)
115         initonce_libgcrypt ();
116     retval = -libgcrypt_usable;
117 #endif
118
119     return retval;
120
121 }
122
123
124 static void proto_destroy (srtp_proto_t *p)
125 {
126     gcry_md_close (p->mac);
127     gcry_cipher_close (p->cipher);
128 }
129
130
131 /**
132  * Releases all resources associated with a Secure RTP session.
133  */
134 void srtp_destroy (srtp_session_t *s)
135 {
136     assert (s != NULL);
137
138     proto_destroy (&s->rtcp);
139     proto_destroy (&s->rtp);
140     free (s);
141 }
142
143
144 static int proto_create (srtp_proto_t *p, int gcipher, int gmd)
145 {
146     if (gcry_cipher_open (&p->cipher, gcipher, GCRY_CIPHER_MODE_CTR, 0) == 0)
147     {
148         if (gcry_md_open (&p->mac, gmd, GCRY_MD_FLAG_HMAC) == 0)
149             return 0;
150         gcry_cipher_close (p->cipher);
151     }
152     return -1;
153 }
154
155
156 /**
157  * Allocates a Secure RTP one-way session.
158  * The same session cannot be used both ways because this would confuse
159  * internal cryptographic counters; it is however of course feasible to open
160  * multiple simultaneous sessions with the same master key.
161  *
162  * @param name cipher-suite name
163  * @param kdr key derivation rate
164  * @param flags OR'ed optional flags.
165  *
166  * @return NULL in case of error
167  */
168 srtp_session_t *
169 srtp_create (const char *name, unsigned flags, unsigned kdr)
170 {
171     assert (name != NULL);
172
173     if (kdr != 0)
174         return NULL; // FIXME: KDR not implemented yet
175
176     uint8_t tag_len;
177     int cipher = GCRY_CIPHER_AES, md = GCRY_MD_SHA1;
178
179     if (strcmp (name, "AES_CM_128_HMAC_SHA1_80") == 0)
180         tag_len = 10;
181     else
182     if (strcmp (name, "AES_CM_128_HMAC_SHA1_32") == 0)
183         tag_len = 4;
184     else
185     // F8_128_HMAC_SHA1_80 is not implemented
186         return NULL;
187
188     if ((flags & ~SRTP_FLAGS_MASK) || init_libgcrypt ())
189         return NULL;
190
191     srtp_session_t *s = malloc (sizeof (*s));
192     if (s == NULL)
193         return NULL;
194
195     memset (s, 0, sizeof (*s));
196     s->flags = flags;
197     s->kdr = kdr;
198     s->tag_len = tag_len;
199
200     if (proto_create (&s->rtp, cipher, md) == 0)
201     {
202         if (proto_create (&s->rtcp, cipher, md) == 0)
203             return s;
204         proto_destroy (&s->rtp);
205     }
206
207     free (s);
208     return NULL;
209 }
210
211
212 /**
213  * AES-CM key derivation (saltlen = 14 bytes)
214  */
215 static int
216 derive (gcry_cipher_hd_t prf, const void *salt,
217         const uint8_t *r, size_t rlen, uint8_t label,
218         void *out, size_t outlen)
219 {
220     uint8_t iv[16];
221
222     memcpy (iv, salt, 14);
223     iv[14] = iv[15] = 0;
224
225     assert (rlen < 14);
226     iv[13 - rlen] ^= label;
227     for (size_t i = 0; i < rlen; i++)
228         iv[sizeof (iv) - rlen + i] ^= r[i];
229
230     /* TODO: retry with CTR mode */
231     while (outlen >= sizeof (iv))
232     {
233         /* AES */
234         if (gcry_cipher_encrypt (prf, out, sizeof (iv), iv, sizeof (iv)))
235             return EINVAL;
236         outlen -= sizeof (iv);
237         out = ((uint8_t *)out) + sizeof (iv);
238
239         /* Increment IV in network byte order */
240         if (++iv[sizeof (iv) - 1] == 0)
241             ++iv[sizeof (iv) -2];
242     }
243
244     if (outlen > 0)
245     {
246         /* Truncated last AES output block */
247         if (gcry_cipher_encrypt (prf, iv, sizeof (iv), NULL, 0))
248             return -1;
249         memcpy (out, iv, outlen);
250     }
251
252     return 0;
253 }
254
255
256 static int
257 proto_derive (srtp_proto_t *p, gcry_cipher_hd_t prf,
258               const void *salt, size_t saltlen,
259               const uint8_t *r, size_t rlen, bool rtcp)
260 {
261     if (saltlen != 14)
262         return -1;
263
264     uint8_t keybuf[20];
265     uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT;
266
267     if (derive (prf, salt, r, rlen, label++, keybuf, 16)
268      || gcry_cipher_setkey (p->cipher, keybuf, 16)
269      || derive (prf, salt, r, rlen, label++, keybuf, 20)
270      || gcry_md_setkey (p->mac, keybuf, 20)
271      || derive (prf, salt, r, rlen, label, p->salt, 14))
272         return -1;
273
274     return 0;
275 }
276
277
278 /**
279  * SRTP/SRTCP cipher/salt/MAC keys derivation.
280  */
281 static int
282 srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
283              const void *salt, size_t saltlen)
284 {
285     gcry_cipher_hd_t prf;
286     uint8_t r[6];
287
288     /* TODO: retry with CTR mode */
289     if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0)
290      || gcry_cipher_setkey (prf, key, keylen))
291         return -1;
292
293     /* RTP key derivation */
294     if (s->kdr != 0)
295     {
296         uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
297         index /= s->kdr;
298
299         for (int i = sizeof (r) - 1; i >= 0; i--)
300         {
301             r[i] = index & 0xff;
302             index = index >> 8;
303         }
304     }
305     else
306         memset (r, 0, sizeof (r));
307
308     if (proto_derive (&s->rtp, prf, salt, saltlen, r, 6, false))
309         return -1;
310
311     /* RTCP key derivation */
312     memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
313     if (proto_derive (&s->rtcp, prf, salt, saltlen, r, 4, true))
314         return -1;
315
316     (void)gcry_cipher_close (prf);
317     return 0;
318 }
319
320
321 /**
322  * Sets (or resets) the master key and master salt for a SRTP session.
323  * This must be done at least once before using rtp_send(), rtp_recv(),
324  * rtcp_send() or rtcp_recv(). Also, rekeying is required every
325  * 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
326  * otherwise the protocol security might be broken.
327  *
328  * @return 0 on success, in case of error:
329  *  EINVAL  invalid or unsupported key/salt sizes combination
330  */
331 int
332 srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
333              const void *salt, size_t saltlen)
334 {
335     return srtp_derive (s, key, keylen, salt, saltlen) ? EINVAL : 0;
336 }
337
338
339 /** AES-CM encryption/decryption (ctr length = 16 bytes) */
340 static int
341 ctr_crypt (gcry_cipher_hd_t hd, uint32_t *ctr, uint8_t *data, size_t len)
342 {
343     const size_t ctrlen = 16;
344     while (len >= ctrlen)
345     {
346         if (gcry_cipher_setctr (hd, ctr, ctrlen)
347          || gcry_cipher_encrypt (hd, data, ctrlen, NULL, 0))
348             return -1;
349
350         data += ctrlen;
351         len -= ctrlen;
352         ctr[3] = htonl (ntohl (ctr[3]) + 1);
353     }
354
355     if (len > 0)
356     {
357         /* Truncated last block */
358         uint8_t dummy[ctrlen];
359         memcpy (dummy, data, len);
360         memset (dummy + len, 0, ctrlen - len);
361
362         if (gcry_cipher_setctr (hd, ctr, ctrlen)
363          || gcry_cipher_encrypt (hd, dummy, ctrlen, data, ctrlen))
364             return -1;
365         memcpy (data, dummy, len);
366     }
367
368     return 0;
369 }
370
371
372 /** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
373 static int
374 rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
375            const uint32_t *salt, uint8_t *data, size_t len)
376 {
377     /* Determines cryptographic counter (IV) */
378     uint32_t counter[4];
379     counter[0] = salt[0];
380     counter[1] = salt[1] ^ ssrc;
381     counter[2] = salt[2] ^ htonl (roc);
382     counter[3] = salt[3] ^ htonl (seq << 16);
383
384     /* Encryption */
385     return ctr_crypt (hd, counter, data, len);
386 }
387
388
389 /** Determines SRTP Roll-Over-Counter (in host-byte order) */
390 static uint32_t
391 srtp_compute_roc (const srtp_session_t *s, uint16_t seq)
392 {
393     uint32_t roc = s->rtp_roc;
394
395     if (((seq - s->rtp_seq) & 0xffff) < 0x8000)
396     {
397         /* Sequence is ahead, good */
398         if (seq < s->rtp_seq)
399             roc++; /* Sequence number wrap */
400     }
401     else
402     {
403         /* Sequence is late, bad */
404         if (seq > s->rtp_seq)
405             roc--; /* Wrap back */
406     }
407     return roc;
408 }
409
410
411 /** Returns RTP sequence (in host-byte order) */
412 static inline uint16_t rtp_seq (const uint8_t *buf)
413 {
414     return (buf[2] << 8) | buf[3];
415 }
416
417
418 /** Message Authentication and Integrity for RTP */
419 static const uint8_t *
420 rtp_digest (srtp_session_t *s, const uint8_t *data, size_t len)
421 {
422     const gcry_md_hd_t md = s->rtp.mac;
423     uint32_t roc = htonl (srtp_compute_roc (s, rtp_seq (data)));
424
425     gcry_md_reset (md);
426     gcry_md_write (md, data, len);
427     gcry_md_write (md, &roc, 4);
428     return gcry_md_read (md, 0);
429 }
430
431
432 /**
433  * Encrypts/decrypts a RTP packet and updates SRTP context
434  * (CTR block cypher mode of operation has identical encryption and
435  * decryption function).
436  *
437  * @param buf RTP packet to be en-/decrypted
438  * @param len RTP packet length
439  *
440  * @return 0 on success, in case of error:
441  *  EINVAL  malformatted RTP packet
442  *  EACCES  replayed packet or out-of-window or sync lost
443  */
444 static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
445 {
446     assert (s != NULL);
447
448     if ((len < 12) || ((buf[0] >> 6) != 2))
449         return EINVAL;
450
451     /* Computes encryption offset */
452     uint16_t offset = 12;
453     offset += (buf[0] & 0xf) * 4; // skips CSRC
454
455     if (buf[0] & 0x10)
456     {
457         uint16_t extlen;
458
459         offset += 4;
460         if (len < offset)
461             return EINVAL;
462
463         memcpy (&extlen, buf + offset - 2, 2);
464         offset += htons (extlen); // skips RTP extension header
465     }
466
467     if (len < offset)
468         return EINVAL;
469
470     /* Determines RTP 48-bits counter and SSRC */
471     uint16_t seq = rtp_seq (buf);
472     uint32_t roc = srtp_compute_roc (s, seq), ssrc;
473     memcpy (&ssrc, buf + 8, 4);
474
475     /* Updates ROC and sequence (it's safe now) */
476     int16_t diff = seq - s->rtp_seq;
477     if (diff > 0)
478     {
479         /* Sequence in the future, good */
480         s->rtp.window = s->rtp.window << diff;
481         s->rtp.window |= 1;
482         s->rtp_seq = seq, s->rtp_roc = roc;
483     }
484     else
485     {
486         /* Sequence in the past/present, bad */
487         diff = -diff;
488         if ((diff >= 64) || ((s->rtp.window >> diff) & 1))
489             return EACCES; /* Replay attack */
490         s->rtp.window |= 1 << diff;
491     }
492
493     /* Encrypt/Decrypt */
494     if (s->flags & SRTP_UNENCRYPTED)
495         return 0;
496
497     if (rtp_crypt (s->rtp.cipher, ssrc, roc, seq, s->rtp.salt,
498                    buf + offset, len - offset))
499         return EINVAL;
500
501     return 0;
502 }
503
504
505 /**
506  * Turns a RTP packet into a SRTP packet: encrypt it, then computes
507  * the authentication tag and appends it.
508  * Note that you can encrypt packet in disorder.
509  *
510  * @param buf RTP packet to be encrypted/digested
511  * @param lenp pointer to the RTP packet length on entry,
512  *             set to the SRTP length on exit (undefined in case of error)
513  * @param bufsize size (bytes) of the packet buffer
514  *
515  * @return 0 on success, in case of error:
516  *  EINVAL  malformatted RTP packet or internal error
517  *  ENOSPC  bufsize is too small (to add authentication tag)
518  *  EACCES  packet would trigger a replay error on receiver
519  */
520 int
521 srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
522 {
523     size_t len = *lenp;
524     int val = srtp_crypt (s, buf, len);
525     if (val)
526         return val;
527
528     if (!(s->flags & SRTP_UNAUTHENTICATED))
529     {
530         if (bufsize < (len + s->tag_len))
531             return ENOSPC;
532
533         const uint8_t *tag = rtp_digest (s, buf, len);
534         memcpy (buf + len, tag, s->tag_len);
535         *lenp = len + s->tag_len;
536     }
537
538     return 0;
539 }
540
541
542 /**
543  * Turns a SRTP packet into a RTP packet: authenticates the packet,
544  * then decrypts it.
545  *
546  * @param buf RTP packet to be digested/decrypted
547  * @param lenp pointer to the SRTP packet length on entry,
548  *             set to the RTP length on exit (undefined in case of error)
549  *
550  * @return 0 on success, in case of error:
551  *  EINVAL  malformatted SRTP packet
552  *  EACCES  authentication failed (spoofed packet or out-of-sync)
553  */
554 int
555 srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
556 {
557     size_t len = *lenp;
558
559     if (!(s->flags & SRTP_UNAUTHENTICATED))
560     {
561         if (len < (12u + s->tag_len))
562             return EINVAL;
563         len -= s->tag_len;
564
565         const uint8_t *tag = rtp_digest (s, buf, len);
566         if (memcmp (buf + len, tag, s->tag_len))
567             return EACCES;
568
569         *lenp = len;
570     }
571
572     return srtp_crypt (s, buf, len);
573 }
574
575
576 /** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
577 static int
578 rtcp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t index,
579             const uint32_t *salt, uint8_t *data, size_t len)
580 {
581     return rtp_crypt (hd, ssrc, index >> 16, index & 0xffff, salt, data, len);
582 }
583
584
585 /** Message Authentication and Integrity for RTCP */
586 static const uint8_t *
587 rtcp_digest (gcry_md_hd_t md, const void *data, size_t len)
588 {
589     gcry_md_reset (md);
590     gcry_md_write (md, data, len);
591     return gcry_md_read (md, 0);
592 }
593
594
595 /**
596  * Encrypts/decrypts a RTCP packet and updates SRTCP context
597  * (CTR block cypher mode of operation has identical encryption and
598  * decryption function).
599  *
600  * @param buf RTCP packet to be en-/decrypted
601  * @param len RTCP packet length
602  *
603  * @return 0 on success, in case of error:
604  *  EINVAL  malformatted RTCP packet
605  */
606 static int srtcp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
607 {
608     assert (s != NULL);
609
610     /* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
611     if ((len < 12) || ((buf[0] >> 6) != 2))
612         return EINVAL;
613
614     uint32_t index;
615     memcpy (&index, buf + len, 4);
616     index = ntohl (index);
617     if (((index >> 31) != 0) != ((s->flags & SRTCP_UNENCRYPTED) == 0))
618         return EINVAL; // E-bit mismatch
619
620     index &= ~(1 << 31); // clear E-bit for counter
621
622     /* Updates SRTCP index (safe here) */
623     int32_t diff = index - s->rtcp_index;
624     if (diff > 0)
625     {
626         /* Packet in the future, good */
627         s->rtcp.window = s->rtcp.window << diff;
628         s->rtcp.window |= 1;
629         s->rtcp_index = index;
630     }
631     else
632     {
633         /* Packet in the past/present, bad */
634         diff = -diff;
635         if ((diff >= 64) || ((s->rtcp.window >> diff) & 1))
636             return EACCES; // replay attack!
637         s->rtp.window |= 1 << diff;
638     }
639
640     /* Crypts SRTCP */
641     if (s->flags & SRTCP_UNENCRYPTED)
642         return 0;
643
644     uint32_t ssrc;
645     memcpy (&ssrc, buf + 4, 4);
646
647     if (rtcp_crypt (s->rtcp.cipher, ssrc, index, s->rtp.salt,
648                     buf + 8, len - 8))
649         return EINVAL;
650     return 0;
651 }
652
653
654 /**
655  * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
656  * the authentication tag and appends it.
657  *
658  * @param buf RTCP packet to be encrypted/digested
659  * @param lenp pointer to the RTCP packet length on entry,
660  *             set to the SRTCP length on exit (undefined in case of error)
661  * @param bufsize size (bytes) of the packet buffer
662  *
663  * @return 0 on success, in case of error:
664  *  EINVAL  malformatted RTCP packet or internal error
665  *  ENOSPC  bufsize is too small (to add index and authentication tag)
666  */
667 int
668 srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
669 {
670     size_t len = *lenp;
671     if (bufsize < (len + 4 + s->tag_len))
672         return ENOSPC;
673
674     uint32_t index = ++s->rtcp_index;
675     if (index >> 31)
676         s->rtcp_index = index = 0; /* 31-bit wrap */
677
678     if ((s->flags & SRTCP_UNENCRYPTED) == 0)
679         index |= 0x80000000; /* Set Encrypted bit */
680     memcpy (buf + len, &(uint32_t){ htonl (index) }, 4);
681
682     int val = srtcp_crypt (s, buf, len);
683     if (val)
684         return val;
685
686     len += 4; /* Digests SRTCP index too */
687
688     const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
689     memcpy (buf + len, tag, s->tag_len);
690     *lenp = len + s->tag_len;
691     return 0;
692 }
693
694
695 /**
696  * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
697  * then decrypts it.
698  *
699  * @param buf RTCP packet to be digested/decrypted
700  * @param lenp pointer to the SRTCP packet length on entry,
701  *             set to the RTCP length on exit (undefined in case of error)
702  *
703  * @return 0 on success, in case of error:
704  *  EINVAL  malformatted SRTCP packet
705  *  EACCES  authentication failed (spoofed packet or out-of-sync)
706  */
707 int
708 srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
709 {
710     size_t len = *lenp;
711
712     if (len < (4u + s->tag_len))
713         return EINVAL;
714     len -= s->tag_len;
715
716     const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
717     if (memcmp (buf + len, tag, s->tag_len))
718          return EACCES;
719
720     len -= 4; /* Remove SRTCP index before decryption */
721     *lenp = len;
722     return srtp_crypt (s, buf, len);
723 }
724