Commit ad28a7f3 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

SRTP: refactor

Signed-off-by: default avatarRémi Denis-Courmont <remi@remlab.net>
parent 52495d74
...@@ -203,7 +203,7 @@ error: ...@@ -203,7 +203,7 @@ error:
* with non-padded (truncated) text * with non-padded (truncated) text
*/ */
static int static int
ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len) do_ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len)
{ {
const size_t ctrlen = 16; const size_t ctrlen = 16;
div_t d = div (len, ctrlen); div_t d = div (len, ctrlen);
...@@ -233,9 +233,9 @@ ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len) ...@@ -233,9 +233,9 @@ ctr_crypt (gcry_cipher_hd_t hd, const void *ctr, uint8_t *data, size_t len)
* AES-CM key derivation (saltlen = 14 bytes) * AES-CM key derivation (saltlen = 14 bytes)
*/ */
static int static int
derive (gcry_cipher_hd_t prf, const void *salt, do_derive (gcry_cipher_hd_t prf, const void *salt,
const uint8_t *r, size_t rlen, uint8_t label, const uint8_t *r, size_t rlen, uint8_t label,
void *out, size_t outlen) void *out, size_t outlen)
{ {
uint8_t iv[16]; uint8_t iv[16];
...@@ -248,48 +248,37 @@ derive (gcry_cipher_hd_t prf, const void *salt, ...@@ -248,48 +248,37 @@ derive (gcry_cipher_hd_t prf, const void *salt,
iv[sizeof (iv) - rlen + i] ^= r[i]; iv[sizeof (iv) - rlen + i] ^= r[i];
memset (out, 0, outlen); memset (out, 0, outlen);
return ctr_crypt (prf, iv, out, outlen); return do_ctr_crypt (prf, iv, out, outlen);
}
static int
proto_derive (srtp_proto_t *p, gcry_cipher_hd_t prf,
const void *salt, size_t saltlen,
const uint8_t *r, size_t rlen, bool rtcp)
{
if (saltlen != 14)
return -1;
uint8_t keybuf[20];
uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT;
if (derive (prf, salt, r, rlen, label++, keybuf, 16)
|| gcry_cipher_setkey (p->cipher, keybuf, 16)
|| derive (prf, salt, r, rlen, label++, keybuf, 20)
|| gcry_md_setkey (p->mac, keybuf, 20)
|| derive (prf, salt, r, rlen, label, p->salt, 14))
return -1;
return 0;
} }
/** /**
* SRTP/SRTCP cipher/salt/MAC keys derivation. * Sets (or resets) the master key and master salt for a SRTP session.
* This must be done at least once before using srtp_send(), srtp_recv(),
* srtcp_send() or srtcp_recv(). Also, rekeying is required every
* 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
* otherwise the protocol security might be broken.
*
* @return 0 on success, in case of error:
* EINVAL invalid or unsupported key/salt sizes combination
*/ */
static int int
srtp_derive (srtp_session_t *s, const void *key, size_t keylen, srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
const void *salt, size_t saltlen) const void *salt, size_t saltlen)
{ {
/* SRTP/SRTCP cipher/salt/MAC keys derivation */
gcry_cipher_hd_t prf; gcry_cipher_hd_t prf;
uint8_t r[6]; uint8_t r[6], keybuf[20];
if (saltlen != 14)
return EINVAL;
if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0) if (gcry_cipher_open (&prf, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR, 0)
|| gcry_cipher_setkey (prf, key, keylen)) || gcry_cipher_setkey (prf, key, keylen))
return -1; return EINVAL;
/* SRTP key derivation */
#if 0 #if 0
/* RTP key derivation */
if (s->kdr != 0) if (s->kdr != 0)
{ {
uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq; uint64_t index = (((uint64_t)s->rtp_roc) << 16) | s->rtp_seq;
...@@ -304,37 +293,26 @@ srtp_derive (srtp_session_t *s, const void *key, size_t keylen, ...@@ -304,37 +293,26 @@ srtp_derive (srtp_session_t *s, const void *key, size_t keylen,
else else
#endif #endif
memset (r, 0, sizeof (r)); memset (r, 0, sizeof (r));
if (do_derive (prf, salt, r, 6, SRTP_CRYPT, keybuf, 16)
if (proto_derive (&s->rtp, prf, salt, saltlen, r, 6, false)) || gcry_cipher_setkey (s->rtp.cipher, keybuf, 16)
|| do_derive (prf, salt, r, 6, SRTP_AUTH, keybuf, 20)
|| gcry_md_setkey (s->rtp.mac, keybuf, 20)
|| do_derive (prf, salt, r, 6, SRTP_SALT, s->rtp.salt, 14))
return -1; return -1;
/* RTCP key derivation */ /* SRTCP key derivation */
memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4); memcpy (r, &(uint32_t){ htonl (s->rtcp_index) }, 4);
if (proto_derive (&s->rtcp, prf, salt, saltlen, r, 4, true)) if (do_derive (prf, salt, r, 4, SRTCP_CRYPT, keybuf, 16)
|| gcry_cipher_setkey (s->rtcp.cipher, keybuf, 16)
|| do_derive (prf, salt, r, 4, SRTCP_AUTH, keybuf, 20)
|| gcry_md_setkey (s->rtcp.mac, keybuf, 20)
|| do_derive (prf, salt, r, 4, SRTCP_SALT, s->rtcp.salt, 14))
return -1; return -1;
(void)gcry_cipher_close (prf); (void)gcry_cipher_close (prf);
return 0; return 0;
} }
/**
* Sets (or resets) the master key and master salt for a SRTP session.
* This must be done at least once before using rtp_send(), rtp_recv(),
* rtcp_send() or rtcp_recv(). Also, rekeying is required every
* 2^48 RTP packets or 2^31 RTCP packets (whichever comes first),
* otherwise the protocol security might be broken.
*
* @return 0 on success, in case of error:
* EINVAL invalid or unsupported key/salt sizes combination
*/
int
srtp_setkey (srtp_session_t *s, const void *key, size_t keylen,
const void *salt, size_t saltlen)
{
return srtp_derive (s, key, keylen, salt, saltlen) ? EINVAL : 0;
}
static int hexdigit (char c) static int hexdigit (char c)
{ {
if ((c >= '0') && (c <= '9')) if ((c >= '0') && (c <= '9'))
...@@ -423,7 +401,7 @@ rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq, ...@@ -423,7 +401,7 @@ rtp_crypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq,
counter[3] = salt[3] ^ htonl (seq << 16); counter[3] = salt[3] ^ htonl (seq << 16);
/* Encryption */ /* Encryption */
return ctr_crypt (hd, counter, data, len); return do_ctr_crypt (hd, counter, data, len);
} }
...@@ -458,11 +436,9 @@ static inline uint16_t rtp_seq (const uint8_t *buf) ...@@ -458,11 +436,9 @@ static inline uint16_t rtp_seq (const uint8_t *buf)
/** Message Authentication and Integrity for RTP */ /** Message Authentication and Integrity for RTP */
static const uint8_t * static const uint8_t *
rtp_digest (srtp_session_t *s, const uint8_t *data, size_t len, rtp_digest (gcry_md_hd_t md, const uint8_t *data, size_t len,
uint32_t roc) uint32_t roc)
{ {
const gcry_md_hd_t md = s->rtp.mac;
gcry_md_reset (md); gcry_md_reset (md);
gcry_md_write (md, data, len); gcry_md_write (md, data, len);
gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4); gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4);
...@@ -579,7 +555,7 @@ srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize) ...@@ -579,7 +555,7 @@ srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
if (!(s->flags & SRTP_UNAUTHENTICATED)) if (!(s->flags & SRTP_UNAUTHENTICATED))
{ {
uint32_t roc = srtp_compute_roc (s, rtp_seq (buf)); uint32_t roc = srtp_compute_roc (s, rtp_seq (buf));
const uint8_t *tag = rtp_digest (s, buf, len, roc); const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, roc);
if (rcc_mode (s)) if (rcc_mode (s))
{ {
assert (s->rtp_rcc); assert (s->rtp_rcc);
...@@ -664,7 +640,7 @@ srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp) ...@@ -664,7 +640,7 @@ srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
else else
rcc = roc; rcc = roc;
const uint8_t *tag = rtp_digest (s, buf, len, rcc); const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, rcc);
#if 0 #if 0
printf ("Computed: 0x"); printf ("Computed: 0x");
for (unsigned i = 0; i < tag_len; i++) for (unsigned i = 0; i < tag_len; i++)
......
...@@ -67,21 +67,21 @@ static void test_derivation (void) ...@@ -67,21 +67,21 @@ static void test_derivation (void)
|| gcry_cipher_setkey (prf, key, sizeof (key))) || gcry_cipher_setkey (prf, key, sizeof (key)))
fatal ("Internal PRF error"); fatal ("Internal PRF error");
if (derive (prf, salt, r, sizeof (r), SRTP_CRYPT, out, 16)) if (do_derive (prf, salt, r, sizeof (r), SRTP_CRYPT, out, 16))
fatal ("Internal cipher derivation error"); fatal ("Internal cipher derivation error");
printf (" cipher key: "); printf (" cipher key: ");
printhex (out, 16); printhex (out, 16);
if (memcmp (out, good_cipher, 16)) if (memcmp (out, good_cipher, 16))
fatal ("Test failed"); fatal ("Test failed");
if (derive (prf, salt, r, sizeof (r), SRTP_SALT, out, 14)) if (do_derive (prf, salt, r, sizeof (r), SRTP_SALT, out, 14))
fatal ("Internal salt derivation error"); fatal ("Internal salt derivation error");
printf (" cipher salt: "); printf (" cipher salt: ");
printhex (out, 14); printhex (out, 14);
if (memcmp (out, good_salt, 14)) if (memcmp (out, good_salt, 14))
fatal ("Test failed"); fatal ("Test failed");
if (derive (prf, salt, r, sizeof (r), SRTP_AUTH, out, 94)) if (do_derive (prf, salt, r, sizeof (r), SRTP_AUTH, out, 94))
fatal ("Internal auth key derivation error"); fatal ("Internal auth key derivation error");
printf (" auth key: "); printf (" auth key: ");
printhex (out, 94); printhex (out, 94);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment