File Coverage

_algorithms.c
Criterion Covered Total %
statement 25 46 54.3
branch 2 4 50.0
condition n/a
subroutine n/a
pod n/a
total 27 50 54.0


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