2 * Copyright (C) 2012 Martin Storsjo
4 * This file is part of Libav.
6 * Libav 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.
11 * Libav 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "attributes.h"
29 #define MAX_HASHLEN 20
30 #define MAX_BLOCKLEN 64
34 int blocklen
, hashlen
;
35 void (*final
)(void*, uint8_t*);
36 void (*update
)(void*, const uint8_t*, int len
);
38 uint8_t key
[MAX_BLOCKLEN
];
42 static av_cold
void sha1_init(void *ctx
)
44 av_sha_init(ctx
, 160);
47 AVHMAC
*av_hmac_alloc(enum AVHMACType type
)
49 AVHMAC
*c
= av_mallocz(sizeof(*c
));
56 c
->init
= av_md5_init
;
57 c
->update
= av_md5_update
;
58 c
->final
= av_md5_final
;
59 c
->hash
= av_md5_alloc();
65 c
->update
= av_sha_update
;
66 c
->final
= av_sha_final
;
67 c
->hash
= av_sha_alloc();
80 void av_hmac_free(AVHMAC
*c
)
88 void av_hmac_init(AVHMAC
*c
, const uint8_t *key
, unsigned int keylen
)
91 uint8_t block
[MAX_BLOCKLEN
];
92 if (keylen
> c
->blocklen
) {
94 c
->update(c
->hash
, key
, keylen
);
95 c
->final(c
->hash
, c
->key
);
96 c
->keylen
= c
->hashlen
;
98 memcpy(c
->key
, key
, keylen
);
102 for (i
= 0; i
< c
->keylen
; i
++)
103 block
[i
] = c
->key
[i
] ^ 0x36;
104 for (i
= c
->keylen
; i
< c
->blocklen
; i
++)
106 c
->update(c
->hash
, block
, c
->blocklen
);
109 void av_hmac_update(AVHMAC
*c
, const uint8_t *data
, unsigned int len
)
111 c
->update(c
->hash
, data
, len
);
114 int av_hmac_final(AVHMAC
*c
, uint8_t *out
, unsigned int outlen
)
116 uint8_t block
[MAX_BLOCKLEN
];
118 if (outlen
< c
->hashlen
)
119 return AVERROR(EINVAL
);
120 c
->final(c
->hash
, out
);
122 for (i
= 0; i
< c
->keylen
; i
++)
123 block
[i
] = c
->key
[i
] ^ 0x5C;
124 for (i
= c
->keylen
; i
< c
->blocklen
; i
++)
126 c
->update(c
->hash
, block
, c
->blocklen
);
127 c
->update(c
->hash
, out
, c
->hashlen
);
128 c
->final(c
->hash
, out
);
132 int av_hmac_calc(AVHMAC
*c
, const uint8_t *data
, unsigned int len
,
133 const uint8_t *key
, unsigned int keylen
,
134 uint8_t *out
, unsigned int outlen
)
136 av_hmac_init(c
, key
, keylen
);
137 av_hmac_update(c
, data
, len
);
138 return av_hmac_final(c
, out
, outlen
);
144 static void test(AVHMAC
*hmac
, const uint8_t *key
, int keylen
,
145 const uint8_t *data
, int datalen
)
147 uint8_t buf
[MAX_HASHLEN
];
149 // Some of the test vectors are strings, where sizeof() includes the
150 // trailing null byte - remove that.
151 if (!key
[keylen
- 1])
153 if (!data
[datalen
- 1])
155 out
= av_hmac_calc(hmac
, data
, datalen
, key
, keylen
, buf
, sizeof(buf
));
156 for (i
= 0; i
< out
; i
++)
157 printf("%02x", buf
[i
]);
163 uint8_t key1
[16], key3
[16], data3
[50], key4
[63], key5
[64], key6
[65];
164 const uint8_t key2
[] = "Jefe";
165 const uint8_t data1
[] = "Hi There";
166 const uint8_t data2
[] = "what do ya want for nothing?";
167 AVHMAC
*hmac
= av_hmac_alloc(AV_HMAC_MD5
);
170 memset(key1
, 0x0b, sizeof(key1
));
171 memset(key3
, 0xaa, sizeof(key3
));
172 memset(key4
, 0x44, sizeof(key4
));
173 memset(key5
, 0x55, sizeof(key5
));
174 memset(key6
, 0x66, sizeof(key6
));
175 memset(data3
, 0xdd, sizeof(data3
));
176 // RFC 2104 test vectors
177 test(hmac
, key1
, sizeof(key1
), data1
, sizeof(data1
));
178 test(hmac
, key2
, sizeof(key2
), data2
, sizeof(data2
));
179 test(hmac
, key3
, sizeof(key3
), data3
, sizeof(data3
));
180 // Additional tests, to test cases where the key is too long
181 test(hmac
, key4
, sizeof(key4
), data1
, sizeof(data1
));
182 test(hmac
, key5
, sizeof(key5
), data2
, sizeof(data2
));
183 test(hmac
, key6
, sizeof(key6
), data3
, sizeof(data3
));