Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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