LCOV - code coverage report
Current view: top level - src/media - srtp.c (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 74.4 % 195 145
Test Date: 2026-06-13 09:18:46 Functions: 100.0 % 7 7

            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         1584 : void ff_srtp_free(struct SRTPContext *s)
      35              : {
      36         1584 :     uint8_t zero_buffer[32] = {0}; // WARNING: must be long enough to handle any key length
      37              :     static_assert(sizeof(zero_buffer) >= sizeof(s->master_key), "");
      38              :     static_assert(sizeof(zero_buffer) >= sizeof(s->rtp_key), "");
      39              :     static_assert(sizeof(zero_buffer) >= sizeof(s->rtp_auth), "");
      40              : 
      41         1584 :     if (!s)
      42            0 :         return;
      43              :     // aes and hmac have an opaque pointer type.
      44              :     // No API to safely erase them, so just re-init with "dummy keys" to sanitize them
      45         1584 :     if (s->aes) {
      46          636 :         av_aes_init(s->aes, zero_buffer, 128, 0);
      47          636 :         av_freep((void*)&s->aes);
      48              :     }
      49         1584 :     if (s->hmac) {
      50          636 :         av_hmac_init(s->hmac, zero_buffer, sizeof(s->rtp_auth));
      51          636 :         av_hmac_free(s->hmac);
      52              :     }
      53         1584 :     jami_secure_memzero(s, sizeof(*s));
      54              : }
      55              : 
      56        15164 : static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
      57              :                             int outlen)
      58              : {
      59              :     int i, j, outpos;
      60       165476 :     for (i = 0, outpos = 0; outpos < outlen; i++) {
      61              :         uint8_t keystream[16];
      62       150300 :         AV_WB16(&iv[14], i);
      63       150300 :         av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
      64      2452729 :         for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
      65      2302417 :             outbuf[outpos] ^= keystream[j];
      66              :     }
      67        15176 : }
      68              : 
      69         3805 : static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
      70              :                        uint8_t *out, int outlen)
      71              : {
      72         3805 :     uint8_t input[16] = { 0 };
      73         3805 :     memcpy(input, salt, 14);
      74              :     // Key derivation rate assumed to be zero
      75         3805 :     input[14 - 7] ^= label;
      76         3805 :     memset(out, 0, outlen);
      77         3805 :     encrypt_counter(aes, input, out, outlen);
      78         3810 : }
      79              : 
      80          636 : int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
      81              :                        const char *params)
      82              : {
      83              :     uint8_t buf[30];
      84              : 
      85          636 :     ff_srtp_free(s);
      86              : 
      87              :     // RFC 4568
      88          636 :     if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80") ||
      89            0 :         !strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_80")) {
      90          636 :         s->rtp_hmac_size = s->rtcp_hmac_size = 10;
      91            0 :     } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
      92            0 :         s->rtp_hmac_size = s->rtcp_hmac_size = 4;
      93            0 :     } else if (!strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_32")) {
      94              :         // RFC 5764 section 4.1.2
      95            0 :         s->rtp_hmac_size  = 4;
      96            0 :         s->rtcp_hmac_size = 10;
      97              :     } else {
      98            0 :         av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n",
      99              :                                      suite);
     100            0 :         return AVERROR(EINVAL);
     101              :     }
     102          636 :     if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) {
     103            0 :         av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n");
     104            0 :         jami_secure_memzero(buf, sizeof(buf));
     105            0 :         return AVERROR(EINVAL);
     106              :     }
     107              :     // MKI and lifetime not handled yet
     108          636 :     s->aes  = av_aes_alloc();
     109          634 :     s->hmac = av_hmac_alloc(AV_HMAC_SHA1);
     110          636 :     if (!s->aes || !s->hmac)
     111            0 :         return AVERROR(ENOMEM);
     112          636 :     memcpy(s->master_key, buf, 16);
     113          636 :     memcpy(s->master_salt, buf + 16, 14);
     114          636 :     jami_secure_memzero(buf, sizeof(buf));
     115              : 
     116              :     // RFC 3711
     117          636 :     av_aes_init(s->aes, s->master_key, 128, 0);
     118              : 
     119          636 :     derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key));
     120          636 :     derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt));
     121          636 :     derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth));
     122              : 
     123          636 :     derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key));
     124          635 :     derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt));
     125          636 :     derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth));
     126          636 :     return 0;
     127              : }
     128              : 
     129        11359 : static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index,
     130              :                       uint32_t ssrc)
     131              : {
     132              :     uint8_t indexbuf[8];
     133              :     int i;
     134        11359 :     memset(iv, 0, 16);
     135        11359 :     AV_WB32(&iv[4], ssrc);
     136        11359 :     AV_WB64(indexbuf, index);
     137       102231 :     for (i = 0; i < 8; i++) // index << 16
     138        90872 :         iv[6 + i] ^= indexbuf[i];
     139       170385 :     for (i = 0; i < 14; i++)
     140       159026 :         iv[i] ^= salt[i];
     141        11359 :     jami_secure_memzero(indexbuf, sizeof(indexbuf));
     142        11359 : }
     143              : 
     144         5675 : int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
     145              : {
     146         5675 :     uint8_t iv[16] = { 0 }, hmac[20];
     147         5675 :     int len = *lenptr;
     148              : #ifdef _MSC_VER
     149              : #pragma message (__FILE__ "(" STR2(__LINE__) ") : -NOTE- " seq_largest and roc may be unitialized)
     150              : #else
     151              : #warning seq_largest and roc may be unitialized
     152              : #endif
     153         5675 :     int av_uninit(seq_largest);
     154         5675 :     uint32_t ssrc, av_uninit(roc);
     155              :     uint64_t index;
     156              :     int rtcp, hmac_size;
     157              : 
     158              :     // TODO: Missing replay protection
     159              : 
     160         5675 :     if (len < 2)
     161            0 :         return AVERROR_INVALIDDATA;
     162              : 
     163         5675 :     rtcp = RTP_PT_IS_RTCP(buf[1]);
     164         5675 :     hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
     165              : 
     166         5675 :     if (len < hmac_size)
     167            0 :         return AVERROR_INVALIDDATA;
     168              : 
     169              :     // Authentication HMAC
     170         5675 :     av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
     171              :     // If MKI is used, this should exclude the MKI as well
     172         5675 :     av_hmac_update(s->hmac, buf, len - hmac_size);
     173              : 
     174         5675 :     if (!rtcp) {
     175         5675 :         int seq = AV_RB16(buf + 2);
     176              :         uint32_t v;
     177              :         uint8_t rocbuf[4];
     178              : 
     179              :         // RFC 3711 section 3.3.1, appendix A
     180         5675 :         seq_largest = s->seq_initialized ? s->seq_largest : seq;
     181         5675 :         v = roc = s->roc;
     182         5675 :         if (seq_largest < 32768) {
     183         5675 :             if (seq - seq_largest > 32768)
     184            0 :                 v = roc - 1;
     185              :         } else {
     186            0 :             if (seq_largest - 32768 > seq)
     187            0 :                 v = roc + 1;
     188              :         }
     189         5675 :         if (v == roc) {
     190         5675 :             seq_largest = FFMAX(seq_largest, seq);
     191            0 :         } else if (v == roc + 1) {
     192            0 :             seq_largest = seq;
     193            0 :             roc = v;
     194              :         }
     195         5675 :         index = seq + (((uint64_t)v) << 16);
     196              : 
     197         5675 :         AV_WB32(rocbuf, roc);
     198         5675 :         av_hmac_update(s->hmac, rocbuf, 4);
     199              :     }
     200              : 
     201         5675 :     av_hmac_final(s->hmac, hmac, sizeof(hmac));
     202         5675 :     if (memcmp(hmac, buf + len - hmac_size, hmac_size)) {
     203            0 :         av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n");
     204            0 :         return AVERROR_INVALIDDATA;
     205              :     }
     206              : 
     207         5675 :     len -= hmac_size;
     208         5675 :     *lenptr = len;
     209              : 
     210         5675 :     if (len < 12)
     211            0 :         return AVERROR_INVALIDDATA;
     212              : 
     213         5675 :     if (rtcp) {
     214            0 :         uint32_t srtcp_index = AV_RB32(buf + len - 4);
     215            0 :         len -= 4;
     216            0 :         *lenptr = len;
     217              : 
     218            0 :         ssrc = AV_RB32(buf + 4);
     219            0 :         index = srtcp_index & 0x7fffffff;
     220              : 
     221            0 :         buf += 8;
     222            0 :         len -= 8;
     223            0 :         if (!(srtcp_index & 0x80000000))
     224            0 :             return 0;
     225              :     } else {
     226              :         int ext, csrc;
     227         5675 :         s->seq_initialized = 1;
     228         5675 :         s->seq_largest     = seq_largest;
     229         5675 :         s->roc             = roc;
     230              : 
     231         5675 :         csrc = buf[0] & 0x0f;
     232         5675 :         ext  = buf[0] & 0x10;
     233         5675 :         ssrc = AV_RB32(buf + 8);
     234              : 
     235         5675 :         buf += 12;
     236         5675 :         len -= 12;
     237              : 
     238         5675 :         buf += (ptrdiff_t)4 * csrc;
     239         5675 :         len -= 4 * csrc;
     240         5675 :         if (len < 0)
     241            0 :             return AVERROR_INVALIDDATA;
     242              : 
     243         5675 :         if (ext) {
     244         5675 :             if (len < 4)
     245            0 :                 return AVERROR_INVALIDDATA;
     246         5675 :             ext = (AV_RB16(buf + 2) + 1) * 4;
     247         5675 :             if (len < ext)
     248            0 :                 return AVERROR_INVALIDDATA;
     249         5675 :             len -= ext;
     250         5675 :             buf += ext;
     251              :         }
     252              :     }
     253              : 
     254         5675 :     create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
     255         5675 :     av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
     256         5675 :     encrypt_counter(s->aes, iv, buf, len);
     257              : 
     258         5675 :     return 0;
     259              : }
     260              : 
     261         5684 : int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
     262              :                     uint8_t *out, int outlen)
     263              : {
     264         5684 :     uint8_t iv[16] = { 0 }, hmac[20];
     265              :     uint64_t index;
     266              :     uint32_t ssrc;
     267              :     int rtcp, hmac_size, padding;
     268              :     uint8_t *buf;
     269              : 
     270         5684 :     if (len < 8)
     271            0 :         return AVERROR_INVALIDDATA;
     272              : 
     273         5684 :     rtcp = RTP_PT_IS_RTCP(in[1]);
     274         5684 :     hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
     275         5684 :     padding = hmac_size;
     276         5684 :     if (rtcp)
     277            0 :         padding += 4; // For the RTCP index
     278              : 
     279         5684 :     if (len + padding > outlen)
     280            0 :         return 0;
     281              : 
     282         5684 :     memcpy(out, in, len);
     283         5684 :     buf = out;
     284              : 
     285         5684 :     if (rtcp) {
     286            0 :         ssrc = AV_RB32(buf + 4);
     287            0 :         index = s->rtcp_index++;
     288              : 
     289            0 :         buf += 8;
     290            0 :         len -= 8;
     291              :     } else {
     292              :         int ext, csrc;
     293         5684 :         int seq = AV_RB16(buf + 2);
     294              : 
     295         5684 :         if (len < 12)
     296            0 :             return AVERROR_INVALIDDATA;
     297              : 
     298         5684 :         ssrc = AV_RB32(buf + 8);
     299              : 
     300         5684 :         if (seq < s->seq_largest)
     301            0 :             s->roc++;
     302         5684 :         s->seq_largest = seq;
     303         5684 :         index = seq + (((uint64_t)s->roc) << 16);
     304              : 
     305         5684 :         csrc = buf[0] & 0x0f;
     306         5684 :         ext = buf[0] & 0x10;
     307              : 
     308         5684 :         buf += 12;
     309         5684 :         len -= 12;
     310              : 
     311         5684 :         buf += (ptrdiff_t)4 * csrc;
     312         5684 :         len -= 4 * csrc;
     313         5684 :         if (len < 0)
     314            0 :             return AVERROR_INVALIDDATA;
     315              : 
     316         5684 :         if (ext) {
     317         5684 :             if (len < 4)
     318            0 :                 return AVERROR_INVALIDDATA;
     319         5684 :             ext = (AV_RB16(buf + 2) + 1) * 4;
     320         5684 :             if (len < ext)
     321            0 :                 return AVERROR_INVALIDDATA;
     322         5684 :             len -= ext;
     323         5684 :             buf += ext;
     324              :         }
     325              :     }
     326              : 
     327         5684 :     create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
     328         5684 :     av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
     329         5684 :     encrypt_counter(s->aes, iv, buf, len);
     330              : 
     331         5684 :     if (rtcp) {
     332            0 :         AV_WB32(buf + len, 0x80000000 | index);
     333            0 :         len += 4;
     334              :     }
     335              : 
     336         5684 :     av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
     337         5684 :     av_hmac_update(s->hmac, out, buf + len - out);
     338         5684 :     if (!rtcp) {
     339              :         uint8_t rocbuf[4];
     340         5684 :         AV_WB32(rocbuf, s->roc);
     341         5684 :         av_hmac_update(s->hmac, rocbuf, 4);
     342              :     }
     343         5684 :     av_hmac_final(s->hmac, hmac, sizeof(hmac));
     344              : 
     345         5684 :     memcpy(buf + len, hmac, hmac_size);
     346         5684 :     len += hmac_size;
     347         5684 :     return (int)(buf + len - out);
     348              : }
        

Generated by: LCOV version 2.0-1