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
const
uint8_t
key2[] =
"Jefe"
;
212
const
uint8_t
data1[] =
"Hi There"
;
213
const
uint8_t
data2[] =
"what do ya want for nothing?"
;
214
const
uint8_t
data4[] =
"Test Using Larger Than Block-Size Key - Hash Key First"
;
215
const
uint8_t
data5[] =
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
;
216
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 Wed Jul 10 2013 23:48:15 for FFmpeg by
1.8.2