Changeset eb7428c1d38b3b70af04184f4f0562a50db12931

Show
Ignore:
Timestamp:
10/03/07 17:28:20 (2 years ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1173544100 +0000
git-parent:

[fb8aac670cd81dded1ec61986934d04eb2f3bb5d]

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

RTP HMAC-SHA1 authentication

Files:

Legend:

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

    r22c5fe4 reb7428c  
    3434#include <gcrypt.h> 
    3535 
     36#define debug( ... ) (void)0 
     37 
    3638/* TODO: 
    3739 * Useful stuff: 
     
    5355    gcry_md_hd_t     mac; 
    5456    uint32_t         salt[4]; 
    55     uint8_t          mac_len; 
    5657} srtp_proto_t; 
    5758 
     
    6566    uint32_t rtp_roc; 
    6667    uint16_t rtp_seq; 
     68    uint8_t  tag_len; 
    6769}; 
    6870 
     
    177179        return NULL; // FIXME: replay protection not implemented yet 
    178180 
    179     uint8_t mac_len; 
     181    uint8_t tag_len; 
    180182    int cipher = GCRY_CIPHER_AES, md = GCRY_MD_SHA1; 
    181183 
    182184    if (strcmp (name, "AES_CM_128_HMAC_SHA1_80") == 0) 
    183         mac_len = 80; 
     185        tag_len = 10; 
    184186    else 
    185187    if (strcmp (name, "AES_CM_128_HMAC_SHA1_32") == 0) 
    186         mac_len = 32
     188        tag_len = 4
    187189    else 
    188190    // F8_128_HMAC_SHA1_80 is not implemented 
     
    199201    s->flags = flags; 
    200202    s->kdr = kdr; 
     203    s->tag_len = tag_len; 
    201204 
    202205    if (proto_create (&s->rtp, cipher, md) == 0) 
     
    255258} 
    256259 
     260#include <stdio.h> 
    257261 
    258262static int 
     
    264268        return -1; 
    265269 
    266     uint8_t cipherkey[16]; 
     270    uint32_t cipherkey[4], authkey[5]; 
    267271    uint8_t label = rtcp ? SRTCP_CRYPT : SRTP_CRYPT; 
    268272 
    269273    if (derive (prf, salt, r, rlen, label++, cipherkey, 16) 
    270274     || gcry_cipher_setkey (p->cipher, cipherkey, 16) 
    271      || derive (prf, salt, r, rlen, label++, NULL, 0) /* FIXME HMAC */ 
     275     || derive (prf, salt, r, rlen, label++, authkey, 20) 
     276     || gcry_md_setkey (p->mac, authkey, 20) 
    272277     || derive (prf, salt, r, rlen, label++, p->salt, 14)) 
    273278        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])); 
    274284 
    275285    return 0; 
     
    389399 
    390400 
     401/** Message Authentication and Integrity for RTP */ 
     402static const uint8_t * 
     403rtp_digest (gcry_md_hd_t md, const void *data, size_t len, uint32_t roc) 
     404{ 
     405    gcry_md_reset (md); 
     406    gcry_md_write (md, data, len); 
     407    gcry_md_write (md, &(uint32_t){ htonl (roc) }, 4); 
     408    return gcry_md_read (md, 0); 
     409} 
     410 
     411 
    391412/** 
    392413 * Encrypts/decrypts a RTP packet and updates SRTP context 
     
    400421 *  EINVAL  malformatted RTP packet 
    401422 */ 
    402 static int srtp_encrypt (srtp_session_t *s, uint8_t *buf, size_t len) 
     423static int srtp_crypt (srtp_session_t *s, uint8_t *buf, size_t len) 
    403424{ 
    404425    assert (s != NULL); 
     
    420441 
    421442        memcpy (&extlen, buf + offset - 2, 2); 
    422         offset += htons (extlen); 
     443        offset += htons (extlen); // skips RTP extension header 
    423444    } 
    424445 
     
    466487 * 
    467488 * @return 0 on success, in case of error: 
    468  *  EINVAL  malformatted RTP packet 
     489 *  EINVAL  malformatted RTP packet or internal error 
    469490 *  ENOSPC  bufsize is too small (to add authentication tag) 
    470491 */ 
     
    473494{ 
    474495    size_t len = *lenp; 
    475     int val = srtp_encrypt (s, buf, len); 
     496    int val = srtp_crypt (s, buf, len); 
    476497    if (val) 
    477498        return val; 
    478499 
    479     if (bufsize < (len + s->rtp.mac_len)) 
     500    if (s->flags & SRTP_UNAUTHENTICATED) 
     501        return 0; 
     502 
     503    if (bufsize < (len + s->tag_len)) 
    480504        return ENOSPC; 
    481505 
    482     /* FIXME: HMAC and anti-replay */ 
     506    const uint8_t *tag = rtp_digest (s->rtp.mac, buf, len, s->rtp_roc); 
     507    memcpy (buf + len, tag, s->tag_len); 
     508    *lenp = len + s->tag_len; 
     509 
    483510    return 0; 
    484511} 
     
    486513 
    487514/** 
    488  * Turns a RTP packet into a SRTP packet: encrypt it, then computes 
    489  * the authentication tag and appends it. 
    490  * Note that you can encrypt packet in disorder. 
    491  * 
    492  * @param buf RTP packet to be decrypted/digested 
     515 * Turns a SRTP packet into a RTP packet: authenticates the packet, 
     516 * then decrypts it. 
     517 * 
     518 * @param buf RTP packet to be digested/decrypted 
    493519 * @param lenp pointer to the RTP packet length on entry, 
    494520 *             set to the SRTP length on exit (undefined in case of error) 
    495521 * 
    496522 * @return 0 on success, in case of error: 
    497  *  EINVAL  malformatted RTP packet 
     523 *  EINVAL  malformatted SRTP packet 
    498524 *  EACCES  authentication failed (spoofed packet or out-of-sync) 
    499525 */ 
     
    502528{ 
    503529    size_t len = *lenp; 
    504     int val = srtp_encrypt (s, buf, len); 
    505     if (val) 
    506         return val; 
    507  
    508     /* FIXME: HMAC and anti-replay */ 
    509     return 0; 
    510 
    511  
     530 
     531    if (!(s->flags & SRTP_UNAUTHENTICATED)) 
     532    { 
     533        if (len < s->tag_len) 
     534            return EINVAL; 
     535        len -= s->tag_len; 
     536        *lenp = len; 
     537 
     538        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])); 
     545        if (memcmp (buf + len, tag, s->tag_len)) 
     546            return EACCES; 
     547    } 
     548 
     549    /* FIXME: anti-replay */ 
     550 
     551    return srtp_crypt (s, buf, len); 
     552
     553