Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger@gmx.de> | |
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 | #include <stdint.h> | |
21 | #include "hash.h" | |
22 | ||
23 | #include "adler32.h" | |
24 | #include "crc.h" | |
25 | #include "md5.h" | |
26 | #include "murmur3.h" | |
27 | #include "ripemd.h" | |
28 | #include "sha.h" | |
29 | #include "sha512.h" | |
30 | ||
31 | #include "avstring.h" | |
32 | #include "base64.h" | |
33 | #include "error.h" | |
34 | #include "intreadwrite.h" | |
35 | #include "mem.h" | |
36 | ||
37 | enum hashtype { | |
38 | MD5, | |
39 | MURMUR3, | |
40 | RIPEMD128, | |
41 | RIPEMD160, | |
42 | RIPEMD256, | |
43 | RIPEMD320, | |
44 | SHA160, | |
45 | SHA224, | |
46 | SHA256, | |
47 | SHA512_224, | |
48 | SHA512_256, | |
49 | SHA384, | |
50 | SHA512, | |
51 | CRC32, | |
52 | ADLER32, | |
53 | NUM_HASHES | |
54 | }; | |
55 | ||
56 | typedef struct AVHashContext { | |
57 | void *ctx; | |
58 | enum hashtype type; | |
59 | const AVCRC *crctab; | |
60 | uint32_t crc; | |
61 | } AVHashContext; | |
62 | ||
63 | static const struct { | |
64 | const char *name; | |
65 | int size; | |
66 | } hashdesc[] = { | |
67 | [MD5] = {"MD5", 16}, | |
68 | [MURMUR3] = {"murmur3", 16}, | |
69 | [RIPEMD128] = {"RIPEMD128", 16}, | |
70 | [RIPEMD160] = {"RIPEMD160", 20}, | |
71 | [RIPEMD256] = {"RIPEMD256", 32}, | |
72 | [RIPEMD320] = {"RIPEMD320", 40}, | |
73 | [SHA160] = {"SHA160", 20}, | |
74 | [SHA224] = {"SHA224", 28}, | |
75 | [SHA256] = {"SHA256", 32}, | |
76 | [SHA512_224] = {"SHA512/224", 28}, | |
77 | [SHA512_256] = {"SHA512/256", 32}, | |
78 | [SHA384] = {"SHA384", 48}, | |
79 | [SHA512] = {"SHA512", 64}, | |
80 | [CRC32] = {"CRC32", 4}, | |
81 | [ADLER32] = {"adler32", 4}, | |
82 | }; | |
83 | ||
84 | const char *av_hash_names(int i) | |
85 | { | |
86 | if (i < 0 || i >= NUM_HASHES) return NULL; | |
87 | return hashdesc[i].name; | |
88 | } | |
89 | ||
90 | const char *av_hash_get_name(const AVHashContext *ctx) | |
91 | { | |
92 | return hashdesc[ctx->type].name; | |
93 | } | |
94 | ||
95 | int av_hash_get_size(const AVHashContext *ctx) | |
96 | { | |
97 | return hashdesc[ctx->type].size; | |
98 | } | |
99 | ||
100 | int av_hash_alloc(AVHashContext **ctx, const char *name) | |
101 | { | |
102 | AVHashContext *res; | |
103 | int i; | |
104 | *ctx = NULL; | |
105 | for (i = 0; i < NUM_HASHES; i++) | |
106 | if (av_strcasecmp(name, hashdesc[i].name) == 0) | |
107 | break; | |
108 | if (i >= NUM_HASHES) return AVERROR(EINVAL); | |
109 | res = av_mallocz(sizeof(*res)); | |
110 | if (!res) return AVERROR(ENOMEM); | |
111 | res->type = i; | |
112 | switch (i) { | |
113 | case MD5: res->ctx = av_md5_alloc(); break; | |
114 | case MURMUR3: res->ctx = av_murmur3_alloc(); break; | |
115 | case RIPEMD128: | |
116 | case RIPEMD160: | |
117 | case RIPEMD256: | |
118 | case RIPEMD320: res->ctx = av_ripemd_alloc(); break; | |
119 | case SHA160: | |
120 | case SHA224: | |
121 | case SHA256: res->ctx = av_sha_alloc(); break; | |
122 | case SHA512_224: | |
123 | case SHA512_256: | |
124 | case SHA384: | |
125 | case SHA512: res->ctx = av_sha512_alloc(); break; | |
126 | case CRC32: res->crctab = av_crc_get_table(AV_CRC_32_IEEE_LE); break; | |
127 | case ADLER32: break; | |
128 | } | |
129 | if (i != ADLER32 && i != CRC32 && !res->ctx) { | |
130 | av_free(res); | |
131 | return AVERROR(ENOMEM); | |
132 | } | |
133 | *ctx = res; | |
134 | return 0; | |
135 | } | |
136 | ||
137 | void av_hash_init(AVHashContext *ctx) | |
138 | { | |
139 | switch (ctx->type) { | |
140 | case MD5: av_md5_init(ctx->ctx); break; | |
141 | case MURMUR3: av_murmur3_init(ctx->ctx); break; | |
142 | case RIPEMD128: av_ripemd_init(ctx->ctx, 128); break; | |
143 | case RIPEMD160: av_ripemd_init(ctx->ctx, 160); break; | |
144 | case RIPEMD256: av_ripemd_init(ctx->ctx, 256); break; | |
145 | case RIPEMD320: av_ripemd_init(ctx->ctx, 320); break; | |
146 | case SHA160: av_sha_init(ctx->ctx, 160); break; | |
147 | case SHA224: av_sha_init(ctx->ctx, 224); break; | |
148 | case SHA256: av_sha_init(ctx->ctx, 256); break; | |
149 | case SHA512_224: av_sha512_init(ctx->ctx, 224); break; | |
150 | case SHA512_256: av_sha512_init(ctx->ctx, 256); break; | |
151 | case SHA384: av_sha512_init(ctx->ctx, 384); break; | |
152 | case SHA512: av_sha512_init(ctx->ctx, 512); break; | |
153 | case CRC32: ctx->crc = UINT32_MAX; break; | |
154 | case ADLER32: ctx->crc = 1; break; | |
155 | } | |
156 | } | |
157 | ||
158 | void av_hash_update(AVHashContext *ctx, const uint8_t *src, int len) | |
159 | { | |
160 | switch (ctx->type) { | |
161 | case MD5: av_md5_update(ctx->ctx, src, len); break; | |
162 | case MURMUR3: av_murmur3_update(ctx->ctx, src, len); break; | |
163 | case RIPEMD128: | |
164 | case RIPEMD160: | |
165 | case RIPEMD256: | |
166 | case RIPEMD320: av_ripemd_update(ctx->ctx, src, len); break; | |
167 | case SHA160: | |
168 | case SHA224: | |
169 | case SHA256: av_sha_update(ctx->ctx, src, len); break; | |
170 | case SHA512_224: | |
171 | case SHA512_256: | |
172 | case SHA384: | |
173 | case SHA512: av_sha512_update(ctx->ctx, src, len); break; | |
174 | case CRC32: ctx->crc = av_crc(ctx->crctab, ctx->crc, src, len); break; | |
175 | case ADLER32: ctx->crc = av_adler32_update(ctx->crc, src, len); break; | |
176 | } | |
177 | } | |
178 | ||
179 | void av_hash_final(AVHashContext *ctx, uint8_t *dst) | |
180 | { | |
181 | switch (ctx->type) { | |
182 | case MD5: av_md5_final(ctx->ctx, dst); break; | |
183 | case MURMUR3: av_murmur3_final(ctx->ctx, dst); break; | |
184 | case RIPEMD128: | |
185 | case RIPEMD160: | |
186 | case RIPEMD256: | |
187 | case RIPEMD320: av_ripemd_final(ctx->ctx, dst); break; | |
188 | case SHA160: | |
189 | case SHA224: | |
190 | case SHA256: av_sha_final(ctx->ctx, dst); break; | |
191 | case SHA512_224: | |
192 | case SHA512_256: | |
193 | case SHA384: | |
194 | case SHA512: av_sha512_final(ctx->ctx, dst); break; | |
195 | case CRC32: AV_WB32(dst, ctx->crc ^ UINT32_MAX); break; | |
196 | case ADLER32: AV_WB32(dst, ctx->crc); break; | |
197 | } | |
198 | } | |
199 | ||
200 | void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size) | |
201 | { | |
202 | uint8_t buf[AV_HASH_MAX_SIZE]; | |
203 | unsigned rsize = av_hash_get_size(ctx); | |
204 | ||
205 | av_hash_final(ctx, buf); | |
206 | memcpy(dst, buf, FFMIN(size, rsize)); | |
207 | if (size > rsize) | |
208 | memset(dst + rsize, 0, size - rsize); | |
209 | } | |
210 | ||
211 | void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size) | |
212 | { | |
213 | uint8_t buf[AV_HASH_MAX_SIZE]; | |
214 | unsigned rsize = av_hash_get_size(ctx), i; | |
215 | ||
216 | av_hash_final(ctx, buf); | |
217 | for (i = 0; i < FFMIN(rsize, size / 2); i++) | |
218 | snprintf(dst + i * 2, size - i * 2, "%02x", buf[i]); | |
219 | } | |
220 | ||
221 | void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size) | |
222 | { | |
223 | uint8_t buf[AV_HASH_MAX_SIZE], b64[AV_BASE64_SIZE(AV_HASH_MAX_SIZE)]; | |
224 | unsigned rsize = av_hash_get_size(ctx), osize; | |
225 | ||
226 | av_hash_final(ctx, buf); | |
227 | av_base64_encode(b64, sizeof(b64), buf, rsize); | |
228 | osize = AV_BASE64_SIZE(rsize); | |
229 | memcpy(dst, b64, FFMIN(osize, size)); | |
230 | if (size < osize) | |
231 | dst[size - 1] = 0; | |
232 | } | |
233 | ||
234 | void av_hash_freep(AVHashContext **ctx) | |
235 | { | |
236 | if (*ctx) | |
237 | av_freep(&(*ctx)->ctx); | |
238 | av_freep(ctx); | |
239 | } |