LCOV - code coverage report
Current view: top level - src/media - srtp.c (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 76.3 % 232 177
Test Date: 2026-09-13 09:08:58 Functions: 100.0 % 11 11

            Line data    Source code
       1              : /*
       2              :  * SRTP encryption/decryption
       3              :  * Copyright (c) 2012 Martin Storsjo
       4              :  *
       5              :  * This file is part of Libav.
       6              :  *
       7              :  * Libav is free software; you can redistribute it and/or
       8              :  * modify it under the terms of the GNU Lesser General Public
       9              :  * License as published by the Free Software Foundation; either
      10              :  * version 2.1 of the License, or (at your option) any later version.
      11              :  *
      12              :  * Libav is distributed in the hope that it will be useful,
      13              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              :  * Lesser General Public License for more details.
      16              :  *
      17              :  * You should have received a copy of the GNU Lesser General Public
      18              :  * License along with Libav; if not, write to the Free Software
      19              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20              :  */
      21              : 
      22              : #include <assert.h>
      23              : #include <libavutil/common.h>
      24              : #include <libavutil/base64.h>
      25              : #include <libavutil/aes.h>
      26              : #include <libavutil/hmac.h>
      27              : #include <libavutil/intreadwrite.h>
      28              : #include <libavutil/log.h>
      29              : #include <stddef.h>
      30              : #include "srtp.h"
      31              : 
      32              : #include "connectivity/security/memory.h"
      33              : 
      34              : struct SRTPCryptoSuite {
      35              :     const char *name;
      36              :     int master_key_size;
      37              :     int master_salt_size;
      38              :     int session_key_size;
      39              :     int rtp_hmac_size;
      40              :     int rtcp_hmac_size;
      41              : };
      42              : 
      43              : static const struct SRTPCryptoSuite ff_srtp_suites[] = {
      44              :     {"AES_CM_128_HMAC_SHA1_80", 16, SRTP_MASTER_SALT_SIZE, 16, 10, 10},
      45              :     {"SRTP_AES128_CM_HMAC_SHA1_80", 16, SRTP_MASTER_SALT_SIZE, 16, 10, 10},
      46              :     {"AES_CM_128_HMAC_SHA1_32", 16, SRTP_MASTER_SALT_SIZE, 16, 4, 10},
      47              :     {"SRTP_AES128_CM_HMAC_SHA1_32", 16, SRTP_MASTER_SALT_SIZE, 16, 4, 10},
      48              :     {"AES_256_CM_HMAC_SHA1_80", 32, SRTP_MASTER_SALT_SIZE, 32, 10, 10},
      49              :     {"AES_256_CM_HMAC_SHA1_32", 32, SRTP_MASTER_SALT_SIZE, 32, 4, 10},
      50              : };
      51              : 
      52              : static const struct SRTPCryptoSuite*
      53          707 : ff_srtp_get_suite(const char *suite)
      54              : {
      55              :     size_t i;
      56              : 
      57          707 :     for (i = 0; i < FF_ARRAY_ELEMS(ff_srtp_suites); ++i)
      58          707 :         if (!strcmp(suite, ff_srtp_suites[i].name))
      59          707 :             return &ff_srtp_suites[i];
      60              : 
      61            0 :     return NULL;
      62              : }
      63              : 
      64              : static int
      65        12580 : ff_srtp_get_key_bits(int key_size)
      66              : {
      67        12580 :     return key_size > 0 ? key_size * 8 : 128;
      68              : }
      69              : 
      70         1760 : void ff_srtp_free(struct SRTPContext *s)
      71              : {
      72         1760 :     uint8_t zero_buffer[32] = {0}; // WARNING: must be long enough to handle any key length
      73              :     static_assert(sizeof(zero_buffer) >= sizeof(s->master_key), "");
      74              :     static_assert(sizeof(zero_buffer) >= sizeof(s->rtp_key), "");
      75              :     static_assert(sizeof(zero_buffer) >= sizeof(s->rtp_auth), "");
      76              : 
      77         1760 :     if (!s)
      78            0 :         return;
      79              :     // aes and hmac have an opaque pointer type.
      80              :     // No API to safely erase them, so just re-init with "dummy keys" to sanitize them
      81         1760 :     if (s->aes) {
      82          708 :         av_aes_init(s->aes, zero_buffer, ff_srtp_get_key_bits(s->session_key_size), 0);
      83          708 :         av_freep((void*)&s->aes);
      84              :     }
      85         1760 :     if (s->hmac) {
      86          708 :         av_hmac_init(s->hmac, zero_buffer, sizeof(s->rtp_auth));
      87          708 :         av_hmac_free(s->hmac);
      88              :     }
      89         1760 :     jami_secure_memzero(s, sizeof(*s));
      90              : }
      91              : 
      92        15401 : static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
      93              :                             int outlen)
      94              : {
      95              :     int i, j, outpos;
      96       163217 :     for (i = 0, outpos = 0; outpos < outlen; i++) {
      97              :         uint8_t keystream[16];
      98       147805 :         AV_WB16(&iv[14], i);
      99       147805 :         av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
     100      2352319 :         for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
     101      2204503 :             outbuf[outpos] ^= keystream[j];
     102              :     }
     103        15412 : }
     104              : 
     105         4237 : static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
     106              :                        uint8_t *out, int outlen)
     107              : {
     108         4237 :     uint8_t input[16] = { 0 };
     109         4237 :     memcpy(input, salt, 14);
     110              :     // Key derivation rate assumed to be zero
     111         4237 :     input[14 - 7] ^= label;
     112         4237 :     memset(out, 0, outlen);
     113         4237 :     encrypt_counter(aes, input, out, outlen);
     114         4245 : }
     115              : 
     116          708 : int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
     117              :                        const char *params)
     118              : {
     119              :     uint8_t buf[SRTP_MAX_MASTER_KEY_SIZE + SRTP_MASTER_SALT_SIZE];
     120              :     const struct SRTPCryptoSuite *suite_def;
     121              :     int expected_params_size;
     122              : 
     123          708 :     ff_srtp_free(s);
     124              : 
     125              :     // RFC 4568 and RFC 6188.
     126          707 :     suite_def = ff_srtp_get_suite(suite);
     127          707 :     if (!suite_def) {
     128            0 :         av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n",
     129              :                                      suite);
     130            0 :         return AVERROR(EINVAL);
     131              :     }
     132              : 
     133          707 :     s->rtp_hmac_size = suite_def->rtp_hmac_size;
     134          707 :     s->rtcp_hmac_size = suite_def->rtcp_hmac_size;
     135          707 :     s->master_key_size = suite_def->master_key_size;
     136          707 :     s->master_salt_size = suite_def->master_salt_size;
     137          707 :     s->session_key_size = suite_def->session_key_size;
     138              : 
     139          707 :     expected_params_size = s->master_key_size + s->master_salt_size;
     140          707 :     if (av_base64_decode(buf, params, sizeof(buf)) != expected_params_size) {
     141            0 :         av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n");
     142            0 :         jami_secure_memzero(buf, sizeof(buf));
     143            0 :         return AVERROR(EINVAL);
     144              :     }
     145              :     // MKI and lifetime not handled yet
     146          708 :     s->aes  = av_aes_alloc();
     147          708 :     s->hmac = av_hmac_alloc(AV_HMAC_SHA1);
     148          708 :     if (!s->aes || !s->hmac) {
     149            0 :         jami_secure_memzero(buf, sizeof(buf));
     150            0 :         ff_srtp_free(s);
     151            0 :         return AVERROR(ENOMEM);
     152              :     }
     153          708 :     memcpy(s->master_key, buf, s->master_key_size);
     154          708 :     memcpy(s->master_salt, buf + s->master_key_size, s->master_salt_size);
     155          708 :     jami_secure_memzero(buf, sizeof(buf));
     156              : 
     157              :     // RFC 3711 and RFC 6188.
     158          708 :     av_aes_init(s->aes, s->master_key, ff_srtp_get_key_bits(s->master_key_size), 0);
     159              : 
     160          708 :     derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, s->session_key_size);
     161          707 :     derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt));
     162          708 :     derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth));
     163              : 
     164          707 :     derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, s->session_key_size);
     165          708 :     derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt));
     166          708 :     derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth));
     167          708 :     return 0;
     168              : }
     169              : 
     170        11164 : static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index,
     171              :                       uint32_t ssrc)
     172              : {
     173              :     uint8_t indexbuf[8];
     174              :     int i;
     175        11164 :     memset(iv, 0, 16);
     176        11164 :     AV_WB32(&iv[4], ssrc);
     177        11164 :     AV_WB64(indexbuf, index);
     178       100476 :     for (i = 0; i < 8; i++) // index << 16
     179        89312 :         iv[6 + i] ^= indexbuf[i];
     180       167460 :     for (i = 0; i < 14; i++)
     181       156296 :         iv[i] ^= salt[i];
     182        11164 :     jami_secure_memzero(indexbuf, sizeof(indexbuf));
     183        11164 : }
     184              : 
     185              : /* RFC 3711 section 3.3.2: reject indexes already received or too old */
     186         5568 : static int replay_check(const struct SRTPReplayList *r, uint64_t index)
     187              : {
     188              :     uint64_t diff;
     189         5568 :     if (!r->initialized || index > r->highest)
     190         5568 :         return 1;
     191            0 :     diff = r->highest - index;
     192            0 :     if (diff >= SRTP_REPLAY_WINDOW_SIZE)
     193            0 :         return 0;
     194            0 :     return !(r->bitmap[diff / 64] & ((uint64_t)1 << (diff % 64)));
     195              : }
     196              : 
     197              : /* Only call once the packet is authenticated */
     198         5568 : static void replay_update(struct SRTPReplayList *r, uint64_t index)
     199              : {
     200              :     uint64_t diff;
     201              :     int i;
     202         5568 :     if (!r->initialized || index > r->highest) {
     203         5568 :         uint64_t shift = r->initialized ? index - r->highest : SRTP_REPLAY_WINDOW_SIZE;
     204         5568 :         if (shift >= SRTP_REPLAY_WINDOW_SIZE) {
     205           47 :             memset(r->bitmap, 0, sizeof(r->bitmap));
     206              :         } else {
     207              :             /* Slide the window up by `shift` bits */
     208        16563 :             for (i = SRTP_REPLAY_WINDOW_WORDS - 1; i >= 0; i--) {
     209        11042 :                 int from = i - (int)(shift / 64);
     210        11042 :                 uint64_t v = from >= 0 ? r->bitmap[from] << (shift % 64) : 0;
     211        11042 :                 if (shift % 64 && from - 1 >= 0)
     212         5521 :                     v |= r->bitmap[from - 1] >> (64 - shift % 64);
     213        11042 :                 r->bitmap[i] = v;
     214              :             }
     215              :         }
     216         5568 :         r->highest = index;
     217         5568 :         r->initialized = 1;
     218         5568 :         r->bitmap[0] |= 1;
     219         5568 :         return;
     220              :     }
     221            0 :     diff = r->highest - index;
     222            0 :     r->bitmap[diff / 64] |= (uint64_t)1 << (diff % 64);
     223              : }
     224              : 
     225         5568 : int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
     226              : {
     227         5568 :     uint8_t iv[16] = { 0 }, hmac[20];
     228         5568 :     int len = *lenptr;
     229         5568 :     int seq_largest = 0;
     230         5568 :     uint32_t ssrc, roc = 0;
     231         5568 :     uint64_t index = 0;
     232              :     int rtcp, hmac_size;
     233              :     struct SRTPReplayList *replay;
     234              : 
     235              :     /* Nothing is handed out unless the packet is fully authenticated */
     236         5568 :     *lenptr = 0;
     237              : 
     238         5568 :     if (len < 2)
     239            0 :         return AVERROR_INVALIDDATA;
     240              : 
     241         5568 :     rtcp = RTP_PT_IS_RTCP(buf[1]);
     242         5568 :     hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
     243         5568 :     replay = rtcp ? &s->rtcp_replay : &s->rtp_replay;
     244              : 
     245              :     /* Fixed header (+ SRTCP index) and authentication tag */
     246         5568 :     if (len < (rtcp ? 8 + 4 : 12) + hmac_size)
     247            0 :         return AVERROR_INVALIDDATA;
     248              : 
     249              :     // Authentication HMAC
     250         5568 :     av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
     251              :     // If MKI is used, this should exclude the MKI as well
     252         5568 :     av_hmac_update(s->hmac, buf, len - hmac_size);
     253              : 
     254         5568 :     if (!rtcp) {
     255         5568 :         int seq = AV_RB16(buf + 2);
     256              :         uint32_t v;
     257              :         uint8_t rocbuf[4];
     258              : 
     259              :         // RFC 3711 section 3.3.1, appendix A
     260         5568 :         seq_largest = s->seq_initialized ? s->seq_largest : seq;
     261         5568 :         v = roc = s->roc;
     262         5568 :         if (seq_largest < 32768) {
     263         5568 :             if (seq - seq_largest > 32768)
     264            0 :                 v = roc - 1;
     265              :         } else {
     266            0 :             if (seq_largest - 32768 > seq)
     267            0 :                 v = roc + 1;
     268              :         }
     269         5568 :         if (v == roc) {
     270         5568 :             seq_largest = FFMAX(seq_largest, seq);
     271            0 :         } else if (v == roc + 1) {
     272            0 :             seq_largest = seq;
     273            0 :             roc = v;
     274              :         }
     275         5568 :         index = seq + (((uint64_t)v) << 16);
     276              : 
     277         5568 :         AV_WB32(rocbuf, roc);
     278         5568 :         av_hmac_update(s->hmac, rocbuf, 4);
     279              :     } else {
     280            0 :         index = AV_RB32(buf + len - hmac_size - 4) & 0x7fffffff;
     281              :     }
     282              : 
     283         5568 :     if (!replay_check(replay, index)) {
     284            0 :         av_log(NULL, AV_LOG_DEBUG, "SRTP replayed packet\n");
     285            0 :         return AVERROR_INVALIDDATA;
     286              :     }
     287              : 
     288         5568 :     av_hmac_final(s->hmac, hmac, sizeof(hmac));
     289         5568 :     if (memcmp(hmac, buf + len - hmac_size, hmac_size)) {
     290            0 :         av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n");
     291            0 :         return AVERROR_INVALIDDATA;
     292              :     }
     293              : 
     294         5568 :     len -= hmac_size;
     295              : 
     296         5568 :     if (rtcp) {
     297            0 :         uint32_t srtcp_index = AV_RB32(buf + len - 4);
     298            0 :         len -= 4;
     299              : 
     300            0 :         ssrc = AV_RB32(buf + 4);
     301              : 
     302            0 :         buf += 8;
     303            0 :         len -= 8;
     304            0 :         replay_update(replay, index);
     305            0 :         *lenptr = len + 8;
     306            0 :         if (!(srtcp_index & 0x80000000))
     307            0 :             return 0;
     308              :     } else {
     309              :         int ext, csrc;
     310              :         int payload_start;
     311              : 
     312         5568 :         csrc = buf[0] & 0x0f;
     313         5568 :         ext  = buf[0] & 0x10;
     314         5568 :         ssrc = AV_RB32(buf + 8);
     315              : 
     316         5568 :         payload_start = 12 + 4 * csrc;
     317         5568 :         if (len < payload_start)
     318            0 :             return AVERROR_INVALIDDATA;
     319              : 
     320         5568 :         if (ext) {
     321         5568 :             if (len < payload_start + 4)
     322            0 :                 return AVERROR_INVALIDDATA;
     323         5568 :             ext = (AV_RB16(buf + payload_start + 2) + 1) * 4;
     324         5568 :             if (len < payload_start + ext)
     325            0 :                 return AVERROR_INVALIDDATA;
     326         5568 :             payload_start += ext;
     327              :         }
     328              : 
     329              :         /* Authenticated and well-formed: commit the receiver state */
     330         5568 :         s->seq_initialized = 1;
     331         5568 :         s->seq_largest     = seq_largest;
     332         5568 :         s->roc             = roc;
     333         5568 :         replay_update(replay, index);
     334         5568 :         *lenptr = len;
     335              : 
     336         5568 :         buf += payload_start;
     337         5568 :         len -= payload_start;
     338              :     }
     339              : 
     340         5568 :     create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
     341         5568 :     av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, ff_srtp_get_key_bits(s->session_key_size), 0);
     342         5568 :     encrypt_counter(s->aes, iv, buf, len);
     343              : 
     344         5568 :     return 0;
     345              : }
     346              : 
     347         5596 : int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
     348              :                     uint8_t *out, int outlen)
     349              : {
     350         5596 :     uint8_t iv[16] = { 0 }, hmac[20];
     351              :     uint64_t index;
     352              :     uint32_t ssrc;
     353              :     int rtcp, hmac_size, padding;
     354              :     uint8_t *buf;
     355              : 
     356         5596 :     if (len < 8)
     357            0 :         return AVERROR_INVALIDDATA;
     358              : 
     359         5596 :     rtcp = RTP_PT_IS_RTCP(in[1]);
     360         5596 :     hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
     361         5596 :     padding = hmac_size;
     362         5596 :     if (rtcp)
     363            0 :         padding += 4; // For the RTCP index
     364              : 
     365         5596 :     if (len + padding > outlen)
     366            0 :         return 0;
     367              : 
     368         5596 :     memcpy(out, in, len);
     369         5596 :     buf = out;
     370              : 
     371         5596 :     if (rtcp) {
     372            0 :         ssrc = AV_RB32(buf + 4);
     373            0 :         index = s->rtcp_index++;
     374              : 
     375            0 :         buf += 8;
     376            0 :         len -= 8;
     377              :     } else {
     378              :         int ext, csrc;
     379         5596 :         int seq = AV_RB16(buf + 2);
     380              : 
     381         5596 :         if (len < 12)
     382            0 :             return AVERROR_INVALIDDATA;
     383              : 
     384         5596 :         ssrc = AV_RB32(buf + 8);
     385              : 
     386         5596 :         if (seq < s->seq_largest)
     387            0 :             s->roc++;
     388         5596 :         s->seq_largest = seq;
     389         5596 :         index = seq + (((uint64_t)s->roc) << 16);
     390              : 
     391         5596 :         csrc = buf[0] & 0x0f;
     392         5596 :         ext = buf[0] & 0x10;
     393              : 
     394         5596 :         buf += 12;
     395         5596 :         len -= 12;
     396              : 
     397         5596 :         buf += (ptrdiff_t)4 * csrc;
     398         5596 :         len -= 4 * csrc;
     399         5596 :         if (len < 0)
     400            0 :             return AVERROR_INVALIDDATA;
     401              : 
     402         5596 :         if (ext) {
     403         5596 :             if (len < 4)
     404            0 :                 return AVERROR_INVALIDDATA;
     405         5596 :             ext = (AV_RB16(buf + 2) + 1) * 4;
     406         5596 :             if (len < ext)
     407            0 :                 return AVERROR_INVALIDDATA;
     408         5596 :             len -= ext;
     409         5596 :             buf += ext;
     410              :         }
     411              :     }
     412              : 
     413         5596 :     create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
     414         5596 :     av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, ff_srtp_get_key_bits(s->session_key_size), 0);
     415         5596 :     encrypt_counter(s->aes, iv, buf, len);
     416              : 
     417         5596 :     if (rtcp) {
     418            0 :         AV_WB32(buf + len, 0x80000000 | index);
     419            0 :         len += 4;
     420              :     }
     421              : 
     422         5596 :     av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
     423         5596 :     av_hmac_update(s->hmac, out, buf + len - out);
     424         5596 :     if (!rtcp) {
     425              :         uint8_t rocbuf[4];
     426         5596 :         AV_WB32(rocbuf, s->roc);
     427         5596 :         av_hmac_update(s->hmac, rocbuf, 4);
     428              :     }
     429         5596 :     av_hmac_final(s->hmac, hmac, sizeof(hmac));
     430              : 
     431         5596 :     memcpy(buf + len, hmac, hmac_size);
     432         5596 :     len += hmac_size;
     433         5596 :     return (int)(buf + len - out);
     434              : }
        

Generated by: LCOV version 2.0-1