2 * Secure RTP with libgcrypt
3 * Copyright (C) 2007 RĂ©mi Denis-Courmont
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.
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.
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
21 * Useless stuff (because nothing depends on it):
22 * - non-nul key derivation rate
43 # include <winsock2.h>
45 # include <netinet/in.h>
48 #define debug( ... ) (void)0
50 typedef struct srtp_proto_t
52 gcry_cipher_hd_t cipher
;
82 static inline unsigned rcc_mode (const srtp_session_t
*s
)
84 return (s
->flags
>> 4) & 3;
88 static void proto_destroy (srtp_proto_t
*p
)
90 gcry_md_close (p
->mac
);
91 gcry_cipher_close (p
->cipher
);
96 * Releases all resources associated with a Secure RTP session.
98 void srtp_destroy (srtp_session_t
*s
)
102 proto_destroy (&s
->rtcp
);
103 proto_destroy (&s
->rtp
);
108 static int proto_create (srtp_proto_t
*p
, int gcipher
, int gmd
)
110 if (gcry_cipher_open (&p
->cipher
, gcipher
, GCRY_CIPHER_MODE_CTR
, 0) == 0)
112 if (gcry_md_open (&p
->mac
, gmd
, GCRY_MD_FLAG_HMAC
) == 0)
114 gcry_cipher_close (p
->cipher
);
121 * Allocates a Secure RTP one-way session.
122 * The same session cannot be used both ways because this would confuse
123 * internal cryptographic counters; it is however of course feasible to open
124 * multiple simultaneous sessions with the same master key.
126 * @param encr encryption algorithm number
127 * @param auth authentication algortihm number
128 * @param tag_len authentication tag byte length (NOT including RCC)
129 * @param flags OR'ed optional flags.
131 * @return NULL in case of error
134 srtp_create (int encr
, int auth
, unsigned tag_len
, int prf
, unsigned flags
)
136 if ((flags
& ~SRTP_FLAGS_MASK
))
143 cipher
= GCRY_CIPHER_NONE
;
146 case SRTP_ENCR_AES_CM
:
147 cipher
= GCRY_CIPHER_AES
;
160 case SRTP_AUTH_HMAC_SHA1
:
168 if (tag_len
> gcry_md_get_algo_dlen (md
))
171 if (prf
!= SRTP_PRF_AES_CM
)
174 srtp_session_t
*s
= malloc (sizeof (*s
));
178 memset (s
, 0, sizeof (*s
));
180 s
->tag_len
= tag_len
;
181 s
->rtp_rcc
= 1; /* Default RCC rate */
188 if (proto_create (&s
->rtp
, cipher
, md
) == 0)
190 if (proto_create (&s
->rtcp
, cipher
, md
) == 0)
192 proto_destroy (&s
->rtp
);
202 * Counter Mode encryption/decryption (ctr length = 16 bytes)
203 * with non-padded (truncated) text
206 do_ctr_crypt (gcry_cipher_hd_t hd
, const void *ctr
, uint8_t *data
, size_t len
)
208 const size_t ctrlen
= 16;
209 div_t d
= div (len
, ctrlen
);
211 if (gcry_cipher_setctr (hd
, ctr
, ctrlen
)
212 || gcry_cipher_encrypt (hd
, data
, d
.quot
* ctrlen
, NULL
, 0))
217 /* Truncated last block */
218 uint8_t dummy
[ctrlen
];
219 data
+= d
.quot
* ctrlen
;
220 memcpy (dummy
, data
, d
.rem
);
221 memset (dummy
+ d
.rem
, 0, ctrlen
- d
.rem
);
223 if (gcry_cipher_encrypt (hd
, dummy
, ctrlen
, data
, ctrlen
))
225 memcpy (data
, dummy
, d
.rem
);
233 * AES-CM key derivation (saltlen = 14 bytes)
236 do_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
)
242 memcpy (iv
, salt
, 14);
246 iv
[13 - rlen
] ^= label
;
247 for (size_t i
= 0; i
< rlen
; i
++)
248 iv
[sizeof (iv
) - rlen
+ i
] ^= r
[i
];
250 memset (out
, 0, outlen
);
251 return do_ctr_crypt (prf
, iv
, out
, outlen
);
256 * Sets (or resets) the master key and master salt for a SRTP session.
257 * This must be done at least once before using srtp_send(), srtp_recv(),
258 * srtcp_send() or srtcp_recv(). Also, rekeying is required every
259 * 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
260 * otherwise the protocol security might be broken.
262 * @return 0 on success, in case of error:
263 * EINVAL invalid or unsupported key/salt sizes combination
266 srtp_setkey (srtp_session_t
*s
, const void *key
, size_t keylen
,
267 const void *salt
, size_t saltlen
)
269 /* SRTP/SRTCP cipher/salt/MAC keys derivation */
270 gcry_cipher_hd_t prf
;
271 uint8_t r
[6], keybuf
[20];
276 if (gcry_cipher_open (&prf
, GCRY_CIPHER_AES
, GCRY_CIPHER_MODE_CTR
, 0)
277 || gcry_cipher_setkey (prf
, key
, keylen
))
280 /* SRTP key derivation */
284 uint64_t index
= (((uint64_t)s
->rtp_roc
) << 16) | s
->rtp_seq
;
287 for (int i
= sizeof (r
) - 1; i
>= 0; i
--)
295 memset (r
, 0, sizeof (r
));
296 if (do_derive (prf
, salt
, r
, 6, SRTP_CRYPT
, keybuf
, 16)
297 || gcry_cipher_setkey (s
->rtp
.cipher
, keybuf
, 16)
298 || do_derive (prf
, salt
, r
, 6, SRTP_AUTH
, keybuf
, 20)
299 || gcry_md_setkey (s
->rtp
.mac
, keybuf
, 20)
300 || do_derive (prf
, salt
, r
, 6, SRTP_SALT
, s
->rtp
.salt
, 14))
303 /* SRTCP key derivation */
304 memcpy (r
, &(uint32_t){ htonl (s
->rtcp_index
) }, 4);
305 if (do_derive (prf
, salt
, r
, 4, SRTCP_CRYPT
, keybuf
, 16)
306 || gcry_cipher_setkey (s
->rtcp
.cipher
, keybuf
, 16)
307 || do_derive (prf
, salt
, r
, 4, SRTCP_AUTH
, keybuf
, 20)
308 || gcry_md_setkey (s
->rtcp
.mac
, keybuf
, 20)
309 || do_derive (prf
, salt
, r
, 4, SRTCP_SALT
, s
->rtcp
.salt
, 14))
312 (void)gcry_cipher_close (prf
);
316 static int hexdigit (char c
)
318 if ((c
>= '0') && (c
<= '9'))
320 if ((c
>= 'A') && (c
<= 'F'))
321 return c
- 'A' + 0xA;
322 if ((c
>= 'a') && (c
<= 'f'))
323 return c
- 'a' + 0xa;
327 static ssize_t
hexstring (const char *in
, uint8_t *out
, size_t outlen
)
329 size_t inlen
= strlen (in
);
331 if ((inlen
> (2 * outlen
)) || (inlen
& 1))
334 for (size_t i
= 0; i
< inlen
; i
+= 2)
336 int a
= hexdigit (in
[i
]), b
= hexdigit (in
[i
+ 1]);
337 if ((a
== -1) || (b
== -1))
339 out
[i
/ 2] = (a
<< 4) | b
;
345 * Sets (or resets) the master key and master salt for a SRTP session
346 * from hexadecimal strings. See also srtp_setkey().
348 * @return 0 on success, in case of error:
349 * EINVAL invalid or unsupported key/salt sizes combination
352 srtp_setkeystring (srtp_session_t
*s
, const char *key
, const char *salt
)
354 uint8_t bkey
[16]; /* TODO/NOTE: hard-coded for AES */
355 uint8_t bsalt
[14]; /* TODO/NOTE: hard-coded for the PRF-AES-CM */
356 ssize_t bkeylen
= hexstring (key
, bkey
, sizeof (bkey
));
357 ssize_t bsaltlen
= hexstring (salt
, bsalt
, sizeof (bsalt
));
359 if ((bkeylen
== -1) || (bsaltlen
== -1))
361 return srtp_setkey (s
, bkey
, bkeylen
, bsalt
, bsaltlen
) ? EINVAL
: 0;
365 * Sets Roll-over-Counter Carry (RCC) rate for the SRTP session. If not
366 * specified (through this function), the default rate of ONE is assumed
367 * (i.e. every RTP packets will carry the RoC). RCC rate is ignored if none
368 * of the RCC mode has been selected.
370 * The RCC mode is selected through one of these flags for srtp_create():
371 * SRTP_RCC_MODE1: integrity protection only for RoC carrying packets
372 * SRTP_RCC_MODE2: integrity protection for all packets
373 * SRTP_RCC_MODE3: no integrity protection
375 * RCC mode 3 is insecure. Compared to plain RTP, it provides confidentiality
376 * (through encryption) but is much more prone to DoS. It can only be used if
377 * anti-spoofing protection is provided by lower network layers (e.g. IPsec,
378 * or trusted routers and proper source address filtering).
380 * If RCC rate is 1, RCC mode 1 and 2 are functionally identical.
382 * @param rate RoC Carry rate (MUST NOT be zero)
384 void srtp_setrcc_rate (srtp_session_t
*s
, uint16_t rate
)
391 /** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */
393 rtp_crypt (gcry_cipher_hd_t hd
, uint32_t ssrc
, uint32_t roc
, uint16_t seq
,
394 const uint32_t *salt
, uint8_t *data
, size_t len
)
396 /* Determines cryptographic counter (IV) */
398 counter
[0] = salt
[0];
399 counter
[1] = salt
[1] ^ ssrc
;
400 counter
[2] = salt
[2] ^ htonl (roc
);
401 counter
[3] = salt
[3] ^ htonl (seq
<< 16);
404 return do_ctr_crypt (hd
, counter
, data
, len
);
408 /** Determines SRTP Roll-Over-Counter (in host-byte order) */
410 srtp_compute_roc (const srtp_session_t
*s
, uint16_t seq
)
412 uint32_t roc
= s
->rtp_roc
;
414 if (((seq
- s
->rtp_seq
) & 0xffff) < 0x8000)
416 /* Sequence is ahead, good */
417 if (seq
< s
->rtp_seq
)
418 roc
++; /* Sequence number wrap */
422 /* Sequence is late, bad */
423 if (seq
> s
->rtp_seq
)
424 roc
--; /* Wrap back */
430 /** Returns RTP sequence (in host-byte order) */
431 static inline uint16_t rtp_seq (const uint8_t *buf
)
433 return (buf
[2] << 8) | buf
[3];
437 /** Message Authentication and Integrity for RTP */
438 static const uint8_t *
439 rtp_digest (gcry_md_hd_t md
, const uint8_t *data
, size_t len
,
443 gcry_md_write (md
, data
, len
);
444 gcry_md_write (md
, &(uint32_t){ htonl (roc
) }, 4);
445 return gcry_md_read (md
, 0);
450 * Encrypts/decrypts a RTP packet and updates SRTP context
451 * (CTR block cypher mode of operation has identical encryption and
452 * decryption function).
454 * @param buf RTP packet to be en-/decrypted
455 * @param len RTP packet length
457 * @return 0 on success, in case of error:
458 * EINVAL malformatted RTP packet
459 * EACCES replayed packet or out-of-window or sync lost
461 static int srtp_crypt (srtp_session_t
*s
, uint8_t *buf
, size_t len
)
466 if ((buf
[0] >> 6) != 2)
469 /* Computes encryption offset */
470 uint16_t offset
= 12;
471 offset
+= (buf
[0] & 0xf) * 4; // skips CSRC
481 memcpy (&extlen
, buf
+ offset
- 2, 2);
482 offset
+= htons (extlen
); // skips RTP extension header
488 /* Determines RTP 48-bits counter and SSRC */
489 uint16_t seq
= rtp_seq (buf
);
490 uint32_t roc
= srtp_compute_roc (s
, seq
), ssrc
;
491 memcpy (&ssrc
, buf
+ 8, 4);
493 /* Updates ROC and sequence (it's safe now) */
494 int16_t diff
= seq
- s
->rtp_seq
;
497 /* Sequence in the future, good */
498 s
->rtp
.window
= s
->rtp
.window
<< diff
;
499 s
->rtp
.window
|= UINT64_C(1);
500 s
->rtp_seq
= seq
, s
->rtp_roc
= roc
;
504 /* Sequence in the past/present, bad */
506 if ((diff
>= 64) || ((s
->rtp
.window
>> diff
) & 1))
507 return EACCES
; /* Replay attack */
508 s
->rtp
.window
|= UINT64_C(1) << diff
;
511 /* Encrypt/Decrypt */
512 if (s
->flags
& SRTP_UNENCRYPTED
)
515 if (rtp_crypt (s
->rtp
.cipher
, ssrc
, roc
, seq
, s
->rtp
.salt
,
516 buf
+ offset
, len
- offset
))
524 * Turns a RTP packet into a SRTP packet: encrypt it, then computes
525 * the authentication tag and appends it.
526 * Note that you can encrypt packet in disorder.
528 * @param buf RTP packet to be encrypted/digested
529 * @param lenp pointer to the RTP packet length on entry,
530 * set to the SRTP length on exit (undefined on non-ENOSPC error)
531 * @param bufsize size (bytes) of the packet buffer
533 * @return 0 on success, in case of error:
534 * EINVAL malformatted RTP packet or internal error
535 * ENOSPC bufsize is too small to add authentication tag
536 * (<lenp> will hold the required byte size)
537 * EACCES packet would trigger a replay error on receiver
540 srtp_send (srtp_session_t
*s
, uint8_t *buf
, size_t *lenp
, size_t bufsize
)
546 /* Compute required buffer size */
550 if (!(s
->flags
& SRTP_UNAUTHENTICATED
))
552 tag_len
= s
->tag_len
;
556 assert (tag_len
>= 4);
557 assert (s
->rtp_rcc
!= 0);
558 if ((rtp_seq (buf
) % s
->rtp_rcc
) == 0)
561 if (rcc_mode (s
) == 3)
562 tag_len
= 0; /* RCC mode 3 -> no auth*/
564 tag_len
-= 4; /* RCC mode 1 or 2 -> auth*/
568 if (rcc_mode (s
) & 1)
569 tag_len
= 0; /* RCC mode 1 or 3 -> no auth */
573 *lenp
= len
+ roc_len
+ tag_len
;
581 /* Encrypt payload */
582 int val
= srtp_crypt (s
, buf
, len
);
586 /* Authenticate payload */
587 if (!(s
->flags
& SRTP_UNAUTHENTICATED
))
589 uint32_t roc
= srtp_compute_roc (s
, rtp_seq (buf
));
590 const uint8_t *tag
= rtp_digest (s
->rtp
.mac
, buf
, len
, roc
);
594 memcpy (buf
+ len
, &(uint32_t){ htonl (s
->rtp_roc
) }, 4);
597 memcpy (buf
+ len
, tag
, tag_len
);
599 printf ("Sent : 0x");
600 for (unsigned i
= 0; i
< tag_len
; i
++)
601 printf ("%02x", tag
[i
]);
611 * Turns a SRTP packet into a RTP packet: authenticates the packet,
614 * @param buf RTP packet to be digested/decrypted
615 * @param lenp pointer to the SRTP packet length on entry,
616 * set to the RTP length on exit (undefined in case of error)
618 * @return 0 on success, in case of error:
619 * EINVAL malformatted SRTP packet
620 * EACCES authentication failed (spoofed packet or out-of-sync)
623 srtp_recv (srtp_session_t
*s
, uint8_t *buf
, size_t *lenp
)
629 if (!(s
->flags
& SRTP_UNAUTHENTICATED
))
631 size_t tag_len
= s
->tag_len
, roc_len
= 0;
634 if ((rtp_seq (buf
) % s
->rtp_rcc
) == 0)
637 if (rcc_mode (s
) == 3)
644 if (rcc_mode (s
) & 1)
645 tag_len
= 0; // RCC mode 1 or 3: no auth
649 if (len
< (12u + roc_len
+ tag_len
))
651 len
-= roc_len
+ tag_len
;
653 uint32_t roc
= srtp_compute_roc (s
, rtp_seq (buf
)), rcc
;
656 assert (roc_len
== 4);
657 memcpy (&rcc
, buf
+ len
, 4);
663 const uint8_t *tag
= rtp_digest (s
->rtp
.mac
, buf
, len
, rcc
);
665 printf ("Computed: 0x");
666 for (unsigned i
= 0; i
< tag_len
; i
++)
667 printf ("%02x", tag
[i
]);
668 printf ("\nReceived: 0x");
669 for (unsigned i
= 0; i
< tag_len
; i
++)
670 printf ("%02x", buf
[len
+ roc_len
+ i
]);
673 if (memcmp (buf
+ len
+ roc_len
, tag
, tag_len
))
678 /* Authenticated packet carried a Roll-Over-Counter */
679 s
->rtp_roc
+= rcc
- roc
;
680 assert (srtp_compute_roc (s
, rtp_seq (buf
)) == rcc
);
685 return srtp_crypt (s
, buf
, len
);
689 /** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */
691 rtcp_crypt (gcry_cipher_hd_t hd
, uint32_t ssrc
, uint32_t index
,
692 const uint32_t *salt
, uint8_t *data
, size_t len
)
694 return rtp_crypt (hd
, ssrc
, index
>> 16, index
& 0xffff, salt
, data
, len
);
698 /** Message Authentication and Integrity for RTCP */
699 static const uint8_t *
700 rtcp_digest (gcry_md_hd_t md
, const void *data
, size_t len
)
703 gcry_md_write (md
, data
, len
);
704 return gcry_md_read (md
, 0);
709 * Encrypts/decrypts a RTCP packet and updates SRTCP context
710 * (CTR block cypher mode of operation has identical encryption and
711 * decryption function).
713 * @param buf RTCP packet to be en-/decrypted
714 * @param len RTCP packet length
716 * @return 0 on success, in case of error:
717 * EINVAL malformatted RTCP packet
719 static int srtcp_crypt (srtp_session_t
*s
, uint8_t *buf
, size_t len
)
723 /* 8-bytes unencrypted header, and 4-bytes unencrypted footer */
724 if ((len
< 12) || ((buf
[0] >> 6) != 2))
728 memcpy (&index
, buf
+ len
, 4);
729 index
= ntohl (index
);
730 if (((index
>> 31) != 0) != ((s
->flags
& SRTCP_UNENCRYPTED
) == 0))
731 return EINVAL
; // E-bit mismatch
733 index
&= ~(1 << 31); // clear E-bit for counter
735 /* Updates SRTCP index (safe here) */
736 int32_t diff
= index
- s
->rtcp_index
;
739 /* Packet in the future, good */
740 s
->rtcp
.window
= s
->rtcp
.window
<< diff
;
741 s
->rtcp
.window
|= UINT64_C(1);
742 s
->rtcp_index
= index
;
746 /* Packet in the past/present, bad */
748 if ((diff
>= 64) || ((s
->rtcp
.window
>> diff
) & 1))
749 return EACCES
; // replay attack!
750 s
->rtp
.window
|= UINT64_C(1) << diff
;
754 if (s
->flags
& SRTCP_UNENCRYPTED
)
758 memcpy (&ssrc
, buf
+ 4, 4);
760 if (rtcp_crypt (s
->rtcp
.cipher
, ssrc
, index
, s
->rtp
.salt
,
768 * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
769 * the authentication tag and appends it.
771 * @param buf RTCP packet to be encrypted/digested
772 * @param lenp pointer to the RTCP packet length on entry,
773 * set to the SRTCP length on exit (undefined in case of error)
774 * @param bufsize size (bytes) of the packet buffer
776 * @return 0 on success, in case of error:
777 * EINVAL malformatted RTCP packet or internal error
778 * ENOSPC bufsize is too small (to add index and authentication tag)
781 srtcp_send (srtp_session_t
*s
, uint8_t *buf
, size_t *lenp
, size_t bufsize
)
784 if (bufsize
< (len
+ 4 + s
->tag_len
))
787 uint32_t index
= ++s
->rtcp_index
;
789 s
->rtcp_index
= index
= 0; /* 31-bit wrap */
791 if ((s
->flags
& SRTCP_UNENCRYPTED
) == 0)
792 index
|= 0x80000000; /* Set Encrypted bit */
793 memcpy (buf
+ len
, &(uint32_t){ htonl (index
) }, 4);
795 int val
= srtcp_crypt (s
, buf
, len
);
799 len
+= 4; /* Digests SRTCP index too */
801 const uint8_t *tag
= rtcp_digest (s
->rtcp
.mac
, buf
, len
);
802 memcpy (buf
+ len
, tag
, s
->tag_len
);
803 *lenp
= len
+ s
->tag_len
;
809 * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
812 * @param buf RTCP packet to be digested/decrypted
813 * @param lenp pointer to the SRTCP packet length on entry,
814 * set to the RTCP length on exit (undefined in case of error)
816 * @return 0 on success, in case of error:
817 * EINVAL malformatted SRTCP packet
818 * EACCES authentication failed (spoofed packet or out-of-sync)
821 srtcp_recv (srtp_session_t
*s
, uint8_t *buf
, size_t *lenp
)
825 if (len
< (4u + s
->tag_len
))
829 const uint8_t *tag
= rtcp_digest (s
->rtcp
.mac
, buf
, len
);
830 if (memcmp (buf
+ len
, tag
, s
->tag_len
))
833 len
-= 4; /* Remove SRTCP index before decryption */
835 return srtp_crypt (s
, buf
, len
);