Changeset e5c071abd8c79d19f3f6e19f626540e241c36849

Show
Ignore:
Timestamp:
03/10/07 19:06:47 (1 year ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1173550007 +0000
git-parent:

[62e11e95946388cc8d9ae585c5737ef7ad1e67b5]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1173550007 +0000
Message:

SRTCP support

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • libs/srtp/srtp.c

    reb7428c re5c071a  
    3838/* TODO: 
    3939 * Useful stuff: 
    40  * - ROC profil thingy (multicast really needs this) 
     40 * - ROC profile thingy (multicast really needs this) 
    4141 * - replay protection 
    42  * 
    43  * Requirements for conformance: 
    44  * - suites with NULL cipher 
    45  * - SRTCP 
    4642 * 
    4743 * Useless stuff (because nothing depends on it): 
     
    159155 
    160156/** 
    161  * Allocates a Secure RTP session. 
     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. 
    162161 * 
    163162 * @param name cipher-suite name 
     
    258257} 
    259258 
    260 #include <stdio.h> 
    261259 
    262260static int 
     
    268266        return -1; 
    269267 
    270     uint32_t cipherkey[4], authkey[5]; 
     268    uint8_t keybuf[20]; 
    271269    uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT; 
    272270 
    273     if (derive (prf, salt, r, rlen, label++, cipherkey, 16) 
    274      || gcry_cipher_setkey (p->cipher, cipherkey, 16) 
    275      || derive (prf, salt, r, rlen, label++, authkey, 20) 
    276      || gcry_md_setkey (p->mac, authkey, 20) 
    277      || derive (prf, salt, r, rlen, label++, p->salt, 14)) 
     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)) 
    278276        return -1; 
    279  
    280     debug (" cipher key: %08x%08x%08x%08x\n auth key: %08x%08x%08x%08x%08x\n", 
    281             ntohl (cipherkey[0]), ntohl (cipherkey[1]), ntohl (cipherkey[2]), 
    282             ntohl (cipherkey[3]), ntohl (authkey[0]), ntohl (authkey[1]), 
    283             ntohl (authkey[2]), ntohl (authkey[3]), ntohl (authkey[4])); 
    284277 
    285278    return 0; 
     
    330323 
    331324 
    332  
    333325/** 
    334326 * Sets (or resets) the master key and master salt for a SRTP session. 
     
    351343/** AES-CM encryption/decryption (ctr length = 16 bytes) */ 
    352344static int 
    353 encrypt (gcry_cipher_hd_t hd, uint32_t *ctr, uint8_t *data, size_t len) 
     345ctr_crypt (gcry_cipher_hd_t hd, uint32_t *ctr, uint8_t *data, size_t len) 
    354346{ 
    355347    const size_t ctrlen = 16; 
     
    383375 
    384376/** AES-CM for RTP (salt = 14 bytes + 2 nul bytes) */ 
    385 static inline in
    386 rtp_encrypt (gcry_cipher_hd_t hd, uint32_t ssrc, uint32_t roc, uint16_t seq, 
    387              const uint32_t *salt, uint8_t *data, size_t len) 
     377static in
     378rtp_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) 
    388380{ 
    389381    /* Determines cryptographic counter (IV) */ 
     
    395387 
    396388    /* Encryption */ 
    397     return encrypt (hd, counter, data, len); 
     389    return ctr_crypt (hd, counter, data, len); 
    398390} 
    399391 
     
    415407 * decryption function). 
    416408 * 
    417  * @param buf RTP packet to be encrypted/digested 
     409 * @param buf RTP packet to be en-/decrypted 
    418410 * @param len RTP packet length 
    419411 * 
     
    468460        return 0; 
    469461 
    470     if (rtp_encrypt (s->rtp.cipher, ssrc, s->rtp_roc, seq, s->rtp.salt, 
    471                      buf + offset, len - offset)) 
     462    if (rtp_crypt (s->rtp.cipher, ssrc, s->rtp_roc, seq, s->rtp.salt, 
     463                   buf + offset, len - offset)) 
    472464        return EINVAL; 
    473465 
     
    517509 * 
    518510 * @param buf RTP packet to be digested/decrypted 
    519  * @param lenp pointer to the RTP packet length on entry, 
    520  *             set to the SRTP length on exit (undefined in case of error) 
     511 * @param lenp pointer to the SRTP packet length on entry, 
     512 *             set to the RTP length on exit (undefined in case of error) 
    521513 * 
    522514 * @return 0 on success, in case of error: 
     
    528520{ 
    529521    size_t len = *lenp; 
     522    /* FIXME: anti-replay */ 
    530523 
    531524    if (!(s->flags & SRTP_UNAUTHENTICATED)) 
     
    534527            return EINVAL; 
    535528        len -= s->tag_len; 
    536         *lenp = len; 
    537529 
    538530        const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, s->rtp_roc); 
    539         debug  (" Auth tag: %08x%08x%04x (wanted)\n" 
    540                 " Auth tag: %08x%08x%04x (recv'd)\n", 
    541                 ntohl (((uint32_t *)tag)[0]), ntohl (((uint32_t *)tag)[1]), 
    542                 ntohs (((uint16_t *)tag)[4]), 
    543                 ntohl (((uint32_t *)w)[0]), ntohl (((uint32_t *)w)[1]), 
    544                 ntohs (((uint16_t *)w)[4])); 
    545531        if (memcmp (buf + len, tag, s->tag_len)) 
    546532            return EACCES; 
    547     } 
    548  
    549     /* FIXME: anti-replay */ 
     533 
     534        *lenp = len; 
     535    } 
    550536 
    551537    return srtp_crypt (s, buf, len); 
    552538} 
    553539 
     540 
     541/** AES-CM for RTCP (salt = 14 bytes + 2 nul bytes) */ 
     542static int 
     543rtcp_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 */ 
     551static const uint8_t * 
     552rtcp_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 */ 
     571static 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 */ 
     609int 
     610srtcp_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 */ 
     646int 
     647srtcp_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 
  • libs/srtp/srtp.h

    r10ee356 re5c071a  
    4040                             uint16_t winsize); 
    4141void srtp_destroy (srtp_session_t *s); 
     42int srtp_setkey (srtp_session_t *s, const void *key, size_t keylen, 
     43                 const void *salt, size_t saltlen); 
     44 
    4245int srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t maxsize); 
    4346int srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp); 
     47int srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t maxsiz); 
     48int srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp); 
    4449 
    45 int srtp_setkey (srtp_session_t *s, const void *key, size_t keylen, 
    46                  const void *salt, size_t saltlen); 
    4750# ifdef __cplusplus 
    4851} 
  • libs/srtp/test-aes.c

    r10ee356 re5c071a  
    118118        fatal ("Cipher key error"); 
    119119 
    120     if (rtp_encrypt (hd, 0, 0, 0, salt, buf, 0xff020)) 
     120    if (rtp_crypt (hd, 0, 0, 0, salt, buf, 0xff020)) 
    121121        fatal ("Encryption failure"); 
    122122    gcry_cipher_close (hd);