• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stddef.h>
22 #include <stdint.h>
23 #include <string.h>
24 
25 #include "attributes.h"
26 #include "hmac.h"
27 #include "md5.h"
28 #include "sha.h"
29 #include "sha512.h"
30 #include "mem.h"
31 
32 #define MAX_HASHLEN 64
33 #define MAX_BLOCKLEN 128
34 
35 typedef void (*hmac_final)(void *ctx, uint8_t *dst);
36 typedef void (*hmac_update)(void *ctx, const uint8_t *src, size_t len);
37 typedef void (*hmac_init)(void *ctx);
38 
39 struct AVHMAC {
40     void *hash;
41     int blocklen, hashlen;
42     hmac_final  final;
43     hmac_update update;
44     hmac_init   init;
45     uint8_t key[MAX_BLOCKLEN];
46     int keylen;
47 };
48 
49 #define DEFINE_SHA(bits)                           \
50 static av_cold void sha ## bits ##_init(void *ctx) \
51 {                                                  \
52     av_sha_init(ctx, bits);                        \
53 }
54 
55 #define DEFINE_SHA512(bits)                        \
56 static av_cold void sha ## bits ##_init(void *ctx) \
57 {                                                  \
58     av_sha512_init(ctx, bits);                     \
59 }
60 
61 DEFINE_SHA(160)
62 DEFINE_SHA(224)
63 DEFINE_SHA(256)
64 DEFINE_SHA512(384)
65 DEFINE_SHA512(512)
66 
av_hmac_alloc(enum AVHMACType type)67 AVHMAC *av_hmac_alloc(enum AVHMACType type)
68 {
69     AVHMAC *c = av_mallocz(sizeof(*c));
70     if (!c)
71         return NULL;
72     switch (type) {
73     case AV_HMAC_MD5:
74         c->blocklen = 64;
75         c->hashlen  = 16;
76         c->init     = (hmac_init) av_md5_init;
77         c->update   = (hmac_update) av_md5_update;
78         c->final    = (hmac_final) av_md5_final;
79         c->hash     = av_md5_alloc();
80         break;
81     case AV_HMAC_SHA1:
82         c->blocklen = 64;
83         c->hashlen  = 20;
84         c->init     = sha160_init;
85         c->update   = (hmac_update) av_sha_update;
86         c->final    = (hmac_final) av_sha_final;
87         c->hash     = av_sha_alloc();
88         break;
89     case AV_HMAC_SHA224:
90         c->blocklen = 64;
91         c->hashlen  = 28;
92         c->init     = sha224_init;
93         c->update   = (hmac_update) av_sha_update;
94         c->final    = (hmac_final) av_sha_final;
95         c->hash     = av_sha_alloc();
96         break;
97     case AV_HMAC_SHA256:
98         c->blocklen = 64;
99         c->hashlen  = 32;
100         c->init     = sha256_init;
101         c->update   = (hmac_update) av_sha_update;
102         c->final    = (hmac_final) av_sha_final;
103         c->hash     = av_sha_alloc();
104         break;
105     case AV_HMAC_SHA384:
106         c->blocklen = 128;
107         c->hashlen  = 48;
108         c->init     = sha384_init;
109         c->update   = (hmac_update) av_sha512_update;
110         c->final    = (hmac_final) av_sha512_final;
111         c->hash     = av_sha512_alloc();
112         break;
113     case AV_HMAC_SHA512:
114         c->blocklen = 128;
115         c->hashlen  = 64;
116         c->init     = sha512_init;
117         c->update   = (hmac_update) av_sha512_update;
118         c->final    = (hmac_final) av_sha512_final;
119         c->hash     = av_sha512_alloc();
120         break;
121     default:
122         av_free(c);
123         return NULL;
124     }
125     if (!c->hash) {
126         av_free(c);
127         return NULL;
128     }
129     return c;
130 }
131 
av_hmac_free(AVHMAC * c)132 void av_hmac_free(AVHMAC *c)
133 {
134     if (!c)
135         return;
136     av_freep(&c->hash);
137     av_free(c);
138 }
139 
av_hmac_init(AVHMAC * c,const uint8_t * key,unsigned int keylen)140 void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
141 {
142     int i;
143     uint8_t block[MAX_BLOCKLEN];
144     if (keylen > c->blocklen) {
145         c->init(c->hash);
146         c->update(c->hash, key, keylen);
147         c->final(c->hash, c->key);
148         c->keylen = c->hashlen;
149     } else {
150         memcpy(c->key, key, keylen);
151         c->keylen = keylen;
152     }
153     c->init(c->hash);
154     for (i = 0; i < c->keylen; i++)
155         block[i] = c->key[i] ^ 0x36;
156     for (i = c->keylen; i < c->blocklen; i++)
157         block[i] = 0x36;
158     c->update(c->hash, block, c->blocklen);
159 }
160 
av_hmac_update(AVHMAC * c,const uint8_t * data,unsigned int len)161 void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
162 {
163     c->update(c->hash, data, len);
164 }
165 
av_hmac_final(AVHMAC * c,uint8_t * out,unsigned int outlen)166 int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
167 {
168     uint8_t block[MAX_BLOCKLEN];
169     int i;
170     if (outlen < c->hashlen)
171         return AVERROR(EINVAL);
172     c->final(c->hash, out);
173     c->init(c->hash);
174     for (i = 0; i < c->keylen; i++)
175         block[i] = c->key[i] ^ 0x5C;
176     for (i = c->keylen; i < c->blocklen; i++)
177         block[i] = 0x5C;
178     c->update(c->hash, block, c->blocklen);
179     c->update(c->hash, out, c->hashlen);
180     c->final(c->hash, out);
181     return c->hashlen;
182 }
183 
av_hmac_calc(AVHMAC * c,const uint8_t * data,unsigned int len,const uint8_t * key,unsigned int keylen,uint8_t * out,unsigned int outlen)184 int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len,
185                  const uint8_t *key, unsigned int keylen,
186                  uint8_t *out, unsigned int outlen)
187 {
188     av_hmac_init(c, key, keylen);
189     av_hmac_update(c, data, len);
190     return av_hmac_final(c, out, outlen);
191 }
192