FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavutil
hmac.c
Go to the documentation of this file.
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 "
attributes.h
"
24
#include "
hmac.h
"
25
#include "
md5.h
"
26
#include "
sha.h
"
27
#include "
sha512.h
"
28
#include "
mem.h
"
29
30
#define MAX_HASHLEN 64
31
#define MAX_BLOCKLEN 128
32
33
struct
AVHMAC
{
34
void
*
hash
;
35
int
blocklen
,
hashlen
;
36
void
(*
final
)(
void
*,
uint8_t
*);
37
void
(*
update
)(
void
*,
const
uint8_t
*,
int
len
);
38
void
(*
init
)(
void
*);
39
uint8_t
key
[
MAX_BLOCKLEN
];
40
int
keylen
;
41
};
42
43
#define DEFINE_SHA(bits) \
44
static av_cold void sha ## bits ##_init(void *ctx) \
45
{ \
46
av_sha_init(ctx, bits); \
47
}
48
49
#define DEFINE_SHA512(bits) \
50
static av_cold void sha ## bits ##_init(void *ctx) \
51
{ \
52
av_sha512_init(ctx, bits); \
53
}
54
55
DEFINE_SHA
(160)
56
DEFINE_SHA
(224)
57
DEFINE_SHA
(256)
58
DEFINE_SHA512
(384)
59
DEFINE_SHA512
(512)
60
61
AVHMAC
*
av_hmac_alloc
(enum
AVHMACType
type)
62
{
63
AVHMAC
*
c
=
av_mallocz
(
sizeof
(*c));
64
if
(!c)
65
return
NULL;
66
switch
(type) {
67
case
AV_HMAC_MD5
:
68
c->
blocklen
= 64;
69
c->
hashlen
= 16;
70
c->
init
= (
void
*)
av_md5_init
;
71
c->
update
= (
void
*)
av_md5_update
;
72
c->
final
= (
void
*)
av_md5_final
;
73
c->
hash
=
av_md5_alloc
();
74
break
;
75
case
AV_HMAC_SHA1
:
76
c->
blocklen
= 64;
77
c->
hashlen
= 20;
78
c->
init
= sha160_init;
79
c->
update
= (
void
*)
av_sha_update
;
80
c->
final
= (
void
*)
av_sha_final
;
81
c->
hash
=
av_sha_alloc
();
82
break
;
83
case
AV_HMAC_SHA224
:
84
c->
blocklen
= 64;
85
c->
hashlen
= 28;
86
c->
init
= sha224_init;
87
c->
update
= (
void
*)
av_sha_update
;
88
c->
final
= (
void
*)
av_sha_final
;
89
c->
hash
=
av_sha_alloc
();
90
break
;
91
case
AV_HMAC_SHA256
:
92
c->
blocklen
= 64;
93
c->
hashlen
= 32;
94
c->
init
= sha256_init;
95
c->
update
= (
void
*)
av_sha_update
;
96
c->
final
= (
void
*)
av_sha_final
;
97
c->
hash
=
av_sha_alloc
();
98
break
;
99
case
AV_HMAC_SHA384
:
100
c->
blocklen
= 128;
101
c->
hashlen
= 48;
102
c->
init
= sha384_init;
103
c->
update
= (
void
*)
av_sha512_update
;
104
c->
final
= (
void
*)
av_sha512_final
;
105
c->
hash
=
av_sha512_alloc
();
106
break
;
107
case
AV_HMAC_SHA512
:
108
c->
blocklen
= 128;
109
c->
hashlen
= 64;
110
c->
init
= sha512_init;
111
c->
update
= (
void
*)
av_sha512_update
;
112
c->
final
= (
void
*)
av_sha512_final
;
113
c->
hash
=
av_sha512_alloc
();
114
break
;
115
default
:
116
av_free
(c);
117
return
NULL;
118
}
119
if
(!c->
hash
) {
120
av_free
(c);
121
return
NULL;
122
}
123
return
c
;
124
}
125
126
void
av_hmac_free
(
AVHMAC
*
c
)
127
{
128
if
(!c)
129
return
;
130
av_free
(c->
hash
);
131
av_free
(c);
132
}
133
134
void
av_hmac_init
(
AVHMAC
*
c
,
const
uint8_t
*key,
unsigned
int
keylen)
135
{
136
int
i;
137
uint8_t
block
[
MAX_BLOCKLEN
];
138
if
(keylen > c->
blocklen
) {
139
c->
init
(c->
hash
);
140
c->
update
(c->
hash
, key, keylen);
141
c->
final
(c->
hash
, c->
key
);
142
c->
keylen
= c->
hashlen
;
143
}
else
{
144
memcpy(c->
key
, key, keylen);
145
c->
keylen
= keylen;
146
}
147
c->
init
(c->
hash
);
148
for
(i = 0; i < c->
keylen
; i++)
149
block[i] = c->
key
[i] ^ 0x36;
150
for
(i = c->
keylen
; i < c->blocklen; i++)
151
block[i] = 0x36;
152
c->
update
(c->
hash
, block, c->
blocklen
);
153
}
154
155
void
av_hmac_update
(
AVHMAC
*
c
,
const
uint8_t
*
data
,
unsigned
int
len
)
156
{
157
c->
update
(c->
hash
, data, len);
158
}
159
160
int
av_hmac_final
(
AVHMAC
*
c
,
uint8_t
*
out
,
unsigned
int
outlen)
161
{
162
uint8_t
block
[
MAX_BLOCKLEN
];
163
int
i;
164
if
(outlen < c->hashlen)
165
return
AVERROR
(EINVAL);
166
c->
final
(c->
hash
, out);
167
c->
init
(c->
hash
);
168
for
(i = 0; i < c->
keylen
; i++)
169
block[i] = c->
key
[i] ^ 0x5C;
170
for
(i = c->
keylen
; i < c->blocklen; i++)
171
block[i] = 0x5C;
172
c->
update
(c->
hash
, block, c->
blocklen
);
173
c->
update
(c->
hash
, out, c->
hashlen
);
174
c->
final
(c->
hash
, out);
175
return
c->
hashlen
;
176
}
177
178
int
av_hmac_calc
(
AVHMAC
*
c
,
const
uint8_t
*
data
,
unsigned
int
len
,
179
const
uint8_t
*key,
unsigned
int
keylen,
180
uint8_t
*
out
,
unsigned
int
outlen)
181
{
182
av_hmac_init
(c, key, keylen);
183
av_hmac_update
(c, data, len);
184
return
av_hmac_final
(c, out, outlen);
185
}
186
187
#ifdef TEST
188
#include <stdio.h>
189
190
static
void
test
(
AVHMAC
*hmac,
const
uint8_t
*key,
int
keylen,
191
const
uint8_t
*
data
,
int
datalen)
192
{
193
uint8_t
buf
[
MAX_HASHLEN
];
194
int
out
, i;
195
// Some of the test vectors are strings, where sizeof() includes the
196
// trailing null byte - remove that.
197
if
(!key[keylen - 1])
198
keylen--;
199
if
(!data[datalen - 1])
200
datalen--;
201
out =
av_hmac_calc
(hmac, data, datalen, key, keylen, buf,
sizeof
(buf));
202
for
(i = 0; i <
out
; i++)
203
printf(
"%02x"
, buf[i]);
204
printf(
"\n"
);
205
}
206
207
int
main
(
void
)
208
{
209
uint8_t
key1[20], key3[131], data3[50];
210
enum
AVHMACType
i =
AV_HMAC_SHA224
;
211
static
const
uint8_t
key2[] =
"Jefe"
;
212
static
const
uint8_t
data1[] =
"Hi There"
;
213
static
const
uint8_t
data2[] =
"what do ya want for nothing?"
;
214
static
const
uint8_t
data4[] =
"Test Using Larger Than Block-Size Key - Hash Key First"
;
215
static
const
uint8_t
data5[] =
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
;
216
static
const
uint8_t
data6[] =
"This is a test using a larger than block-size key and a larger "
217
"than block-size data. The key needs to be hashed before being used"
218
" by the HMAC algorithm."
;
219
AVHMAC
*hmac =
av_hmac_alloc
(
AV_HMAC_MD5
);
220
if
(!hmac)
221
return
1;
222
memset(key1, 0x0b,
sizeof
(key1));
223
memset(key3, 0xaa,
sizeof
(key3));
224
memset(data3, 0xdd,
sizeof
(data3));
225
// RFC 2202 test vectors
226
test
(hmac, key1, 16, data1,
sizeof
(data1));
227
test
(hmac, key2,
sizeof
(key2), data2,
sizeof
(data2));
228
test
(hmac, key3, 16, data3,
sizeof
(data3));
229
test
(hmac, key3, 80, data4,
sizeof
(data4));
230
test
(hmac, key3, 80, data5,
sizeof
(data5));
231
av_hmac_free
(hmac);
232
233
/* SHA-1 */
234
hmac =
av_hmac_alloc
(
AV_HMAC_SHA1
);
235
if
(!hmac)
236
return
1;
237
// RFC 2202 test vectors
238
test
(hmac, key1,
sizeof
(key1), data1,
sizeof
(data1));
239
test
(hmac, key2,
sizeof
(key2), data2,
sizeof
(data2));
240
test
(hmac, key3, 20, data3,
sizeof
(data3));
241
test
(hmac, key3, 80, data4,
sizeof
(data4));
242
test
(hmac, key3, 80, data5,
sizeof
(data5));
243
av_hmac_free
(hmac);
244
245
/* SHA-2 */
246
while
(i <=
AV_HMAC_SHA512
) {
247
hmac =
av_hmac_alloc
(i);
248
// RFC 4231 test vectors
249
test
(hmac, key1,
sizeof
(key1), data1,
sizeof
(data1));
250
test
(hmac, key2,
sizeof
(key2), data2,
sizeof
(data2));
251
test
(hmac, key3, 20, data3,
sizeof
(data3));
252
test
(hmac, key3,
sizeof
(key3), data4,
sizeof
(data4));
253
test
(hmac, key3,
sizeof
(key3), data6,
sizeof
(data6));
254
av_hmac_free
(hmac);
255
i++;
256
}
257
return
0;
258
}
259
#endif
/* TEST */
Generated on Sat Jan 25 2014 19:52:06 for FFmpeg by
1.8.2