File Coverage

_algorithms.c
Criterion Covered Total %
statement 25 25 100.0
branch 1 2 50.0
condition n/a
subroutine n/a
pod n/a
total 26 27 96.3


line stmt bran cond sub pod time code
1             /* algorithms.c - the algorithms supported by the rhash library
2             *
3             * Copyright: 2011-2012 Aleksey Kravchenko
4             *
5             * Permission is hereby granted, free of charge, to any person obtaining a
6             * copy of this software and associated documentation files (the "Software"),
7             * to deal in the Software without restriction, including without limitation
8             * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9             * and/or sell copies of the Software, and to permit persons to whom the
10             * Software is furnished to do so.
11             *
12             * This program is distributed in the hope that it will be useful, but
13             * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14             * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
15             */
16              
17             #include
18             #include
19              
20             #include "byte_order.h"
21             #include "rhash.h"
22             #include "algorithms.h"
23              
24             /* header files of all supported hash sums */
25             #include "aich.h"
26             #include "crc32.h"
27             #include "ed2k.h"
28             #include "edonr.h"
29             #include "gost.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             /* note: BTIH and AICH depends on the used SHA1 algorithm */
46             # define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \
47             RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \
48             RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL)
49             #else
50             # define NEED_OPENSSL_INIT 0
51             #endif /* USE_OPENSSL */
52             #ifdef GENERATE_GOST_LOOKUP_TABLE
53             # define NEED_GOST_INIT (RHASH_GOST | RHASH_GOST_CRYPTOPRO)
54             #else
55             # define NEED_GOST_INIT 0
56             #endif /* GENERATE_GOST_LOOKUP_TABLE */
57              
58             #define RHASH_NEED_INIT_ALG (NEED_GOST_INIT | NEED_OPENSSL_INIT)
59             unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG;
60              
61             rhash_hash_info* rhash_info_table = rhash_hash_info_default;
62             int rhash_info_size = RHASH_HASH_COUNT;
63              
64             static void rhash_crc32_init(uint32_t* crc32);
65             static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size);
66             static void rhash_crc32_final(uint32_t* crc32, unsigned char* result);
67             static void rhash_crc32c_init(uint32_t* crc32);
68             static void rhash_crc32c_update(uint32_t* crc32, const unsigned char* msg, size_t size);
69             static void rhash_crc32c_final(uint32_t* crc32, unsigned char* result);
70              
71             rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" };
72             rhash_info info_crc32c = { RHASH_CRC32C, F_BE32, 4, "CRC32C", "crc32c" };
73             rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" };
74             rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" };
75             rhash_info info_sha1 = { RHASH_SHA1, F_BE32, 20, "SHA1", "sha1" };
76             rhash_info info_tiger = { RHASH_TIGER, F_LE64, 24, "TIGER", "tiger" };
77             rhash_info info_tth = { RHASH_TTH, F_BS32, 24, "TTH", "tree:tiger" };
78             rhash_info info_btih = { RHASH_BTIH, 0, 20, "BTIH", "btih" };
79             rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" };
80             rhash_info info_aich = { RHASH_AICH, F_BS32, 20, "AICH", "aich" };
81             rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" };
82             rhash_info info_rmd160 = { RHASH_RIPEMD160, F_LE32, 20, "RIPEMD-160", "ripemd160" };
83             rhash_info info_gost = { RHASH_GOST, F_LE32, 32, "GOST", "gost" };
84             rhash_info info_gostpro = { RHASH_GOST_CRYPTOPRO, F_LE32, 32, "GOST-CRYPTOPRO", "gost-cryptopro" };
85             rhash_info info_has160 = { RHASH_HAS160, F_LE32, 20, "HAS-160", "has160" };
86             rhash_info info_snf128 = { RHASH_SNEFRU128, F_BE32, 16, "SNEFRU-128", "snefru128" };
87             rhash_info info_snf256 = { RHASH_SNEFRU256, F_BE32, 32, "SNEFRU-256", "snefru256" };
88             rhash_info info_sha224 = { RHASH_SHA224, F_BE32, 28, "SHA-224", "sha224" };
89             rhash_info info_sha256 = { RHASH_SHA256, F_BE32, 32, "SHA-256", "sha256" };
90             rhash_info info_sha384 = { RHASH_SHA384, F_BE64, 48, "SHA-384", "sha384" };
91             rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" };
92             rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" };
93             rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" };
94             rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" };
95             rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" };
96             rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" };
97             rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" };
98              
99             /* some helper macros */
100             #define dgshft(name) (((char*)&((name##_ctx*)0)->hash) - (char*)0)
101             #define dgshft2(name, field) (((char*)&((name##_ctx*)0)->field) - (char*)0)
102             #define ini(name) ((pinit_t)(name##_init))
103             #define upd(name) ((pupdate_t)(name##_update))
104             #define fin(name) ((pfinal_t)(name##_final))
105             #define iuf(name) ini(name), upd(name), fin(name)
106             #define diuf(name) dgshft(name), ini(name), upd(name), fin(name)
107              
108             /* information about all supported hash functions */
109             rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] =
110             {
111             { &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */
112             { &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */
113             { &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */
114             { &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */
115             { &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */
116             { &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */
117             { &info_btih, sizeof(torrent_ctx), dgshft2(torrent, btih), iuf(bt), (pcleanup_t)bt_cleanup }, /* 160 bit */
118             { &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */
119             { &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */
120             { &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */
121             { &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */
122             { &info_gost, sizeof(gost_ctx), dgshft(gost), iuf(rhash_gost), 0 }, /* 256 bit */
123             { &info_gostpro, sizeof(gost_ctx), dgshft(gost), ini(rhash_gost_cryptopro), upd(rhash_gost), fin(rhash_gost), 0 }, /* 256 bit */
124             { &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */
125             { &info_snf128, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru128), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 128 bit */
126             { &info_snf256, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru256), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 256 bit */
127             { &info_sha224, sizeof(sha256_ctx), dgshft(sha256), ini(rhash_sha224), upd(rhash_sha256), fin(rhash_sha256), 0 }, /* 224 bit */
128             { &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 }, /* 256 bit */
129             { &info_sha384, sizeof(sha512_ctx), dgshft(sha512), ini(rhash_sha384), upd(rhash_sha512), fin(rhash_sha512), 0 }, /* 384 bit */
130             { &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 }, /* 512 bit */
131             { &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */
132             { &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */
133             { &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_224), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 224 bit */
134             { &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_256), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 256 bit */
135             { &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_384), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 384 bit */
136             { &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_512), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 512 bit */
137             { &info_crc32c, sizeof(uint32_t), 0, iuf(rhash_crc32c), 0 }, /* 32 bit */
138             };
139              
140             /**
141             * Initialize requested algorithms.
142             *
143             * @param mask ids of hash sums to initialize
144             */
145 3           void rhash_init_algorithms(unsigned mask)
146             {
147             (void)mask; /* unused now */
148              
149             /* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */
150             assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1)));
151              
152             #ifdef GENERATE_GOST_LOOKUP_TABLE
153             rhash_gost_init_table();
154             #endif
155 3           rhash_uninitialized_algorithms = 0;
156 3           }
157              
158             /**
159             * Returns information about a hash function by its hash_id.
160             *
161             * @param hash_id the id of hash algorithm
162             * @return pointer to the rhash_info structure containing the information
163             */
164 63           const rhash_info* rhash_info_by_id(unsigned hash_id)
165             {
166 63           hash_id &= RHASH_ALL_HASHES;
167             /* check that only one bit is set */
168 63 50         if (hash_id != (hash_id & -(int)hash_id)) return NULL;
169             /* note: alternative condition is (hash_id == 0 || (hash_id & (hash_id - 1)) != 0) */
170 63           return rhash_info_table[rhash_ctz(hash_id)].info;
171             }
172              
173             /* CRC32 helper functions */
174              
175             /**
176             * Initialize crc32 hash.
177             *
178             * @param crc32 pointer to the hash to initialize
179             */
180 3           static void rhash_crc32_init(uint32_t* crc32)
181             {
182 3           *crc32 = 0; /* note: context size is sizeof(uint32_t) */
183 3           }
184              
185             /**
186             * Calculate message CRC32 hash.
187             * Can be called repeatedly with chunks of the message to be hashed.
188             *
189             * @param crc32 pointer to the hash
190             * @param msg message chunk
191             * @param size length of the message chunk
192             */
193 3           static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size)
194             {
195 3           *crc32 = rhash_get_crc32(*crc32, msg, size);
196 3           }
197              
198             /**
199             * Store calculated hash into the given array.
200             *
201             * @param crc32 pointer to the current hash value
202             * @param result calculated hash in binary form
203             */
204 3           static void rhash_crc32_final(uint32_t* crc32, unsigned char* result)
205             {
206             #if defined(CPU_IA32) || defined(CPU_X64)
207             /* intel CPUs support assigment with non 32-bit aligned pointers */
208 3           *(unsigned*)result = be2me_32(*crc32);
209             #else
210             /* correct saving BigEndian integer on all archs */
211             result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16);
212             result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32);
213             #endif
214 3           }
215              
216             /**
217             * Initialize crc32c hash.
218             *
219             * @param crc32c pointer to the hash to initialize
220             */
221 2           static void rhash_crc32c_init(uint32_t* crc32c)
222             {
223 2           *crc32c = 0; /* note: context size is sizeof(uint32_t) */
224 2           }
225              
226             /**
227             * Calculate message CRC32C hash.
228             * Can be called repeatedly with chunks of the message to be hashed.
229             *
230             * @param crc32c pointer to the hash
231             * @param msg message chunk
232             * @param size length of the message chunk
233             */
234 2           static void rhash_crc32c_update(uint32_t* crc32c, const unsigned char* msg, size_t size)
235             {
236 2           *crc32c = rhash_get_crc32c(*crc32c, msg, size);
237 2           }
238              
239             /**
240             * Store calculated hash into the given array.
241             *
242             * @param crc32c pointer to the current hash value
243             * @param result calculated hash in binary form
244             */
245 2           static void rhash_crc32c_final(uint32_t* crc32c, unsigned char* result)
246             {
247             #if defined(CPU_IA32) || defined(CPU_X64)
248             /* intel CPUs support assigment with non 32-bit aligned pointers */
249 2           *(unsigned*)result = be2me_32(*crc32c);
250             #else
251             /* correct saving BigEndian integer on all archs */
252             result[0] = (unsigned char)(*crc32c >> 24), result[1] = (unsigned char)(*crc32c >> 16);
253             result[2] = (unsigned char)(*crc32c >> 8), result[3] = (unsigned char)(*crc32c);
254             #endif
255 2           }