History

Merge commit 'ab2ad8bd56882c0ea160b154e8b836eb71abc49d'

* commit 'ab2ad8bd56882c0ea160b154e8b836eb71abc49d': lavf: Add functions for SRTP decryption/encryption lavu: Add an API for calculating HMAC (RFC 2104) Conflicts: doc/APIchanges libavutil/version.h

Michael Niedermayer committed 13 years ago

Commit e7e01862 parents e074fe2 ab2ad8b7 files · +584 −1Browse files

Unified · Split

7 files
  1. doc/APIchanges +3 −0
  2. libavformat/srtp.c +293 −0
  3. libavformat/srtp.h +52 −0
  4. libavutil/Makefile +2 −0
  5. libavutil/hmac.c +138 −0
  6. libavutil/hmac.h +95 −0
  7. libavutil/version.h +1 −1
doc/APIchanges+3−0
@@ -132,6 +132,9 @@ API changes, most recent first: · 131 unmodified lines
1322012-03-26 - a67d9cf - lavfi 2.66.1001322012-03-26 - a67d9cf - lavfi 2.66.100
133 Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.133 Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
134 134
1352013-01-xx - xxxxxxx - lavu 52.5.0 - hmac.h
136 Add AVHMAC.
137
1352013-01-13 - xxxxxxx - lavc 54.36.0 - vdpau.h1382013-01-13 - xxxxxxx - lavc 54.36.0 - vdpau.h
136 Add AVVDPAUContext struct for VDPAU hardware-accelerated decoding.139 Add AVVDPAUContext struct for VDPAU hardware-accelerated decoding.
137 140
libavformat/srtp.c+293−0
@@ -0,0 +1,293 @@
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 "srtp.h"
29
30void ff_srtp_free(struct SRTPContext *s)
31{
32 if (!s)
33 return;
34 av_freep(&s->aes);
35 if (s->hmac)
36 av_hmac_free(s->hmac);
37 s->hmac = NULL;
38}
39
40static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
41 int outlen)
42{
43 int i, j, outpos;
44 for (i = 0, outpos = 0; outpos < outlen; i++) {
45 uint8_t keystream[16];
46 AV_WB16(&iv[14], i);
47 av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
48 for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
49 outbuf[outpos] ^= keystream[j];
50 }
51}
52
53static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
54 uint8_t *out, int outlen)
55{
56 uint8_t input[16] = { 0 };
57 memcpy(input, salt, 14);
58 // Key derivation rate assumed to be zero
59 input[14 - 7] ^= label;
60 memset(out, 0, outlen);
61 encrypt_counter(aes, input, out, outlen);
62}
63
64int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
65 const char *params)
66{
67 uint8_t buf[30];
68
69 ff_srtp_free(s);
70
71 // RFC 4568
72 if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80")) {
73 s->hmac_size = 10;
74 } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) {
75 s->hmac_size = 4;
76 } else {
77 av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n",
78 suite);
79 return AVERROR(EINVAL);
80 }
81 if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) {
82 av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n");
83 return AVERROR(EINVAL);
84 }
85 // MKI and lifetime not handled yet
86 s->aes = av_aes_alloc();
87 s->hmac = av_hmac_alloc(AV_HMAC_SHA1);
88 if (!s->aes || !s->hmac)
89 return AVERROR(ENOMEM);
90 memcpy(s->master_key, buf, 16);
91 memcpy(s->master_salt, buf + 16, 14);
92
93 // RFC 3711
94 av_aes_init(s->aes, s->master_key, 128, 0);
95
96 derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key));
97 derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt));
98 derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth));
99
100 derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key));
101 derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt));
102 derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth));
103 return 0;
104}
105
106static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index,
107 uint32_t ssrc)
108{
109 uint8_t indexbuf[8];
110 int i;
111 memset(iv, 0, 16);
112 AV_WB32(&iv[4], ssrc);
113 AV_WB64(indexbuf, index);
114 for (i = 0; i < 8; i++) // index << 16
115 iv[6 + i] ^= indexbuf[i];
116 for (i = 0; i < 14; i++)
117 iv[i] ^= salt[i];
118}
119
120int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
121{
122 uint8_t iv[16] = { 0 }, hmac[20];
123 int len = *lenptr;
124 int ext, seq_largest;
125 uint32_t ssrc, roc;
126 uint64_t index;
127 int rtcp;
128
129 // TODO: Missing replay protection
130
131 if (len < s->hmac_size)
132 return AVERROR_INVALIDDATA;
133
134 rtcp = RTP_PT_IS_RTCP(buf[1]);
135
136 // Authentication HMAC
137 av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
138 // If MKI is used, this should exclude the MKI as well
139 av_hmac_update(s->hmac, buf, len - s->hmac_size);
140
141 if (!rtcp) {
142 int seq = AV_RB16(buf + 2);
143 uint32_t v;
144 uint8_t rocbuf[4];
145
146 // RFC 3711 section 3.3.1, appendix A
147 seq_largest = s->seq_initialized ? s->seq_largest : seq;
148 v = roc = s->roc;
149 if (seq_largest < 32768) {
150 if (seq - seq_largest > 32768)
151 v = roc - 1;
152 } else {
153 if (seq_largest - 32768 > seq)
154 v = roc + 1;
155 }
156 if (v == roc) {
157 seq_largest = FFMAX(seq_largest, seq);
158 } else if (v == roc + 1) {
159 seq_largest = seq;
160 roc = v;
161 }
162 index = seq + (((uint64_t)v) << 16);
163
164 AV_WB32(rocbuf, roc);
165 av_hmac_update(s->hmac, rocbuf, 4);
166 }
167
168 av_hmac_final(s->hmac, hmac, sizeof(hmac));
169 if (memcmp(hmac, buf + len - s->hmac_size, s->hmac_size)) {
170 av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n");
171 return AVERROR_INVALIDDATA;
172 }
173
174 len -= s->hmac_size;
175 *lenptr = len;
176
177 if (len < 12)
178 return AVERROR_INVALIDDATA;
179
180 if (rtcp) {
181 uint32_t srtcp_index = AV_RB32(buf + len - 4);
182 len -= 4;
183 *lenptr = len;
184
185 ssrc = AV_RB32(buf + 4);
186 index = srtcp_index & 0x7fffffff;
187
188 buf += 8;
189 len -= 8;
190 if (!(srtcp_index & 0x80000000))
191 return 0;
192 } else {
193 s->seq_initialized = 1;
194 s->seq_largest = seq_largest;
195 s->roc = roc;
196
197 ext = buf[0] & 0x10;
198 ssrc = AV_RB32(buf + 8);
199
200 buf += 12;
201 len -= 12;
202
203 if (ext) {
204 if (len < 4)
205 return AVERROR_INVALIDDATA;
206 ext = (AV_RB16(buf + 2) + 1) * 4;
207 if (len < ext)
208 return AVERROR_INVALIDDATA;
209 len -= ext;
210 buf += ext;
211 }
212 }
213
214 create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
215 av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
216 encrypt_counter(s->aes, iv, buf, len);
217
218 return 0;
219}
220
221int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
222 uint8_t *out, int outlen)
223{
224 uint8_t iv[16] = { 0 }, hmac[20];
225 uint64_t index;
226 uint32_t ssrc;
227 int rtcp;
228 uint8_t *buf;
229
230 if (len + 14 > outlen)
231 return 0;
232 if (len < 12)
233 return 0;
234
235 memcpy(out, in, len);
236 buf = out;
237
238 rtcp = RTP_PT_IS_RTCP(buf[1]);
239
240 if (rtcp) {
241 ssrc = AV_RB32(buf + 4);
242 index = s->rtcp_index++;
243
244 buf += 8;
245 len -= 8;
246 } else {
247 int ext;
248 int seq = AV_RB16(buf + 2);
249 ssrc = AV_RB32(buf + 8);
250
251 if (seq < s->seq_largest)
252 s->roc++;
253 s->seq_largest = seq;
254 index = seq + (((uint64_t)s->roc) << 16);
255
256 ext = buf[0] & 0x10;
257
258 buf += 12;
259 len -= 12;
260
261 if (ext) {
262 if (len < 4)
263 return AVERROR_INVALIDDATA;
264 ext = (AV_RB16(buf + 2) + 1) * 4;
265 if (len < ext)
266 return AVERROR_INVALIDDATA;
267 len -= ext;
268 buf += ext;
269 }
270 }
271
272 create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
273 av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
274 encrypt_counter(s->aes, iv, buf, len);
275
276 if (rtcp) {
277 AV_WB32(buf + len, 0x80000000 | index);
278 len += 4;
279 }
280
281 av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
282 av_hmac_update(s->hmac, out, buf + len - out);
283 if (!rtcp) {
284 uint8_t rocbuf[4];
285 AV_WB32(rocbuf, s->roc);
286 av_hmac_update(s->hmac, rocbuf, 4);
287 }
288 av_hmac_final(s->hmac, hmac, sizeof(hmac));
289
290 memcpy(buf + len, hmac, s->hmac_size);
291 len += s->hmac_size;
292 return buf + len - out;
293}
libavformat/srtp.h+52−0
@@ -0,0 +1,52 @@
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#ifndef AVFORMAT_SRTP_H
23#define AVFORMAT_SRTP_H
24
25#include <stdint.h>
26
27struct AVAES;
28struct AVHMAC;
29
30struct SRTPContext {
31 struct AVAES *aes;
32 struct AVHMAC *hmac;
33 int hmac_size;
34 uint8_t master_key[16];
35 uint8_t master_salt[14];
36 uint8_t rtp_key[16], rtcp_key[16];
37 uint8_t rtp_salt[14], rtcp_salt[14];
38 uint8_t rtp_auth[20], rtcp_auth[20];
39 int seq_largest, seq_initialized;
40 uint32_t roc;
41
42 uint32_t rtcp_index;
43};
44
45int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite,
46 const char *params);
47void ff_srtp_free(struct SRTPContext *s);
48int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr);
49int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
50 uint8_t *out, int outlen);
51
52#endif /* AVFORMAT_SRTP_H */
libavutil/Makefile+2−0
@@ -22,6 +22,7 @@ HEADERS = adler32.h \ · 21 unmodified lines
22 eval.h \22 eval.h \
23 fifo.h \23 fifo.h \
24 file.h \24 file.h \
25 hmac.h \
25 imgutils.h \26 imgutils.h \
26 intfloat.h \27 intfloat.h \
27 intfloat_readwrite.h \28 intfloat_readwrite.h \
@@ -72,6 +73,7 @@ OBJS = adler32.o \ · 44 unmodified lines
72 fifo.o \73 fifo.o \
73 file.o \74 file.o \
74 float_dsp.o \75 float_dsp.o \
76 hmac.o \
75 imgutils.o \77 imgutils.o \
76 intfloat_readwrite.o \78 intfloat_readwrite.o \
77 intmath.o \79 intmath.o \
libavutil/hmac.c+138−0
@@ -0,0 +1,138 @@
1/*
2 * Copyright (C) 2012 Martin Storsjo
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <string.h>
22
23#include "hmac.h"
24#include "md5.h"
25#include "sha.h"
26#include "mem.h"
27
28#define MAX_HASHLEN 20
29#define MAX_BLOCKLEN 64
30
31struct AVHMAC {
32 void *hash;
33 int blocklen, hashlen;
34 void (*final)(void*, uint8_t*);
35 void (*update)(void*, const uint8_t*, int len);
36 void (*init)(void*);
37 uint8_t key[MAX_BLOCKLEN];
38 int keylen;
39};
40
41static void sha1_init(void *ctx)
42{
43 av_sha_init(ctx, 160);
44}
45
46AVHMAC *av_hmac_alloc(enum AVHMACType type)
47{
48 AVHMAC *c = av_mallocz(sizeof(*c));
49 if (!c)
50 return NULL;
51 switch (type) {
52 case AV_HMAC_MD5:
53 c->blocklen = 64;
54 c->hashlen = 16;
55 c->init = av_md5_init;
56 c->update = av_md5_update;
57 c->final = av_md5_final;
58 c->hash = av_md5_alloc();
59 break;
60 case AV_HMAC_SHA1:
61 c->blocklen = 64;
62 c->hashlen = 20;
63 c->init = sha1_init;
64 c->update = av_sha_update;
65 c->final = av_sha_final;
66 c->hash = av_sha_alloc();
67 break;
68 default:
69 av_free(c);
70 return NULL;
71 }
72 if (!c->hash) {
73 av_free(c);
74 return NULL;
75 }
76 return c;
77}
78
79void av_hmac_free(AVHMAC *c)
80{
81 if (!c)
82 return;
83 av_free(c->hash);
84 av_free(c);
85}
86
87void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
88{
89 int i;
90 uint8_t block[MAX_BLOCKLEN];
91 if (keylen > c->blocklen) {
92 c->init(c->hash);
93 c->update(c->hash, key, keylen);
94 c->final(c->hash, c->key);
95 c->keylen = c->hashlen;
96 } else {
97 memcpy(c->key, key, keylen);
98 c->keylen = keylen;
99 }
100 c->init(c->hash);
101 for (i = 0; i < c->keylen; i++)
102 block[i] = c->key[i] ^ 0x36;
103 for (i = c->keylen; i < c->blocklen; i++)
104 block[i] = 0x36;
105 c->update(c->hash, block, c->blocklen);
106}
107
108void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
109{
110 c->update(c->hash, data, len);
111}
112
113int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
114{
115 uint8_t block[MAX_BLOCKLEN];
116 int i;
117 if (outlen < c->hashlen)
118 return AVERROR(EINVAL);
119 c->final(c->hash, out);
120 c->init(c->hash);
121 for (i = 0; i < c->keylen; i++)
122 block[i] = c->key[i] ^ 0x5C;
123 for (i = c->keylen; i < c->blocklen; i++)
124 block[i] = 0x5C;
125 c->update(c->hash, block, c->blocklen);
126 c->update(c->hash, out, c->hashlen);
127 c->final(c->hash, out);
128 return c->hashlen;
129}
130
131int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len,
132 const uint8_t *key, unsigned int keylen,
133 uint8_t *out, unsigned int outlen)
134{
135 av_hmac_init(c, key, keylen);
136 av_hmac_update(c, data, len);
137 return av_hmac_final(c, out, outlen);
138}
libavutil/hmac.h+95−0
@@ -0,0 +1,95 @@
1/*
2 * Copyright (C) 2012 Martin Storsjo
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVUTIL_HMAC_H
22#define AVUTIL_HMAC_H
23
24#include <stdint.h>
25
26/**
27 * @defgroup lavu_hmac HMAC
28 * @ingroup lavu_crypto
29 * @{
30 */
31
32enum AVHMACType {
33 AV_HMAC_MD5,
34 AV_HMAC_SHA1,
35};
36
37typedef struct AVHMAC AVHMAC;
38
39/**
40 * Allocate an AVHMAC context.
41 * @param type The hash function used for the HMAC.
42 */
43AVHMAC *av_hmac_alloc(enum AVHMACType type);
44
45/**
46 * Free an AVHMAC context.
47 * @param ctx The context to free, may be NULL
48 */
49void av_hmac_free(AVHMAC *ctx);
50
51/**
52 * Initialize an AVHMAC context with an authentication key.
53 * @param ctx The HMAC context
54 * @param key The authentication key
55 * @param keylen The length of the key, in bytes
56 */
57void av_hmac_init(AVHMAC *ctx, const uint8_t *key, unsigned int keylen);
58
59/**
60 * Hash data with the HMAC.
61 * @param ctx The HMAC context
62 * @param data The data to hash
63 * @param len The length of the data, in bytes
64 */
65void av_hmac_update(AVHMAC *ctx, const uint8_t *data, unsigned int len);
66
67/**
68 * Finish hashing and output the HMAC digest.
69 * @param ctx The HMAC context
70 * @param out The output buffer to write the digest into
71 * @param outlen The length of the out buffer, in bytes
72 * @return The number of bytes written to out, or a negative error code.
73 */
74int av_hmac_final(AVHMAC *ctx, uint8_t *out, unsigned int outlen);
75
76/**
77 * Hash an array of data with a key.
78 * @param ctx The HMAC context
79 * @param data The data to hash
80 * @param len The length of the data, in bytes
81 * @param key The authentication key
82 * @param keylen The length of the key, in bytes
83 * @param out The output buffer to write the digest into
84 * @param outlen The length of the out buffer, in bytes
85 * @return The number of bytes written to out, or a negative error code.
86 */
87int av_hmac_calc(AVHMAC *ctx, const uint8_t *data, unsigned int len,
88 const uint8_t *key, unsigned int keylen,
89 uint8_t *out, unsigned int outlen);
90
91/**
92 * @}
93 */
94
95#endif /* AVUTIL_HMAC_H */
libavutil/version.h+1−1
@@ -75,7 +75,7 @@ · 74 unmodified lines
75 */75 */
76 76
77#define LIBAVUTIL_VERSION_MAJOR 5277#define LIBAVUTIL_VERSION_MAJOR 52
78#define LIBAVUTIL_VERSION_MINOR 1478#define LIBAVUTIL_VERSION_MINOR 15
79#define LIBAVUTIL_VERSION_MICRO 10079#define LIBAVUTIL_VERSION_MICRO 100
80 80
81#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \81#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t