FFmpeg
Loading...
Searching...
No Matches
srtp.c
Go to the documentation of this file.
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"
26#include "libavutil/log.h"
27#include "libavutil/mem.h"
28#include "rtp.h"
29#include "rtpdec.h"
30#include "srtp.h"
31
33{
34 if (!s)
35 return;
36 av_freep(&s->aes);
37 if (s->hmac)
38 av_hmac_free(s->hmac);
39 s->hmac = NULL;
40}
41
42static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
43 int outlen)
44{
45 int i, j, outpos;
46 for (i = 0, outpos = 0; outpos < outlen; i++) {
47 uint8_t keystream[16];
48 AV_WB16(&iv[14], i);
49 av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
50 for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
51 outbuf[outpos] ^= keystream[j];
52 }
53}
54
55static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
56 uint8_t *out, int outlen)
57{
58 uint8_t input[16] = { 0 };
59 memcpy(input, salt, 14);
60 // Key derivation rate assumed to be zero
61 input[14 - 7] ^= label;
62 memset(out, 0, outlen);
63 encrypt_counter(aes, input, out, outlen);
64}
65
66int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
67 const char *params)
68{
69 uint8_t buf[30];
70
72
73 // RFC 4568
74 if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80") ||
75 !strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_80")) {
76 s->rtp_hmac_size = s->rtcp_hmac_size = 10;
77 } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
78 s->rtp_hmac_size = s->rtcp_hmac_size = 4;
79 } else if (!strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_32")) {
80 // RFC 5764 section 4.1.2
81 s->rtp_hmac_size = 4;
82 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 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 s->aes = av_aes_alloc();
95 if (!s->aes || !s->hmac)
96 return AVERROR(ENOMEM);
97 memcpy(s->master_key, buf, 16);
98 memcpy(s->master_salt, buf + 16, 14);
99
100 // RFC 3711
101 av_aes_init(s->aes, s->master_key, 128, 0);
102
103 derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key));
104 derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt));
105 derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth));
106
107 derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key));
108 derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt));
109 derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth));
110 return 0;
111}
112
113static 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 memset(iv, 0, 16);
119 AV_WB32(&iv[4], ssrc);
120 AV_WB64(indexbuf, index);
121 for (i = 0; i < 8; i++) // index << 16
122 iv[6 + i] ^= indexbuf[i];
123 for (i = 0; i < 14; i++)
124 iv[i] ^= salt[i];
125}
126
127int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
128{
129 uint8_t iv[16] = { 0 }, hmac[20];
130 int len = *lenptr;
131 int av_uninit(seq_largest);
132 uint32_t ssrc, av_uninit(roc);
133 uint64_t index;
134 int rtcp, hmac_size;
135
136 // TODO: Missing replay protection
137
138 if (len < 2)
139 return AVERROR_INVALIDDATA;
140
141 rtcp = RTP_PT_IS_RTCP(buf[1]);
142 hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
143
144 if (len < hmac_size)
145 return AVERROR_INVALIDDATA;
146
147 // Authentication HMAC
148 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 av_hmac_update(s->hmac, buf, len - hmac_size);
151
152 if (!rtcp) {
153 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 seq_largest = s->seq_initialized ? s->seq_largest : seq;
159 v = roc = s->roc;
160 if (seq_largest < 32768) {
161 if (seq - seq_largest > 32768)
162 v = roc - 1;
163 } else {
164 if (seq_largest - 32768 > seq)
165 v = roc + 1;
166 }
167 if (v == roc) {
168 seq_largest = FFMAX(seq_largest, seq);
169 } else if (v == roc + 1) {
170 seq_largest = seq;
171 roc = v;
172 }
173 index = seq + (((uint64_t)v) << 16);
174
175 AV_WB32(rocbuf, roc);
176 av_hmac_update(s->hmac, rocbuf, 4);
177 }
178
179 av_hmac_final(s->hmac, hmac, sizeof(hmac));
180 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 len -= hmac_size;
186 *lenptr = len;
187
188 if (len < 12)
189 return AVERROR_INVALIDDATA;
190
191 if (rtcp) {
192 uint32_t srtcp_index = AV_RB32(buf + len - 4);
193 len -= 4;
194 *lenptr = len;
195
196 ssrc = AV_RB32(buf + 4);
197 index = srtcp_index & 0x7fffffff;
198
199 buf += 8;
200 len -= 8;
201 if (!(srtcp_index & 0x80000000))
202 return 0;
203 } else {
204 int ext, csrc;
205 s->seq_initialized = 1;
206 s->seq_largest = seq_largest;
207 s->roc = roc;
208
209 csrc = buf[0] & 0x0f;
210 ext = buf[0] & 0x10;
211 ssrc = AV_RB32(buf + 8);
212
213 buf += 12;
214 len -= 12;
215
216 buf += 4 * csrc;
217 len -= 4 * csrc;
218 if (len < 0)
219 return AVERROR_INVALIDDATA;
220
221 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 create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
233 av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
234 encrypt_counter(s->aes, iv, buf, len);
235
236 return 0;
237}
238
239int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
240 uint8_t *out, int outlen)
241{
242 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 if (len < 8)
249 return AVERROR_INVALIDDATA;
250
251 rtcp = RTP_PT_IS_RTCP(in[1]);
252 hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
253 padding = hmac_size;
254 if (rtcp)
255 padding += 4; // For the RTCP index
256
257 if (len + padding > outlen)
258 return 0;
259
260 memcpy(out, in, len);
261 buf = out;
262
263 if (rtcp) {
264 ssrc = AV_RB32(buf + 4);
265 index = s->rtcp_index++;
266
267 buf += 8;
268 len -= 8;
269 } else {
270 int ext, csrc;
271 int seq = AV_RB16(buf + 2);
272
273 if (len < 12)
274 return AVERROR_INVALIDDATA;
275
276 ssrc = AV_RB32(buf + 8);
277
278 if (seq < s->seq_largest)
279 s->roc++;
280 s->seq_largest = seq;
281 index = seq + (((uint64_t)s->roc) << 16);
282
283 csrc = buf[0] & 0x0f;
284 ext = buf[0] & 0x10;
285
286 buf += 12;
287 len -= 12;
288
289 buf += 4 * csrc;
290 len -= 4 * csrc;
291 if (len < 0)
292 return AVERROR_INVALIDDATA;
293
294 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 create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
306 av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
307 encrypt_counter(s->aes, iv, buf, len);
308
309 if (rtcp) {
310 AV_WB32(buf + len, 0x80000000 | index);
311 len += 4;
312 }
313
314 av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
315 av_hmac_update(s->hmac, out, buf + len - out);
316 if (!rtcp) {
317 uint8_t rocbuf[4];
318 AV_WB32(rocbuf, s->roc);
319 av_hmac_update(s->hmac, rocbuf, 4);
320 }
321 av_hmac_final(s->hmac, hmac, sizeof(hmac));
322
323 memcpy(buf + len, hmac, hmac_size);
324 len += hmac_size;
325 return buf + len - out;
326}
SwsAArch64OpImplParams params
Definition ops.c:51
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
struct AVAES * av_aes_alloc(void)
Allocate an AVAES context.
Definition aes.c:37
int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
Initialize an AVAES context.
Definition aes.c:231
void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt)
Encrypt or decrypt a buffer using a previously initialized context.
Definition aes.c:171
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
Definition base64.c:81
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
Finish hashing and output the HMAC digest.
Definition hmac.c:181
AVHMAC * av_hmac_alloc(enum AVHMACType type)
Allocate an AVHMAC context.
Definition hmac.c:82
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
Hash data with the HMAC.
Definition hmac.c:176
void av_hmac_free(AVHMAC *c)
Free an AVHMAC context.
Definition hmac.c:147
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
Initialize an AVHMAC context with an authentication key.
Definition hmac.c:155
@ AV_HMAC_SHA1
Definition hmac.h:34
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
int index
Definition gxfenc.c:90
#define AV_WB32(p, v)
#define AV_RB32(p)
#define AV_WB64(p, v)
#define AV_WB16(p, v)
#define AV_RB16(p)
#define av_uninit(x)
Definition attributes.h:187
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define RTP_PT_IS_RTCP(x)
Definition rtp.h:112
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen)
Definition srtp.c:239
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params)
Definition srtp.c:66
static void derive_key(struct AVAES *aes, const uint8_t *salt, int label, uint8_t *out, int outlen)
Definition srtp.c:55
static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf, int outlen)
Definition srtp.c:42
static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index, uint32_t ssrc)
Definition srtp.c:113
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
Definition srtp.c:127
void ff_srtp_free(struct SRTPContext *s)
Definition srtp.c:32
#define av_freep(p)
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
const uint8_t keystream[8]
Definition rc4.c:32
int len