]> git.sesse.net Git - vlc/blob - libs/srtp/srtp.c
877e324275d002d0bb6bfbbf7711f90279c8e5d6
[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  * - replay protection
42  *
43  * Useless stuff (because nothing depends on it):
44  * - non-nul key derivation rate
45  * - MKI payload
46  */
47
48 typedef struct srtp_proto_t
49 {
50     gcry_cipher_hd_t cipher;
51     gcry_md_hd_t     mac;
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 winsize anti-replay windows size (between 64 and 32767 inclusive)
165  *                0 disable replay attack protection (OK for send only)
166  * @param flags OR'ed optional flags.
167  *
168  * @return NULL in case of error
169  */
170 srtp_session_t *
171 srtp_create (const char *name, unsigned flags, unsigned kdr, uint16_t winsize)
172 {
173     assert (name != NULL);
174
175     if (kdr != 0)
176         return NULL; // FIXME: KDR not implemented yet
177     if (winsize != 0)
178         return NULL; // FIXME: replay protection not implemented yet
179
180     uint8_t tag_len;
181     int cipher = GCRY_CIPHER_AES, md = GCRY_MD_SHA1;
182
183     if (strcmp (name, "AES_CM_128_HMAC_SHA1_80") == 0)
184         tag_len = 10;
185     else
186     if (strcmp (name, "AES_CM_128_HMAC_SHA1_32") == 0)
187         tag_len = 4;
188     else
189     // F8_128_HMAC_SHA1_80 is not implemented
190         return NULL;
191
192     if ((flags & ~SRTP_FLAGS_MASK) || (winsize > 32767) || init_libgcrypt ())
193         return NULL;
194
195     srtp_session_t *s = malloc (sizeof (*s));
196     if (s == NULL)
197         return NULL;
198
199     memset (s, 0, sizeof (*s));
200     s->flags = flags;
201     s->kdr = kdr;
202     s->tag_len = tag_len;
203
204     if (proto_create (&s->rtp, cipher, md) == 0)
205     {
206         if (proto_create (&s->rtcp, cipher, md) == 0)
207             return s;
208         proto_destroy (&s->rtp);
209     }
210
211     free (s);
212     return NULL;
213 }
214
215
216 /**
217  * AES-CM key derivation (saltlen = 14 bytes)
218  */
219 static int
220 derive (gcry_cipher_hd_t prf, const void *salt,
221         const uint8_t *r, size_t rlen, uint8_t label,
222         void *out, size_t outlen)
223 {
224     uint8_t iv[16];
225
226     memcpy (iv, salt, 14);
227     iv[14] = iv[15] = 0;
228
229     assert (rlen < 14);
230     iv[13 - rlen] ^= label;
231     for (size_t i = 0; i < rlen; i++)
232         iv[sizeof (iv) - rlen + i] ^= r[i];
233
234     /* TODO: retry with CTR mode */
235     while (outlen >= sizeof (iv))
236     {
237         /* AES */
238         if (gcry_cipher_encrypt (prf, out, sizeof (iv), iv, sizeof (iv)))
239             return EINVAL;
240         outlen -= sizeof (iv);
241         out = ((uint8_t *)out) + sizeof (iv);
242
243         /* Increment IV in network byte order */
244         if (++iv[sizeof (iv) - 1] == 0)
245             ++iv[sizeof (iv) -2];
246     }
247
248     if (outlen > 0)
249     {
250         /* Truncated last AES output block */
251         if (gcry_cipher_encrypt (prf, iv, sizeof (iv), NULL, 0))
252             return -1;
253         memcpy (out, iv, outlen);
254     }
255
256     return 0;
257 }
258
259
260 static int
261 proto_derive (srtp_proto_t *p, gcry_cipher_hd_t prf,
262               const void *salt, size_t saltlen,
263               const uint8_t *r, size_t rlen, bool rtcp)
264 {
265     if (saltlen != 14)
266         return -1;
267
268     uint8_t keybuf[20];
269     uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT;
270
271     if (derive (prf, salt, r, rlen, label++, keybuf, 16)
272      || gcry_cipher_setkey (p->cipher, keybuf, 16)
273      || derive (prf, salt, r, rlen, label++, keybuf, 20)
274      || gcry_md_setkey (p->mac, keybuf, 20)
275      || derive (prf, salt, r, rlen, label, p->salt, 14))
276         return -1;
277
278     return 0;
279 }
280
281
282 /**
283  * SRTP/SRTCP cipher/salt/MAC keys derivation.
284  */
285 static int
286 srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
287              const void *salt, size_t saltlen)
288 {
289     gcry_cipher_hd_t prf;
290     uint8_t r[6];
291
292     /* TODO: retry with CTR mode */
293     if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0)
294      || gcry_cipher_setkey (prf, key, keylen))
295         return -1;
296
297     /* RTP key derivation */
298     if (s->kdr != 0)
299     {
300         uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
301         index /= s->kdr;
302
303         for (int i = sizeof (r) - 1; i >= 0; i--)
304         {
305             r[i] = index & 0xff;
306             index = index >> 8;
307         }
308     }
309     else
310         memset (r, 0, sizeof (r));
311
312     if (proto_derive (&s->rtp, prf, salt, saltlen, r, 6, false))
313         return -1;
314
315     /* RTCP key derivation */
316     memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
317     if (proto_derive (&s->rtcp, prf, salt, saltlen, r, 4, true))
318         return -1;
319
320     (void)gcry_cipher_close (prf);
321     return 0;
322 }
323
324
325 /**
326  * Sets (or resets) the master key and master salt for a SRTP session.
327  * This must be done at least once before using rtp_send(), rtp_recv(),
328  * rtcp_send() or rtcp_recv(). Also, rekeying is required every
329  * 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
330  * otherwise the protocol security might be broken.
331  *
332  * @return 0 on success, in case of error:
333  *  EINVAL  invalid or unsupported key/salt sizes combination
334  */
335 int
336 srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
337              const void *salt, size_t saltlen)
338 {
339     return srtp_derive (s, key, keylen, salt, saltlen) ? EINVAL : 0;
340 }
341
342
343 /** AES-CM encryption/decryption (ctr length = 16 bytes) */
344 static int
345 ctr_crypt (gcry_cipher_hd_t hd, uint32_t *ctr, uint8_t *data, size_t len)
346 {
347     const size_t ctrlen = 16;
348     while (len >= ctrlen)
349     {
350         if (gcry_cipher_setctr (hd, ctr, ctrlen)
351          || gcry_cipher_encrypt (hd, data, ctrlen, NULL, 0))
352             return -1;
353
354         data += ctrlen;
355         len -= ctrlen;
356         ctr[3] = htonl (ntohl (ctr[3]) + 1);
357     }
358
359     if (len > 0)
360     {
361         /* Truncated last block */
362         uint8_t dummy[ctrlen];
363         memcpy (dummy, data, len);
364         memset (dummy + len, 0, ctrlen - len);
365
366         if (gcry_cipher_setctr (hd, ctr, ctrlen)
367          || gcry_cipher_encrypt (hd, dummy, ctrlen, data, ctrlen))
368             return -1;
369         memcpy (data, dummy, len);
370     }
371
372     return 0;
373 }
374
375
376 /** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
377 static int
378 rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
379            const uint32_t *salt, uint8_t *data, size_t len)
380 {
381     /* Determines cryptographic counter (IV) */
382     uint32_t counter[4];
383     counter[0] = salt[0];
384     counter[1] = salt[1] ^ ssrc;
385     counter[2] = salt[2] ^ htonl (roc);
386     counter[3] = salt[3] ^ htonl (seq << 16);
387
388     /* Encryption */
389     return ctr_crypt (hd, counter, data, len);
390 }
391
392
393 /** Message Authentication and Integrity for RTP */
394 static const uint8_t *
395 rtp_digest (gcry_md_hd_t md, const void *data, size_t len, uint32_t roc)
396 {
397     gcry_md_reset (md);
398     gcry_md_write (md, data, len);
399     gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4);
400     return gcry_md_read (md, 0);
401 }
402
403
404 /**
405  * Encrypts/decrypts a RTP packet and updates SRTP context
406  * (CTR block cypher mode of operation has identical encryption and
407  * decryption function).
408  *
409  * @param buf RTP packet to be en-/decrypted
410  * @param len RTP packet length
411  *
412  * @return 0 on success, in case of error:
413  *  EINVAL  malformatted RTP packet
414  */
415 static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
416 {
417     assert (s != NULL);
418
419     if ((len < 12) || ((buf[0] >> 6) != 2))
420         return EINVAL;
421
422     /* Computes encryption offset */
423     uint16_t offset = 12;
424     offset += (buf[0] & 0xf) * 4; // skips CSRC
425
426     if (buf[0] & 0x10)
427     {
428         uint16_t extlen;
429
430         offset += 4;
431         if (len < offset)
432             return EINVAL;
433
434         memcpy (&extlen, buf + offset - 2, 2);
435         offset += htons (extlen); // skips RTP extension header
436     }
437
438     if (len < offset)
439         return EINVAL;
440
441     /* Determines RTP 48-bits counter and SSRC */
442     uint32_t ssrc;
443     memcpy (&ssrc, buf + 8, 4);
444
445     uint16_t seq = (buf[2] << 8) | buf[3];
446     if (((seq - s->rtp_seq) & 0xffff) < 32768)
447     {
448         if (seq < s->rtp_seq)
449             s->rtp_roc++; /* Sequence number wrap */
450     }
451     else
452     {
453         if (seq > s->rtp_seq)
454             s->rtp_roc--;
455     }
456
457     s->rtp_seq = seq;
458
459     if (s->flags & SRTP_UNENCRYPTED)
460         return 0;
461
462     if (rtp_crypt (s->rtp.cipher, ssrc, s->rtp_roc, seq, s->rtp.salt,
463                    buf + offset, len - offset))
464         return EINVAL;
465
466     return 0;
467 }
468
469
470 /**
471  * Turns a RTP packet into a SRTP packet: encrypt it, then computes
472  * the authentication tag and appends it.
473  * Note that you can encrypt packet in disorder.
474  *
475  * @param buf RTP packet to be encrypted/digested
476  * @param lenp pointer to the RTP packet length on entry,
477  *             set to the SRTP length on exit (undefined in case of error)
478  * @param bufsize size (bytes) of the packet buffer
479  *
480  * @return 0 on success, in case of error:
481  *  EINVAL  malformatted RTP packet or internal error
482  *  ENOSPC  bufsize is too small (to add authentication tag)
483  */
484 int
485 srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
486 {
487     size_t len = *lenp;
488     int val = srtp_crypt (s, buf, len);
489     if (val)
490         return val;
491
492     if (s->flags & SRTP_UNAUTHENTICATED)
493         return 0;
494
495     if (bufsize < (len + s->tag_len))
496         return ENOSPC;
497
498     const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, s->rtp_roc);
499     memcpy (buf + len, tag, s->tag_len);
500     *lenp = len + s->tag_len;
501
502     return 0;
503 }
504
505
506 /**
507  * Turns a SRTP packet into a RTP packet: authenticates the packet,
508  * then decrypts it.
509  *
510  * @param buf RTP packet to be digested/decrypted
511  * @param lenp pointer to the SRTP packet length on entry,
512  *             set to the RTP length on exit (undefined in case of error)
513  *
514  * @return 0 on success, in case of error:
515  *  EINVAL  malformatted SRTP packet
516  *  EACCES  authentication failed (spoofed packet or out-of-sync)
517  */
518 int
519 srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
520 {
521     size_t len = *lenp;
522     /* FIXME: anti-replay */
523
524     if (!(s->flags & SRTP_UNAUTHENTICATED))
525     {
526         if (len < s->tag_len)
527             return EINVAL;
528         len -= s->tag_len;
529
530         const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, s->rtp_roc);
531         if (memcmp (buf + len, tag, s->tag_len))
532             return EACCES;
533
534         *lenp = len;
535     }
536
537     return srtp_crypt (s, buf, len);
538 }
539
540
541 /** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
542 static int
543 rtcp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t index,
544             const uint32_t *salt, uint8_t *data, size_t len)
545 {
546     return rtp_crypt (hd, ssrc, index >> 16, index & 0xffff, salt, data, len);
547 }
548
549
550 /** Message Authentication and Integrity for RTCP */
551 static const uint8_t *
552 rtcp_digest (gcry_md_hd_t md, const void *data, size_t len)
553 {
554     gcry_md_reset (md);
555     gcry_md_write (md, data, len);
556     return gcry_md_read (md, 0);
557 }
558
559
560 /**
561  * Encrypts/decrypts a RTCP packet and updates SRTCP context
562  * (CTR block cypher mode of operation has identical encryption and
563  * decryption function).
564  *
565  * @param buf RTCP packet to be en-/decrypted
566  * @param len RTCP packet length
567  *
568  * @return 0 on success, in case of error:
569  *  EINVAL  malformatted RTCP packet
570  */
571 static int srtcp_crypt (srtp_session_t *s, uint8_t *buf, size_t len)
572 {
573     assert (s != NULL);
574
575     /* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
576     if ((len < 12) || ((buf[0] >> 6) != 2))
577         return EINVAL;
578
579     uint32_t index = s->rtcp_index++;
580     if (index == 0x7fffffff)
581         s->rtcp_index = 0; /* 31-bit wrap */
582
583     if (s->flags & SRTCP_UNENCRYPTED)
584         return 0;
585
586     uint32_t ssrc;
587     memcpy (&ssrc, buf + 4, 4);
588
589     if (rtcp_crypt (s->rtcp.cipher, ssrc, index, s->rtp.salt,
590                     buf + 8, len - 8))
591         return EINVAL;
592     return 0;
593 }
594
595
596 /**
597  * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
598  * the authentication tag and appends it.
599  *
600  * @param buf RTCP packet to be encrypted/digested
601  * @param lenp pointer to the RTCP packet length on entry,
602  *             set to the SRTCP length on exit (undefined in case of error)
603  * @param bufsize size (bytes) of the packet buffer
604  *
605  * @return 0 on success, in case of error:
606  *  EINVAL  malformatted RTCP packet or internal error
607  *  ENOSPC  bufsize is too small (to add index and authentication tag)
608  */
609 int
610 srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
611 {
612     size_t len = *lenp;
613     if (bufsize < (len + 4 + s->tag_len))
614         return ENOSPC;
615
616     uint32_t index = s->rtcp_index;
617     if ((s->flags & SRTCP_UNENCRYPTED) == 0)
618         index |= 0x80000000; /* Set Encrypted bit */
619     memcpy (buf + len, &(uint32_t){ htonl (index) }, 4);
620
621     int val = srtcp_crypt (s, buf, len);
622     if (val)
623         return val;
624
625     len += 4; /* Digest SRTCP index too */
626
627     const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
628     memcpy (buf + len, tag, s->tag_len);
629     *lenp = len + s->tag_len;
630     return 0;
631 }
632
633
634 /**
635  * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
636  * then decrypts it.
637  *
638  * @param buf RTCP packet to be digested/decrypted
639  * @param lenp pointer to the SRTCP packet length on entry,
640  *             set to the RTCP length on exit (undefined in case of error)
641  *
642  * @return 0 on success, in case of error:
643  *  EINVAL  malformatted SRTCP packet
644  *  EACCES  authentication failed (spoofed packet or out-of-sync)
645  */
646 int
647 srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
648 {
649     size_t len = *lenp;
650     /* FIXME: anti-replay ?? */
651
652     if (len < (4u + s->tag_len))
653         return EINVAL;
654     len -= s->tag_len;
655
656     const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
657     if (memcmp (buf + len, tag, s->tag_len))
658          return EACCES;
659
660     len -= 4; /* Remove SRTCP index befor decryption */
661     *lenp = len;
662
663     return srtp_crypt (s, buf, len);
664 }
665