/src/CMake/Utilities/cmlibrhash/librhash/algorithms.c
Line | Count | Source |
1 | | /* algorithms.c - the algorithms supported by the rhash library |
2 | | * |
3 | | * Copyright (c) 2011, Aleksey Kravchenko <rhash.admin@gmail.com> |
4 | | * |
5 | | * Permission to use, copy, modify, and/or distribute this software for any |
6 | | * purpose with or without fee is hereby granted. |
7 | | * |
8 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
9 | | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
10 | | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
11 | | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
12 | | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
13 | | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
14 | | * PERFORMANCE OF THIS SOFTWARE. |
15 | | */ |
16 | | |
17 | | #include "algorithms.h" |
18 | | #include "byte_order.h" |
19 | | #include "rhash.h" |
20 | | |
21 | | /* header files of all supported hash functions */ |
22 | | #if 0 |
23 | | #include "aich.h" |
24 | | #include "blake2b.h" |
25 | | #include "blake2s.h" |
26 | | #include "crc32.h" |
27 | | #include "ed2k.h" |
28 | | #include "edonr.h" |
29 | | #include "gost12.h" |
30 | | #include "gost94.h" |
31 | | #include "has160.h" |
32 | | #include "md4.h" |
33 | | #endif |
34 | | #include "md5.h" |
35 | | #if 0 |
36 | | #include "ripemd-160.h" |
37 | | #include "snefru.h" |
38 | | #endif |
39 | | #include "sha1.h" |
40 | | #include "sha256.h" |
41 | | #include "sha512.h" |
42 | | #include "sha3.h" |
43 | | #if 0 |
44 | | #include "tiger.h" |
45 | | #include "tth.h" |
46 | | #include "whirlpool.h" |
47 | | #endif |
48 | | |
49 | | #ifdef USE_OPENSSL |
50 | | # include "plug_openssl.h" |
51 | | #endif /* USE_OPENSSL */ |
52 | | #include <assert.h> |
53 | | |
54 | | #ifdef USE_OPENSSL |
55 | | /* note: BTIH and AICH depends on the used SHA1 algorithm */ |
56 | | # define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \ |
57 | | RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \ |
58 | | RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL) |
59 | | #else |
60 | | # define NEED_OPENSSL_INIT 0 |
61 | | #endif /* USE_OPENSSL */ |
62 | | |
63 | | #ifdef GENERATE_GOST94_LOOKUP_TABLE |
64 | | # define NEED_GOST94_INIT (RHASH_GOST94 | RHASH_GOST94_CRYPTOPRO) |
65 | | #else |
66 | | # define NEED_GOST94_INIT 0 |
67 | | #endif /* GENERATE_GOST94_LOOKUP_TABLE */ |
68 | | |
69 | | #define RHASH_NEED_INIT_ALG (NEED_GOST94_INIT | NEED_OPENSSL_INIT) |
70 | | unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG; |
71 | | |
72 | | rhash_hash_info* rhash_info_table = rhash_hash_info_default; |
73 | | int rhash_info_size = RHASH_HASH_COUNT; |
74 | | |
75 | | #if 0 |
76 | | static void rhash_crc32_init(uint32_t* crc32); |
77 | | static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size); |
78 | | static void rhash_crc32_final(uint32_t* crc32, unsigned char* result); |
79 | | static void rhash_crc32c_init(uint32_t* crc32); |
80 | | static void rhash_crc32c_update(uint32_t* crc32, const unsigned char* msg, size_t size); |
81 | | static void rhash_crc32c_final(uint32_t* crc32, unsigned char* result); |
82 | | #endif |
83 | | |
84 | | #if 0 |
85 | | rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" }; |
86 | | rhash_info info_crc32c = { RHASH_CRC32C, F_BE32, 4, "CRC32C", "crc32c" }; |
87 | | rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" }; |
88 | | #endif |
89 | | rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" }; |
90 | | rhash_info info_sha1 = { RHASH_SHA1, F_BE32, 20, "SHA1", "sha1" }; |
91 | | #if 0 |
92 | | rhash_info info_tiger = { RHASH_TIGER, F_LE64, 24, "TIGER", "tiger" }; |
93 | | rhash_info info_tth = { RHASH_TTH, F_BS32 | F_SPCEXP, 24, "TTH", "tree:tiger" }; |
94 | | rhash_info info_btih = { RHASH_BTIH, F_SPCEXP, 20, "BTIH", "btih" }; |
95 | | rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" }; |
96 | | rhash_info info_aich = { RHASH_AICH, F_BS32 | F_SPCEXP, 20, "AICH", "aich" }; |
97 | | rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" }; |
98 | | rhash_info info_rmd160 = { RHASH_RIPEMD160, F_LE32, 20, "RIPEMD-160", "ripemd160" }; |
99 | | rhash_info info_gost12_256 = { RHASH_GOST12_256, F_LE64, 32, "GOST12-256", "gost12-256" }; |
100 | | rhash_info info_gost12_512 = { RHASH_GOST12_512, F_LE64, 64, "GOST12-512", "gost12-512" }; |
101 | | rhash_info info_gost94 = { RHASH_GOST94, F_LE32, 32, "GOST94", "gost94" }; |
102 | | rhash_info info_gost94pro = { RHASH_GOST94_CRYPTOPRO, F_LE32, 32, "GOST94-CRYPTOPRO", "gost94-cryptopro" }; |
103 | | rhash_info info_has160 = { RHASH_HAS160, F_LE32, 20, "HAS-160", "has160" }; |
104 | | rhash_info info_snf128 = { RHASH_SNEFRU128, F_BE32, 16, "SNEFRU-128", "snefru128" }; |
105 | | rhash_info info_snf256 = { RHASH_SNEFRU256, F_BE32, 32, "SNEFRU-256", "snefru256" }; |
106 | | #endif |
107 | | rhash_info info_sha224 = { RHASH_SHA224, F_BE32, 28, "SHA-224", "sha224" }; |
108 | | rhash_info info_sha256 = { RHASH_SHA256, F_BE32, 32, "SHA-256", "sha256" }; |
109 | | rhash_info info_sha384 = { RHASH_SHA384, F_BE64, 48, "SHA-384", "sha384" }; |
110 | | rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" }; |
111 | | #if 0 |
112 | | rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" }; |
113 | | rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" }; |
114 | | rhash_info info_blake2s = { RHASH_BLAKE2S, F_LE32, 32, "BLAKE2S", "blake2s" }; |
115 | | rhash_info info_blake2b = { RHASH_BLAKE2B, F_LE64, 64, "BLAKE2B", "blake2b" }; |
116 | | #endif |
117 | | rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" }; |
118 | | rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" }; |
119 | | rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" }; |
120 | | rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" }; |
121 | | |
122 | | /* some helper macros */ |
123 | | #define dgshft(name) ((uintptr_t)((char*)&((name##_ctx*)0)->hash)) |
124 | | #define dgshft2(name, field) ((uintptr_t)((char*)&((name##_ctx*)0)->field)) |
125 | | #define ini(name) ((pinit_t)(name##_init)) |
126 | | #define upd(name) ((pupdate_t)(name##_update)) |
127 | | #define fin(name) ((pfinal_t)(name##_final)) |
128 | | #define iuf(name) ini(name), upd(name), fin(name) |
129 | | #define iuf2(name1, name2) ini(name1), upd(name2), fin(name2) |
130 | | |
131 | | /* information about all supported hash functions */ |
132 | | rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] = |
133 | | { |
134 | | #if 0 |
135 | | { &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */ |
136 | | { &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */ |
137 | | #endif |
138 | | { &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */ |
139 | | { &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */ |
140 | | #if 0 |
141 | | { &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */ |
142 | | { &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */ |
143 | | { &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */ |
144 | | { &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */ |
145 | | { &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */ |
146 | | { &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */ |
147 | | { &info_gost94, sizeof(gost94_ctx), dgshft(gost94), iuf(rhash_gost94), 0 }, /* 256 bit */ |
148 | | { &info_gost94pro, sizeof(gost94_ctx), dgshft(gost94), iuf2(rhash_gost94_cryptopro, rhash_gost94), 0 }, /* 256 bit */ |
149 | | { &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */ |
150 | | { &info_gost12_256, sizeof(gost12_ctx), dgshft2(gost12, h) + 32, iuf2(rhash_gost12_256, rhash_gost12), 0 }, /* 256 bit */ |
151 | | { &info_gost12_512, sizeof(gost12_ctx), dgshft2(gost12, h), iuf2(rhash_gost12_512, rhash_gost12), 0 }, /* 512 bit */ |
152 | | #endif |
153 | | { &info_sha224, sizeof(sha256_ctx), dgshft(sha256), iuf2(rhash_sha224, rhash_sha256), 0 }, /* 224 bit */ |
154 | | { &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 }, /* 256 bit */ |
155 | | { &info_sha384, sizeof(sha512_ctx), dgshft(sha512), iuf2(rhash_sha384, rhash_sha512), 0 }, /* 384 bit */ |
156 | | { &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 }, /* 512 bit */ |
157 | | #if 0 |
158 | | { &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */ |
159 | | { &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */ |
160 | | #endif |
161 | | { &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_224, rhash_sha3), 0 }, /* 224 bit */ |
162 | | { &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_256, rhash_sha3), 0 }, /* 256 bit */ |
163 | | { &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_384, rhash_sha3), 0 }, /* 384 bit */ |
164 | | { &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_512, rhash_sha3), 0 }, /* 512 bit */ |
165 | | #if 0 |
166 | | { &info_crc32c, sizeof(uint32_t), 0, iuf(rhash_crc32c), 0 }, /* 32 bit */ |
167 | | { &info_snf128, sizeof(snefru_ctx), dgshft(snefru), iuf2(rhash_snefru128, rhash_snefru), 0 }, /* 128 bit */ |
168 | | { &info_snf256, sizeof(snefru_ctx), dgshft(snefru), iuf2(rhash_snefru256, rhash_snefru), 0 }, /* 256 bit */ |
169 | | { &info_blake2s, sizeof(blake2s_ctx), dgshft(blake2s), iuf(rhash_blake2s), 0 }, /* 256 bit */ |
170 | | { &info_blake2b, sizeof(blake2b_ctx), dgshft(blake2b), iuf(rhash_blake2b), 0 }, /* 512 bit */ |
171 | | #endif |
172 | | }; |
173 | | |
174 | | /** |
175 | | * Initialize requested algorithms. |
176 | | * |
177 | | * @param mask ids of hash sums to initialize |
178 | | */ |
179 | | void rhash_init_algorithms(unsigned mask) |
180 | 0 | { |
181 | 0 | (void)mask; /* unused now */ |
182 | | |
183 | | /* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */ |
184 | 0 | assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1))); |
185 | |
|
186 | | #ifdef GENERATE_GOST94_LOOKUP_TABLE |
187 | | rhash_gost94_init_table(); |
188 | | #endif |
189 | 0 | rhash_uninitialized_algorithms = 0; |
190 | 0 | } |
191 | | |
192 | | /** |
193 | | * Returns information about a hash function by its hash_id. |
194 | | * |
195 | | * @param hash_id the id of hash algorithm |
196 | | * @return pointer to the rhash_info structure containing the information |
197 | | */ |
198 | | const rhash_info* rhash_info_by_id(unsigned hash_id) |
199 | 0 | { |
200 | 0 | hash_id &= RHASH_ALL_HASHES; |
201 | | /* check that one and only one bit is set */ |
202 | 0 | if (!hash_id || (hash_id & (hash_id - 1)) != 0) return NULL; |
203 | 0 | return rhash_info_table[rhash_ctz(hash_id)].info; |
204 | 0 | } |
205 | | |
206 | | #if 0 |
207 | | /* CRC32 helper functions */ |
208 | | |
209 | | /** |
210 | | * Initialize crc32 hash. |
211 | | * |
212 | | * @param crc32 pointer to the hash to initialize |
213 | | */ |
214 | | static void rhash_crc32_init(uint32_t* crc32) |
215 | | { |
216 | | *crc32 = 0; /* note: context size is sizeof(uint32_t) */ |
217 | | } |
218 | | |
219 | | /** |
220 | | * Calculate message CRC32 hash. |
221 | | * Can be called repeatedly with chunks of the message to be hashed. |
222 | | * |
223 | | * @param crc32 pointer to the hash |
224 | | * @param msg message chunk |
225 | | * @param size length of the message chunk |
226 | | */ |
227 | | static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size) |
228 | | { |
229 | | *crc32 = rhash_get_crc32(*crc32, msg, size); |
230 | | } |
231 | | |
232 | | /** |
233 | | * Store calculated hash into the given array. |
234 | | * |
235 | | * @param crc32 pointer to the current hash value |
236 | | * @param result calculated hash in binary form |
237 | | */ |
238 | | static void rhash_crc32_final(uint32_t* crc32, unsigned char* result) |
239 | | { |
240 | | #if defined(CPU_IA32) || defined(CPU_X64) |
241 | | /* intel CPUs support assigment with non 32-bit aligned pointers */ |
242 | | *(unsigned*)result = be2me_32(*crc32); |
243 | | #else |
244 | | /* correct saving BigEndian integer on all archs */ |
245 | | result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16); |
246 | | result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32); |
247 | | #endif |
248 | | } |
249 | | |
250 | | /** |
251 | | * Initialize crc32c hash. |
252 | | * |
253 | | * @param crc32c pointer to the hash to initialize |
254 | | */ |
255 | | static void rhash_crc32c_init(uint32_t* crc32c) |
256 | | { |
257 | | *crc32c = 0; /* note: context size is sizeof(uint32_t) */ |
258 | | } |
259 | | |
260 | | /** |
261 | | * Calculate message CRC32C hash. |
262 | | * Can be called repeatedly with chunks of the message to be hashed. |
263 | | * |
264 | | * @param crc32c pointer to the hash |
265 | | * @param msg message chunk |
266 | | * @param size length of the message chunk |
267 | | */ |
268 | | static void rhash_crc32c_update(uint32_t* crc32c, const unsigned char* msg, size_t size) |
269 | | { |
270 | | *crc32c = rhash_get_crc32c(*crc32c, msg, size); |
271 | | } |
272 | | |
273 | | /** |
274 | | * Store calculated hash into the given array. |
275 | | * |
276 | | * @param crc32c pointer to the current hash value |
277 | | * @param result calculated hash in binary form |
278 | | */ |
279 | | static void rhash_crc32c_final(uint32_t* crc32c, unsigned char* result) |
280 | | { |
281 | | #if defined(CPU_IA32) || defined(CPU_X64) |
282 | | /* intel CPUs support assigment with non 32-bit aligned pointers */ |
283 | | *(unsigned*)result = be2me_32(*crc32c); |
284 | | #else |
285 | | /* correct saving BigEndian integer on all archs */ |
286 | | result[0] = (unsigned char)(*crc32c >> 24), result[1] = (unsigned char)(*crc32c >> 16); |
287 | | result[2] = (unsigned char)(*crc32c >> 8), result[3] = (unsigned char)(*crc32c); |
288 | | #endif |
289 | | } |
290 | | #endif |
291 | | |
292 | | #if !defined(NO_IMPORT_EXPORT) |
293 | | /** |
294 | | * Export a hash function context to a memory region, |
295 | | * or calculate the size required for context export. |
296 | | * |
297 | | * @param hash_id identifier of the hash function |
298 | | * @param ctx the algorithm context containing current hashing state |
299 | | * @param out pointer to the memory region or NULL |
300 | | * @param size size of memory region |
301 | | * @return the size of the exported data on success, 0 on fail. |
302 | | */ |
303 | | size_t rhash_export_alg(unsigned hash_id, const void* ctx, void* out, size_t size) |
304 | | { |
305 | | switch (hash_id) |
306 | | { |
307 | | case RHASH_TTH: |
308 | | return rhash_tth_export((const tth_ctx*)ctx, out, size); |
309 | | case RHASH_AICH: |
310 | | return rhash_aich_export((const aich_ctx*)ctx, out, size); |
311 | | } |
312 | | return 0; |
313 | | } |
314 | | |
315 | | /** |
316 | | * Import a hash function context from a memory region. |
317 | | * |
318 | | * @param hash_id identifier of the hash function |
319 | | * @param ctx pointer to the algorithm context |
320 | | * @param in pointer to the data to import |
321 | | * @param size size of data to import |
322 | | * @return the size of the imported data on success, 0 on fail. |
323 | | */ |
324 | | size_t rhash_import_alg(unsigned hash_id, void* ctx, const void* in, size_t size) |
325 | | { |
326 | | switch (hash_id) |
327 | | { |
328 | | case RHASH_TTH: |
329 | | return rhash_tth_import((tth_ctx*)ctx, in, size); |
330 | | case RHASH_AICH: |
331 | | return rhash_aich_import((aich_ctx*)ctx, in, size); |
332 | | } |
333 | | return 0; |
334 | | } |
335 | | #endif /* !defined(NO_IMPORT_EXPORT) */ |
336 | | |
337 | | #ifdef USE_OPENSSL |
338 | | void rhash_load_sha1_methods(rhash_hashing_methods* methods, int methods_type) |
339 | | { |
340 | | int use_openssl; |
341 | | switch (methods_type) { |
342 | | case METHODS_OPENSSL: |
343 | | use_openssl = 1; |
344 | | break; |
345 | | case METHODS_SELECTED: |
346 | | assert(rhash_info_table[3].info->hash_id == RHASH_SHA1); |
347 | | use_openssl = ARE_OPENSSL_METHODS(rhash_info_table[3]); |
348 | | break; |
349 | | default: |
350 | | use_openssl = 0; |
351 | | break; |
352 | | } |
353 | | if (use_openssl) { |
354 | | methods->init = rhash_ossl_sha1_init(); |
355 | | methods->update = rhash_ossl_sha1_update(); |
356 | | methods->final = rhash_ossl_sha1_final(); |
357 | | } else { |
358 | | methods->init = (pinit_t)&rhash_sha1_init; |
359 | | methods->update = (pupdate_t)&rhash_sha1_update; |
360 | | methods->final = (pfinal_t)&rhash_sha1_final; |
361 | | } |
362 | | } |
363 | | #endif |