FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/srtp.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 150 188 79.8%
Functions: 7 7 100.0%
Branches: 77 118 65.3%

Line Branch Exec Source
1 /*
2 * SRTP encryption/decryption
3 * Copyright (c) 2012 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "libavutil/base64.h"
23 #include "libavutil/aes.h"
24 #include "libavutil/hmac.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/log.h"
27 #include "libavutil/mem.h"
28 #include "rtp.h"
29 #include "rtpdec.h"
30 #include "srtp.h"
31
32 30 void ff_srtp_free(struct SRTPContext *s)
33 {
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!s)
35 return;
36 30 av_freep(&s->aes);
37
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (s->hmac)
38 15 av_hmac_free(s->hmac);
39 30 s->hmac = NULL;
40 }
41
42 108 static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
43 int outlen)
44 {
45 int i, j, outpos;
46
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 108 times.
249 for (i = 0, outpos = 0; outpos < outlen; i++) {
47 uint8_t keystream[16];
48 141 AV_WB16(&iv[14], i);
49 141 av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
50
4/4
✓ Branch 0 taken 1749 times.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 1671 times.
✓ Branch 3 taken 78 times.
1812 for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
51 1671 outbuf[outpos] ^= keystream[j];
52 }
53 108 }
54
55 90 static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
56 uint8_t *out, int outlen)
57 {
58 90 uint8_t input[16] = { 0 };
59 90 memcpy(input, salt, 14);
60 // Key derivation rate assumed to be zero
61 90 input[14 - 7] ^= label;
62 90 memset(out, 0, outlen);
63 90 encrypt_counter(aes, input, out, outlen);
64 90 }
65
66 15 int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
67 const char *params)
68 {
69 uint8_t buf[30];
70
71 15 ff_srtp_free(s);
72
73 // RFC 4568
74
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80") ||
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 !strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_80")) {
76 5 s->rtp_hmac_size = s->rtcp_hmac_size = 10;
77
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
78 5 s->rtp_hmac_size = s->rtcp_hmac_size = 4;
79
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (!strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_32")) {
80 // RFC 5764 section 4.1.2
81 5 s->rtp_hmac_size = 4;
82 5 s->rtcp_hmac_size = 10;
83 } else {
84 av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n",
85 suite);
86 return AVERROR(EINVAL);
87 }
88
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) {
89 av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n");
90 return AVERROR(EINVAL);
91 }
92 // MKI and lifetime not handled yet
93 15 s->aes = av_aes_alloc();
94 15 s->hmac = av_hmac_alloc(AV_HMAC_SHA1);
95
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (!s->aes || !s->hmac)
96 return AVERROR(ENOMEM);
97 15 memcpy(s->master_key, buf, 16);
98 15 memcpy(s->master_salt, buf + 16, 14);
99
100 // RFC 3711
101 15 av_aes_init(s->aes, s->master_key, 128, 0);
102
103 15 derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key));
104 15 derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt));
105 15 derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth));
106
107 15 derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key));
108 15 derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt));
109 15 derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth));
110 15 return 0;
111 }
112
113 18 static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index,
114 uint32_t ssrc)
115 {
116 uint8_t indexbuf[8];
117 int i;
118 18 memset(iv, 0, 16);
119 18 AV_WB32(&iv[4], ssrc);
120 18 AV_WB64(indexbuf, index);
121
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 18 times.
162 for (i = 0; i < 8; i++) // index << 16
122 144 iv[6 + i] ^= indexbuf[i];
123
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 18 times.
270 for (i = 0; i < 14; i++)
124 252 iv[i] ^= salt[i];
125 18 }
126
127 12 int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
128 {
129 12 uint8_t iv[16] = { 0 }, hmac[20];
130 12 int len = *lenptr;
131 12 int av_uninit(seq_largest);
132 12 uint32_t ssrc, av_uninit(roc);
133 uint64_t index;
134 int rtcp, hmac_size;
135
136 // TODO: Missing replay protection
137
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (len < 2)
139 return AVERROR_INVALIDDATA;
140
141
5/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 6 times.
12 rtcp = RTP_PT_IS_RTCP(buf[1]);
142
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
143
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (len < hmac_size)
145 return AVERROR_INVALIDDATA;
146
147 // Authentication HMAC
148
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
149 // If MKI is used, this should exclude the MKI as well
150 12 av_hmac_update(s->hmac, buf, len - hmac_size);
151
152
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (!rtcp) {
153 6 int seq = AV_RB16(buf + 2);
154 uint32_t v;
155 uint8_t rocbuf[4];
156
157 // RFC 3711 section 3.3.1, appendix A
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 seq_largest = s->seq_initialized ? s->seq_largest : seq;
159 6 v = roc = s->roc;
160
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (seq_largest < 32768) {
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (seq - seq_largest > 32768)
162 v = roc - 1;
163 } else {
164 if (seq_largest - 32768 > seq)
165 v = roc + 1;
166 }
167
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (v == roc) {
168 6 seq_largest = FFMAX(seq_largest, seq);
169 } else if (v == roc + 1) {
170 seq_largest = seq;
171 roc = v;
172 }
173 6 index = seq + (((uint64_t)v) << 16);
174
175 6 AV_WB32(rocbuf, roc);
176 6 av_hmac_update(s->hmac, rocbuf, 4);
177 }
178
179 12 av_hmac_final(s->hmac, hmac, sizeof(hmac));
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (memcmp(hmac, buf + len - hmac_size, hmac_size)) {
181 av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n");
182 return AVERROR_INVALIDDATA;
183 }
184
185 12 len -= hmac_size;
186 12 *lenptr = len;
187
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (len < 12)
189 return AVERROR_INVALIDDATA;
190
191
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rtcp) {
192 6 uint32_t srtcp_index = AV_RB32(buf + len - 4);
193 6 len -= 4;
194 6 *lenptr = len;
195
196 6 ssrc = AV_RB32(buf + 4);
197 6 index = srtcp_index & 0x7fffffff;
198
199 6 buf += 8;
200 6 len -= 8;
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!(srtcp_index & 0x80000000))
202 return 0;
203 } else {
204 int ext, csrc;
205 6 s->seq_initialized = 1;
206 6 s->seq_largest = seq_largest;
207 6 s->roc = roc;
208
209 6 csrc = buf[0] & 0x0f;
210 6 ext = buf[0] & 0x10;
211 6 ssrc = AV_RB32(buf + 8);
212
213 6 buf += 12;
214 6 len -= 12;
215
216 6 buf += 4 * csrc;
217 6 len -= 4 * csrc;
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (len < 0)
219 return AVERROR_INVALIDDATA;
220
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ext) {
222 if (len < 4)
223 return AVERROR_INVALIDDATA;
224 ext = (AV_RB16(buf + 2) + 1) * 4;
225 if (len < ext)
226 return AVERROR_INVALIDDATA;
227 len -= ext;
228 buf += ext;
229 }
230 }
231
232
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
233
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
234 12 encrypt_counter(s->aes, iv, buf, len);
235
236 12 return 0;
237 }
238
239 6 int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
240 uint8_t *out, int outlen)
241 {
242 6 uint8_t iv[16] = { 0 }, hmac[20];
243 uint64_t index;
244 uint32_t ssrc;
245 int rtcp, hmac_size, padding;
246 uint8_t *buf;
247
248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (len < 8)
249 return AVERROR_INVALIDDATA;
250
251
5/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 3 times.
6 rtcp = RTP_PT_IS_RTCP(in[1]);
252
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
253 6 padding = hmac_size;
254
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rtcp)
255 3 padding += 4; // For the RTCP index
256
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (len + padding > outlen)
258 return 0;
259
260 6 memcpy(out, in, len);
261 6 buf = out;
262
263
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rtcp) {
264 3 ssrc = AV_RB32(buf + 4);
265 3 index = s->rtcp_index++;
266
267 3 buf += 8;
268 3 len -= 8;
269 } else {
270 int ext, csrc;
271 3 int seq = AV_RB16(buf + 2);
272
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (len < 12)
274 return AVERROR_INVALIDDATA;
275
276 3 ssrc = AV_RB32(buf + 8);
277
278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (seq < s->seq_largest)
279 s->roc++;
280 3 s->seq_largest = seq;
281 3 index = seq + (((uint64_t)s->roc) << 16);
282
283 3 csrc = buf[0] & 0x0f;
284 3 ext = buf[0] & 0x10;
285
286 3 buf += 12;
287 3 len -= 12;
288
289 3 buf += 4 * csrc;
290 3 len -= 4 * csrc;
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (len < 0)
292 return AVERROR_INVALIDDATA;
293
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ext) {
295 if (len < 4)
296 return AVERROR_INVALIDDATA;
297 ext = (AV_RB16(buf + 2) + 1) * 4;
298 if (len < ext)
299 return AVERROR_INVALIDDATA;
300 len -= ext;
301 buf += ext;
302 }
303 }
304
305
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
306
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
307 6 encrypt_counter(s->aes, iv, buf, len);
308
309
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (rtcp) {
310 3 AV_WB32(buf + len, 0x80000000 | index);
311 3 len += 4;
312 }
313
314
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
315 6 av_hmac_update(s->hmac, out, buf + len - out);
316
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!rtcp) {
317 uint8_t rocbuf[4];
318 3 AV_WB32(rocbuf, s->roc);
319 3 av_hmac_update(s->hmac, rocbuf, 4);
320 }
321 6 av_hmac_final(s->hmac, hmac, sizeof(hmac));
322
323 6 memcpy(buf + len, hmac, hmac_size);
324 6 len += hmac_size;
325 6 return buf + len - out;
326 }
327