FFmpeg
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"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/log.h"
27 #include "rtp.h"
28 #include "rtpdec.h"
29 #include "srtp.h"
30 
31 void ff_srtp_free(struct SRTPContext *s)
32 {
33  if (!s)
34  return;
35  av_freep(&s->aes);
36  if (s->hmac)
37  av_hmac_free(s->hmac);
38  s->hmac = NULL;
39 }
40 
41 static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
42  int outlen)
43 {
44  int i, j, outpos;
45  for (i = 0, outpos = 0; outpos < outlen; i++) {
46  uint8_t keystream[16];
47  AV_WB16(&iv[14], i);
48  av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
49  for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
50  outbuf[outpos] ^= keystream[j];
51  }
52 }
53 
54 static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
55  uint8_t *out, int outlen)
56 {
57  uint8_t input[16] = { 0 };
58  memcpy(input, salt, 14);
59  // Key derivation rate assumed to be zero
60  input[14 - 7] ^= label;
61  memset(out, 0, outlen);
62  encrypt_counter(aes, input, out, outlen);
63 }
64 
65 int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
66  const char *params)
67 {
68  uint8_t buf[30];
69 
70  ff_srtp_free(s);
71 
72  // RFC 4568
73  if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80") ||
74  !strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_80")) {
75  s->rtp_hmac_size = s->rtcp_hmac_size = 10;
76  } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
77  s->rtp_hmac_size = s->rtcp_hmac_size = 4;
78  } else if (!strcmp(suite, "SRTP_AES128_CM_HMAC_SHA1_32")) {
79  // RFC 5764 section 4.1.2
80  s->rtp_hmac_size = 4;
81  s->rtcp_hmac_size = 10;
82  } else {
83  av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n",
84  suite);
85  return AVERROR(EINVAL);
86  }
87  if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) {
88  av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n");
89  return AVERROR(EINVAL);
90  }
91  // MKI and lifetime not handled yet
92  s->aes = av_aes_alloc();
94  if (!s->aes || !s->hmac)
95  return AVERROR(ENOMEM);
96  memcpy(s->master_key, buf, 16);
97  memcpy(s->master_salt, buf + 16, 14);
98 
99  // RFC 3711
100  av_aes_init(s->aes, s->master_key, 128, 0);
101 
102  derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key));
103  derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt));
104  derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth));
105 
106  derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key));
107  derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt));
108  derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth));
109  return 0;
110 }
111 
112 static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index,
113  uint32_t ssrc)
114 {
115  uint8_t indexbuf[8];
116  int i;
117  memset(iv, 0, 16);
118  AV_WB32(&iv[4], ssrc);
119  AV_WB64(indexbuf, index);
120  for (i = 0; i < 8; i++) // index << 16
121  iv[6 + i] ^= indexbuf[i];
122  for (i = 0; i < 14; i++)
123  iv[i] ^= salt[i];
124 }
125 
126 int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
127 {
128  uint8_t iv[16] = { 0 }, hmac[20];
129  int len = *lenptr;
130  int av_uninit(seq_largest);
131  uint32_t ssrc, av_uninit(roc);
132  uint64_t index;
133  int rtcp, hmac_size;
134 
135  // TODO: Missing replay protection
136 
137  if (len < 2)
138  return AVERROR_INVALIDDATA;
139 
140  rtcp = RTP_PT_IS_RTCP(buf[1]);
141  hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
142 
143  if (len < hmac_size)
144  return AVERROR_INVALIDDATA;
145 
146  // Authentication HMAC
147  av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
148  // If MKI is used, this should exclude the MKI as well
149  av_hmac_update(s->hmac, buf, len - hmac_size);
150 
151  if (!rtcp) {
152  int seq = AV_RB16(buf + 2);
153  uint32_t v;
154  uint8_t rocbuf[4];
155 
156  // RFC 3711 section 3.3.1, appendix A
157  seq_largest = s->seq_initialized ? s->seq_largest : seq;
158  v = roc = s->roc;
159  if (seq_largest < 32768) {
160  if (seq - seq_largest > 32768)
161  v = roc - 1;
162  } else {
163  if (seq_largest - 32768 > seq)
164  v = roc + 1;
165  }
166  if (v == roc) {
167  seq_largest = FFMAX(seq_largest, seq);
168  } else if (v == roc + 1) {
169  seq_largest = seq;
170  roc = v;
171  }
172  index = seq + (((uint64_t)v) << 16);
173 
174  AV_WB32(rocbuf, roc);
175  av_hmac_update(s->hmac, rocbuf, 4);
176  }
177 
178  av_hmac_final(s->hmac, hmac, sizeof(hmac));
179  if (memcmp(hmac, buf + len - hmac_size, hmac_size)) {
180  av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n");
181  return AVERROR_INVALIDDATA;
182  }
183 
184  len -= hmac_size;
185  *lenptr = len;
186 
187  if (len < 12)
188  return AVERROR_INVALIDDATA;
189 
190  if (rtcp) {
191  uint32_t srtcp_index = AV_RB32(buf + len - 4);
192  len -= 4;
193  *lenptr = len;
194 
195  ssrc = AV_RB32(buf + 4);
196  index = srtcp_index & 0x7fffffff;
197 
198  buf += 8;
199  len -= 8;
200  if (!(srtcp_index & 0x80000000))
201  return 0;
202  } else {
203  int ext, csrc;
204  s->seq_initialized = 1;
205  s->seq_largest = seq_largest;
206  s->roc = roc;
207 
208  csrc = buf[0] & 0x0f;
209  ext = buf[0] & 0x10;
210  ssrc = AV_RB32(buf + 8);
211 
212  buf += 12;
213  len -= 12;
214 
215  buf += 4 * csrc;
216  len -= 4 * csrc;
217  if (len < 0)
218  return AVERROR_INVALIDDATA;
219 
220  if (ext) {
221  if (len < 4)
222  return AVERROR_INVALIDDATA;
223  ext = (AV_RB16(buf + 2) + 1) * 4;
224  if (len < ext)
225  return AVERROR_INVALIDDATA;
226  len -= ext;
227  buf += ext;
228  }
229  }
230 
231  create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
232  av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
233  encrypt_counter(s->aes, iv, buf, len);
234 
235  return 0;
236 }
237 
238 int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
239  uint8_t *out, int outlen)
240 {
241  uint8_t iv[16] = { 0 }, hmac[20];
242  uint64_t index;
243  uint32_t ssrc;
244  int rtcp, hmac_size, padding;
245  uint8_t *buf;
246 
247  if (len < 8)
248  return AVERROR_INVALIDDATA;
249 
250  rtcp = RTP_PT_IS_RTCP(in[1]);
251  hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
252  padding = hmac_size;
253  if (rtcp)
254  padding += 4; // For the RTCP index
255 
256  if (len + padding > outlen)
257  return 0;
258 
259  memcpy(out, in, len);
260  buf = out;
261 
262  if (rtcp) {
263  ssrc = AV_RB32(buf + 4);
264  index = s->rtcp_index++;
265 
266  buf += 8;
267  len -= 8;
268  } else {
269  int ext, csrc;
270  int seq = AV_RB16(buf + 2);
271 
272  if (len < 12)
273  return AVERROR_INVALIDDATA;
274 
275  ssrc = AV_RB32(buf + 8);
276 
277  if (seq < s->seq_largest)
278  s->roc++;
279  s->seq_largest = seq;
280  index = seq + (((uint64_t)s->roc) << 16);
281 
282  csrc = buf[0] & 0x0f;
283  ext = buf[0] & 0x10;
284 
285  buf += 12;
286  len -= 12;
287 
288  buf += 4 * csrc;
289  len -= 4 * csrc;
290  if (len < 0)
291  return AVERROR_INVALIDDATA;
292 
293  if (ext) {
294  if (len < 4)
295  return AVERROR_INVALIDDATA;
296  ext = (AV_RB16(buf + 2) + 1) * 4;
297  if (len < ext)
298  return AVERROR_INVALIDDATA;
299  len -= ext;
300  buf += ext;
301  }
302  }
303 
304  create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
305  av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
306  encrypt_counter(s->aes, iv, buf, len);
307 
308  if (rtcp) {
309  AV_WB32(buf + len, 0x80000000 | index);
310  len += 4;
311  }
312 
313  av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
314  av_hmac_update(s->hmac, out, buf + len - out);
315  if (!rtcp) {
316  uint8_t rocbuf[4];
317  AV_WB32(rocbuf, s->roc);
318  av_hmac_update(s->hmac, rocbuf, 4);
319  }
320  av_hmac_final(s->hmac, hmac, sizeof(hmac));
321 
322  memcpy(buf + len, hmac, hmac_size);
323  len += hmac_size;
324  return buf + len - out;
325 }
int rtp_hmac_size
Definition: srtp.h:33
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen)
Definition: srtp.c:238
AVHMAC * av_hmac_alloc(enum AVHMACType type)
Allocate an AVHMAC context.
Definition: hmac.c:72
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf, int outlen)
Definition: srtp.c:41
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:163
uint8_t rtcp_auth[20]
Definition: srtp.h:38
uint8_t rtp_auth[20]
Definition: srtp.h:38
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
uint8_t rtcp_salt[14]
Definition: srtp.h:37
#define AV_WB64(p, v)
Definition: intreadwrite.h:433
int seq_initialized
Definition: srtp.h:39
static void derive_key(struct AVAES *aes, const uint8_t *salt, int label, uint8_t *out, int outlen)
Definition: srtp.c:54
void ff_srtp_free(struct SRTPContext *s)
Definition: srtp.c:31
uint8_t
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:87
struct AVHMAC * hmac
Definition: srtp.h:32
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
Hash data with the HMAC.
Definition: hmac.c:166
uint8_t master_salt[14]
Definition: srtp.h:35
#define AV_WB16(p, v)
Definition: intreadwrite.h:405
#define av_log(a,...)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
struct AVAES * aes
Definition: srtp.h:31
uint8_t rtcp_key[16]
Definition: srtp.h:36
int seq_largest
Definition: srtp.h:39
GLenum GLint * params
Definition: opengl_enc.c:113
struct AVAES * av_aes_alloc(void)
Allocate an AVAES context.
Definition: aes.c:31
#define FFMAX(a, b)
Definition: common.h:94
static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index, uint32_t ssrc)
Definition: srtp.c:112
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
Definition: srtp.c:126
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
Initialize an AVHMAC context with an authentication key.
Definition: hmac.c:145
#define s(width, name)
Definition: cbs_vp9.c:257
uint8_t rtp_key[16]
Definition: srtp.h:36
int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
Initialize an AVAES context.
Definition: aes.c:195
void * buf
Definition: avisynth_c.h:766
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
int index
Definition: gxfenc.c:89
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
uint8_t master_key[16]
Definition: srtp.h:34
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
Finish hashing and output the HMAC digest.
Definition: hmac.c:171
#define RTP_PT_IS_RTCP(x)
Definition: rtp.h:110
uint32_t rtcp_index
Definition: srtp.h:42
void av_hmac_free(AVHMAC *c)
Free an AVHMAC context.
Definition: hmac.c:137
int len
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params)
Definition: srtp.c:65
int rtcp_hmac_size
Definition: srtp.h:33
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
Definition: base64.c:79
uint8_t rtp_salt[14]
Definition: srtp.h:37
#define av_uninit(x)
Definition: attributes.h:148
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DBG Preprocess x86 external assembler files to a dbg asm file in the object which then gets compiled Helps in developing those assembler files DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test suite
Definition: build_system.txt:1
FILE * out
Definition: movenc.c:54
#define av_freep(p)
uint32_t roc
Definition: srtp.h:40
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions