summaryrefslogtreecommitdiff
path: root/Utilities/cmlibrhash/librhash/rhash.h
blob: c0117626eed2aad65ed8d4b6bb2c009cdf945d90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
/** @file rhash.h LibRHash interface */
#ifndef RHASH_H
#define RHASH_H

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef RHASH_API
/**
 * Modifier for LibRHash functions
 */
# define RHASH_API
#endif

/**
 * Identifiers of supported hash functions.
 * The rhash_init() function allows mixing several ids using
 * binary OR, to calculate several hash functions for one message.
 */
enum rhash_ids
{
#if 0
	RHASH_CRC32 = 0x01,
	RHASH_MD4   = 0x02,
	RHASH_MD5   = 0x04,
	RHASH_SHA1  = 0x08,
	RHASH_TIGER = 0x10,
	RHASH_TTH   = 0x20,
	RHASH_BTIH  = 0x40,
	RHASH_ED2K  = 0x80,
	RHASH_AICH  = 0x100,
	RHASH_WHIRLPOOL = 0x200,
	RHASH_RIPEMD160 = 0x400,
	RHASH_GOST94    = 0x800,
	RHASH_GOST94_CRYPTOPRO = 0x1000,
	RHASH_HAS160     = 0x2000,
	RHASH_GOST12_256 = 0x4000,
	RHASH_GOST12_512 = 0x8000,
	RHASH_SHA224    = 0x10000,
	RHASH_SHA256    = 0x20000,
	RHASH_SHA384    = 0x40000,
	RHASH_SHA512    = 0x80000,
	RHASH_EDONR256  = 0x0100000,
	RHASH_EDONR512  = 0x0200000,
	RHASH_SHA3_224  = 0x0400000,
	RHASH_SHA3_256  = 0x0800000,
	RHASH_SHA3_384  = 0x1000000,
	RHASH_SHA3_512  = 0x2000000,
	RHASH_CRC32C    = 0x4000000,
	RHASH_SNEFRU128 = 0x8000000,
	RHASH_SNEFRU256 = 0x10000000,

	/**
	 * The bit-mask containing all supported hashe functions.
	 */
	RHASH_ALL_HASHES = RHASH_CRC32 | RHASH_CRC32C | RHASH_MD4 | RHASH_MD5 |
		RHASH_ED2K | RHASH_SHA1 |RHASH_TIGER | RHASH_TTH |
		RHASH_GOST94 | RHASH_GOST94_CRYPTOPRO | RHASH_GOST12_256 | RHASH_GOST12_512 |
		RHASH_BTIH | RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 |
		RHASH_HAS160 | RHASH_SNEFRU128 | RHASH_SNEFRU256 |
		RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 |
		RHASH_SHA3_224 | RHASH_SHA3_256 | RHASH_SHA3_384 | RHASH_SHA3_512 |
		RHASH_EDONR256 | RHASH_EDONR512,

	RHASH_GOST = RHASH_GOST94, /* deprecated constant name */
	RHASH_GOST_CRYPTOPRO = RHASH_GOST94_CRYPTOPRO, /* deprecated constant name */
	/**
	 * The number of supported hash functions.
	 */
	RHASH_HASH_COUNT = 29
#else
	RHASH_MD5        = 0x01,
	RHASH_SHA1       = 0x02,
	RHASH_SHA224     = 0x04,
	RHASH_SHA256     = 0x08,
	RHASH_SHA384     = 0x10,
	RHASH_SHA512     = 0x20,
	RHASH_SHA3_224   = 0x40,
	RHASH_SHA3_256   = 0x80,
	RHASH_SHA3_384   = 0x100,
	RHASH_SHA3_512   = 0x200,
	RHASH_ALL_HASHES =
		RHASH_MD5 |
		RHASH_SHA1 |
		RHASH_SHA224 |
		RHASH_SHA256 |
		RHASH_SHA384 |
		RHASH_SHA512 |
		RHASH_SHA3_224 |
		RHASH_SHA3_256 |
		RHASH_SHA3_384 |
		RHASH_SHA3_512,
	RHASH_HASH_COUNT = 10
#endif
};

/**
 * The rhash context structure contains contexts for several hash functions.
 */
typedef struct rhash_context
{
	/**
	 * The size of the hashed message.
	 */
	unsigned long long msg_size;

	/**
	 * The bit-mask containing identifiers of the hashes being calculated.
	 */
	unsigned hash_id;
} rhash_context;

#ifndef LIBRHASH_RHASH_CTX_DEFINED
#define LIBRHASH_RHASH_CTX_DEFINED
/**
 * Hashing context.
 */
typedef struct rhash_context* rhash;
#endif /* LIBRHASH_RHASH_CTX_DEFINED */

/**
 * Type of a callback to be called periodically while hashing a file.
 */
typedef void (*rhash_callback_t)(void* data, unsigned long long offset);

/**
 * Initialize static data of rhash algorithms
 */
RHASH_API void rhash_library_init(void);


/* HIGH-LEVEL LIBRHASH INTERFACE */

/**
 * Compute a hash of the given message.
 *
 * @param hash_id id of hash sum to compute
 * @param message the message to process
 * @param length message length
 * @param result buffer to receive binary hash string
 * @return 0 on success, -1 on error
 */
RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result);

/**
 * Compute a single hash for given file.
 *
 * @param hash_id id of hash sum to compute
 * @param filepath path to the file to hash
 * @param result buffer to receive hash value with the lowest requested id
 * @return 0 on success, -1 on error and errno is set
 */
RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result);

#ifdef _WIN32
/**
 * Compute a single hash for given file (Windows-specific function).
 *
 * @param hash_id id of hash sum to compute
 * @param filepath path to the file to hash
 * @param result buffer to receive hash value with the lowest requested id
 * @return 0 on success, -1 on error, -1 on error and errno is set
 */
RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result);
#endif


/* LOW-LEVEL LIBRHASH INTERFACE */

/**
 * Allocate and initialize RHash context for calculating hash(es).
 * After initializing rhash_update()/rhash_final() functions should be used.
 * Then the context must be freed by calling rhash_free().
 *
 * @param hash_id union of bit flags, containing ids of hashes to calculate.
 * @return initialized rhash context, NULL on error and errno is set
 */
RHASH_API rhash rhash_init(unsigned hash_id);

/**
 * Calculate hashes of message.
 * Can be called repeatedly with chunks of the message to be hashed.
 *
 * @param ctx the rhash context
 * @param message message chunk
 * @param length length of the message chunk
 * @return 0 on success; On fail return -1 and set errno
 */
RHASH_API int rhash_update(rhash ctx, const void* message, size_t length);

/**
 * Hash a file or stream. Multiple hashes can be computed.
 * First, inintialize ctx parameter with rhash_init() before calling
 * rhash_file_update(). Then use rhash_final() and rhash_print()
 * to retrive hash values. Finaly call rhash_free() on ctx
 * to free allocated memory or call rhash_reset() to reuse ctx.
 *
 * @param ctx rhash context
 * @param fd descriptor of the file to hash
 * @return 0 on success, -1 on error and errno is set
 */
RHASH_API int rhash_file_update(rhash ctx, FILE* fd);

/**
 * Finalize hash calculation and optionally store the first hash.
 *
 * @param ctx the rhash context
 * @param first_result optional buffer to store a calculated hash with the lowest available id
 * @return 0 on success; On fail return -1 and set errno
 */
RHASH_API int rhash_final(rhash ctx, unsigned char* first_result);

/**
 * Re-initialize RHash context to reuse it.
 * Useful to speed up processing of many small messages.
 *
 * @param ctx context to reinitialize
 */
RHASH_API void rhash_reset(rhash ctx);

/**
 * Free RHash context memory.
 *
 * @param ctx the context to free.
 */
RHASH_API void rhash_free(rhash ctx);

/**
 * Set the callback function to be called from the
 * rhash_file() and rhash_file_update() functions
 * on processing every file block. The file block
 * size is set internally by rhash and now is 8 KiB.
 *
 * @param ctx rhash context
 * @param callback pointer to the callback function
 * @param callback_data pointer to data passed to the callback
 */
RHASH_API void  rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data);


/* INFORMATION FUNCTIONS */

/**
 * Returns the number of supported hash algorithms.
 *
 * @return the number of supported hash functions
 */
RHASH_API int  rhash_count(void); /* number of supported hashes */

/**
 * Returns size of binary digest for given hash algorithm.
 *
 * @param hash_id the id of hash algorithm
 * @return digest size in bytes
 */
RHASH_API int  rhash_get_digest_size(unsigned hash_id); /* size of binary message digest */

/**
 * Returns length of digest hash string in default output format.
 *
 * @param hash_id the id of hash algorithm
 * @return the length of hash string
 */
RHASH_API int  rhash_get_hash_length(unsigned hash_id); /* length of formatted hash string */

/**
 * Detect default digest output format for given hash algorithm.
 *
 * @param hash_id the id of hash algorithm
 * @return 1 for base32 format, 0 for hexadecimal
 */
RHASH_API int  rhash_is_base32(unsigned hash_id); /* default digest output format */

/**
 * Returns a name of given hash algorithm.
 *
 * @param hash_id the id of hash algorithm
 * @return algorithm name
 */
RHASH_API const char* rhash_get_name(unsigned hash_id); /* get hash function name */

/**
 * Returns a name part of magnet urn of the given hash algorithm.
 * Such magnet_name is used to generate a magnet link of the form
 * urn:&lt;magnet_name&gt;=&lt;hash_value&gt;.
 *
 * @param hash_id the id of hash algorithm
 * @return name
 */
RHASH_API const char* rhash_get_magnet_name(unsigned hash_id); /* get name part of magnet urn */

/* HASH SUM OUTPUT INTERFACE */

#if 0
/**
 * Flags for printing a hash sum.
 */
enum rhash_print_sum_flags
{
	/*
	 * Print in a default format
	 */
	RHPR_DEFAULT   = 0x0,
	/*
	 * Output as binary message digest
	 */
	RHPR_RAW       = 0x1,
	/*
	 * Print as a hexadecimal string
	 */
	RHPR_HEX       = 0x2,
	/*
	 * Print as a base32-encoded string
	 */
	RHPR_BASE32    = 0x3,
	/*
	 * Print as a base64-encoded string
	 */
	RHPR_BASE64    = 0x4,
	/*
	 * Print as an uppercase string. Can be used
	 * for base32 or hexadecimal format only.
	 */
	RHPR_UPPERCASE = 0x8,
	/*
	 * Reverse hash bytes. Can be used for GOST hash.
	 */
	RHPR_REVERSE   = 0x10,
	/*
	 * Don't print 'magnet:?' prefix in rhash_print_magnet
	 */
	RHPR_NO_MAGNET  = 0x20,
	/*
	 * Print file size in rhash_print_magnet
	 */
	RHPR_FILESIZE  = 0x40,
	/*
	 * Print as URL-encoded string
	 */
	RHPR_URLENCODE  = 0x80
};
#endif


/**
 * Print a text presentation of a given hash sum to the specified buffer.
 *
 * @param output a buffer to print the hash to
 * @param bytes a hash sum to print
 * @param size a size of hash sum in bytes
 * @param flags  a bit-mask controlling how to format the hash sum,
 *               can be a mix of the flags: RHPR_RAW, RHPR_HEX, RHPR_BASE32,
 *               RHPR_BASE64, RHPR_URLENCODE, RHPR_UPPERCASE, RHPR_REVERSE
 * @return the number of written characters
 */
RHASH_API size_t rhash_print_bytes(char* output,
	const unsigned char* bytes, size_t size, int flags);

/**
 * Print text presentation of a hash sum with given hash_id to the specified
 * output buffer. If the hash_id is zero, then print the hash sum with
 * the lowest id stored in the hash context.
 * The function call fails if the context doesn't include a hash with the
 * given hash_id.
 *
 * @param output a buffer to print the hash to
 * @param ctx    algorithms state
 * @param hash_id id of the hash sum to print or 0 to print the first hash
 *                saved in the context.
 * @param flags  a bitmask controlling how to print the hash. Can contain flags
 *               RHPR_UPPERCASE, RHPR_HEX, RHPR_BASE32, RHPR_BASE64, etc.
 * @return the number of written characters on success or 0 on fail
 */
RHASH_API size_t rhash_print(char* output, rhash ctx, unsigned hash_id,
	int flags);

/**
 * Print magnet link with given filepath and calculated hash sums into the
 * output buffer. The hash_mask can limit which hash values will be printed.
 * The function returns the size of the required buffer.
 * If output is NULL the .
 *
 * @param output a string buffer to receive the magnet link or NULL
 * @param filepath the file path to be printed or NULL
 * @param context algorithms state
 * @param hash_mask bit mask of the hash sums to add to the link
 * @param flags   can be combination of bits RHPR_UPPERCASE, RHPR_NO_MAGNET,
 *                RHPR_FILESIZE
 * @return number of written characters, including terminating '\0' on success, 0 on fail
 */
RHASH_API size_t rhash_print_magnet(char* output, const char* filepath,
	rhash context, unsigned hash_mask, int flags);


/* MESSAGE API */

/**
 * The type of an unsigned integer large enough to hold a pointer.
 */
#if defined(UINTPTR_MAX)
typedef uintptr_t rhash_uptr_t;
#elif defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
	defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
typedef unsigned long long rhash_uptr_t;
#else
typedef unsigned long rhash_uptr_t;
#endif

/**
 * The value returned by rhash_transmit on error.
 */
#define RHASH_ERROR ((rhash_uptr_t)-1)
/**
 * Convert a pointer to rhash_uptr_t.
 */
#define RHASH_STR2UPTR(str) ((rhash_uptr_t)(char*)(str))
/**
 * Convert a rhash_uptr_t to a void* pointer.
 */
#define RHASH_UPTR2PVOID(u) ((void*)((u) + 0))

/**
 * Process a rhash message.
 *
 * @param msg_id message identifier
 * @param dst message destination (can be NULL for generic messages)
 * @param ldata data depending on message
 * @param rdata data depending on message
 * @return message-specific data
 */
RHASH_API rhash_uptr_t rhash_transmit(
	unsigned msg_id, void* dst, rhash_uptr_t ldata, rhash_uptr_t rdata);

/* rhash message constants */

#define RMSG_GET_CONTEXT 1
#define RMSG_CANCEL      2
#define RMSG_IS_CANCELED 3
#define RMSG_GET_FINALIZED 4
#define RMSG_SET_AUTOFINAL 5
#define RMSG_SET_OPENSSL_MASK 10
#define RMSG_GET_OPENSSL_MASK 11
#define RMSG_GET_OPENSSL_SUPPORTED_MASK 12
#define RMSG_GET_OPENSSL_AVAILABLE_MASK 13

/* HELPER MACROS */

/**
 * Get a pointer to context of the specified hash function.
 */
#define rhash_get_context_ptr(ctx, hash_id) RHASH_UPTR2PVOID(rhash_transmit(RMSG_GET_CONTEXT, ctx, hash_id, 0))
/**
 * Cancel hash calculation of a file.
 */
#define rhash_cancel(ctx) rhash_transmit(RMSG_CANCEL, ctx, 0, 0)
/**
 * Return non-zero if hash calculation was canceled, zero otherwise.
 */
#define rhash_is_canceled(ctx) rhash_transmit(RMSG_IS_CANCELED, ctx, 0, 0)
/**
 * Return non-zero if rhash_final was called for rhash_context.
 */
#define rhash_get_finalized(ctx) rhash_transmit(RMSG_GET_FINALIZED, ctx, 0, 0)

/**
 * Turn on/off the auto-final flag for the given rhash_context. By default
 * auto-final is on, which means rhash_final is called automatically, if
 * needed when a hash value is retrieved by rhash_print call.
 */
#define rhash_set_autofinal(ctx, on) rhash_transmit(RMSG_SET_AUTOFINAL, ctx, on, 0)

/**
 * Set the bit-mask of hash algorithms to be calculated by OpenSSL library.
 * The call rhash_set_openssl_mask(0) made before rhash_library_init(),
 * turns off loading of the OpenSSL dynamic library.
 * This call works if the LibRHash was compiled with OpenSSL support.
 */
#define rhash_set_openssl_mask(mask) rhash_transmit(RMSG_SET_OPENSSL_MASK, NULL, mask, 0)

/**
 * Return current bit-mask of hash algorithms selected to be calculated by OpenSSL
 * library. Return RHASH_ERROR if LibRHash is compiled without OpenSSL support.
 */
#define rhash_get_openssl_mask() rhash_transmit(RMSG_GET_OPENSSL_MASK, NULL, 0, 0)

/**
 * Return the bit-mask of algorithms that can be provided by the OpenSSL plugin,
 * if the library is compiled with OpenSSL support, 0 otherwise. This bit-mask is
 * a constant value computed at compile-time.
 */
#define rhash_get_openssl_supported_mask() rhash_transmit(RMSG_GET_OPENSSL_SUPPORTED_MASK, NULL, 0, 0)

/**
 * Return the bit-mask of algorithms that are successfully loaded from
 * OpenSSL library. If the library is not loaded or not supported by LibRHash,
 * then return 0.
 */
#define rhash_get_openssl_available_mask() rhash_transmit(RMSG_GET_OPENSSL_AVAILABLE_MASK, NULL, 0, 0)


/**
 * Return non-zero if LibRHash hash been compiled with OpenSSL support,
 * and zero otherwise.
 */
#define rhash_is_openssl_supported() (rhash_get_openssl_mask() != RHASH_ERROR)

/**
 * Legacy macro. The bit mask of hash algorithms implemented by OpenSSL.
 */
# define RHASH_OPENSSL_SUPPORTED_HASHES (rhash_get_openssl_supported_mask())

#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */

#endif /* RHASH_H */