1 /** @file rhash.h LibRHash interface */
2 #ifndef RHASH_H
3 #define RHASH_H
4 
5 #include <stdio.h>
6 
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 
11 #ifndef RHASH_API
12 /**
13  * Modifier for LibRHash functions
14  */
15 # define RHASH_API
16 #endif
17 
18 /**
19  * Identifiers of supported hash functions.
20  * The rhash_init() function allows mixing several ids using
21  * binary OR, to calculate several hash functions for one message.
22  */
23 enum rhash_ids
24 {
25 #if 0
26 	RHASH_CRC32 = 0x01,
27 	RHASH_MD4   = 0x02,
28 	RHASH_MD5   = 0x04,
29 	RHASH_SHA1  = 0x08,
30 	RHASH_TIGER = 0x10,
31 	RHASH_TTH   = 0x20,
32 	RHASH_BTIH  = 0x40,
33 	RHASH_ED2K  = 0x80,
34 	RHASH_AICH  = 0x100,
35 	RHASH_WHIRLPOOL = 0x200,
36 	RHASH_RIPEMD160 = 0x400,
37 	RHASH_GOST94    = 0x800,
38 	RHASH_GOST94_CRYPTOPRO = 0x1000,
39 	RHASH_HAS160     = 0x2000,
40 	RHASH_GOST12_256 = 0x4000,
41 	RHASH_GOST12_512 = 0x8000,
42 	RHASH_SHA224    = 0x10000,
43 	RHASH_SHA256    = 0x20000,
44 	RHASH_SHA384    = 0x40000,
45 	RHASH_SHA512    = 0x80000,
46 	RHASH_EDONR256  = 0x0100000,
47 	RHASH_EDONR512  = 0x0200000,
48 	RHASH_SHA3_224  = 0x0400000,
49 	RHASH_SHA3_256  = 0x0800000,
50 	RHASH_SHA3_384  = 0x1000000,
51 	RHASH_SHA3_512  = 0x2000000,
52 	RHASH_CRC32C    = 0x4000000,
53 	RHASH_SNEFRU128 = 0x8000000,
54 	RHASH_SNEFRU256 = 0x10000000,
55 
56 	/**
57 	 * The bit-mask containing all supported hashe functions.
58 	 */
59 	RHASH_ALL_HASHES = RHASH_CRC32 | RHASH_CRC32C | RHASH_MD4 | RHASH_MD5 |
60 		RHASH_ED2K | RHASH_SHA1 |RHASH_TIGER | RHASH_TTH |
61 		RHASH_GOST94 | RHASH_GOST94_CRYPTOPRO | RHASH_GOST12_256 | RHASH_GOST12_512 |
62 		RHASH_BTIH | RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 |
63 		RHASH_HAS160 | RHASH_SNEFRU128 | RHASH_SNEFRU256 |
64 		RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 |
65 		RHASH_SHA3_224 | RHASH_SHA3_256 | RHASH_SHA3_384 | RHASH_SHA3_512 |
66 		RHASH_EDONR256 | RHASH_EDONR512,
67 
68 	RHASH_GOST = RHASH_GOST94, /* deprecated constant name */
69 	RHASH_GOST_CRYPTOPRO = RHASH_GOST94_CRYPTOPRO, /* deprecated constant name */
70 	/**
71 	 * The number of supported hash functions.
72 	 */
73 	RHASH_HASH_COUNT = 29
74 #else
75 	RHASH_MD5        = 0x01,
76 	RHASH_SHA1       = 0x02,
77 	RHASH_SHA224     = 0x04,
78 	RHASH_SHA256     = 0x08,
79 	RHASH_SHA384     = 0x10,
80 	RHASH_SHA512     = 0x20,
81 	RHASH_SHA3_224   = 0x40,
82 	RHASH_SHA3_256   = 0x80,
83 	RHASH_SHA3_384   = 0x100,
84 	RHASH_SHA3_512   = 0x200,
85 	RHASH_ALL_HASHES =
86 		RHASH_MD5 |
87 		RHASH_SHA1 |
88 		RHASH_SHA224 |
89 		RHASH_SHA256 |
90 		RHASH_SHA384 |
91 		RHASH_SHA512 |
92 		RHASH_SHA3_224 |
93 		RHASH_SHA3_256 |
94 		RHASH_SHA3_384 |
95 		RHASH_SHA3_512,
96 	RHASH_HASH_COUNT = 10
97 #endif
98 };
99 
100 /**
101  * The rhash context structure contains contexts for several hash functions.
102  */
103 typedef struct rhash_context
104 {
105 	/**
106 	 * The size of the hashed message.
107 	 */
108 	unsigned long long msg_size;
109 
110 	/**
111 	 * The bit-mask containing identifiers of the hashes being calculated.
112 	 */
113 	unsigned hash_id;
114 } rhash_context;
115 
116 #ifndef LIBRHASH_RHASH_CTX_DEFINED
117 #define LIBRHASH_RHASH_CTX_DEFINED
118 /**
119  * Hashing context.
120  */
121 typedef struct rhash_context* rhash;
122 #endif /* LIBRHASH_RHASH_CTX_DEFINED */
123 
124 /**
125  * Type of a callback to be called periodically while hashing a file.
126  */
127 typedef void (*rhash_callback_t)(void* data, unsigned long long offset);
128 
129 /**
130  * Initialize static data of rhash algorithms
131  */
132 RHASH_API void rhash_library_init(void);
133 
134 
135 /* HIGH-LEVEL LIBRHASH INTERFACE */
136 
137 /**
138  * Compute a hash of the given message.
139  *
140  * @param hash_id id of hash sum to compute
141  * @param message the message to process
142  * @param length message length
143  * @param result buffer to receive binary hash string
144  * @return 0 on success, -1 on error
145  */
146 RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result);
147 
148 /**
149  * Compute a single hash for given file.
150  *
151  * @param hash_id id of hash sum to compute
152  * @param filepath path to the file to hash
153  * @param result buffer to receive hash value with the lowest requested id
154  * @return 0 on success, -1 on error and errno is set
155  */
156 RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result);
157 
158 #ifdef _WIN32
159 /**
160  * Compute a single hash for given file (Windows-specific function).
161  *
162  * @param hash_id id of hash sum to compute
163  * @param filepath path to the file to hash
164  * @param result buffer to receive hash value with the lowest requested id
165  * @return 0 on success, -1 on error, -1 on error and errno is set
166  */
167 RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result);
168 #endif
169 
170 
171 /* LOW-LEVEL LIBRHASH INTERFACE */
172 
173 /**
174  * Allocate and initialize RHash context for calculating hash(es).
175  * After initializing rhash_update()/rhash_final() functions should be used.
176  * Then the context must be freed by calling rhash_free().
177  *
178  * @param hash_id union of bit flags, containing ids of hashes to calculate.
179  * @return initialized rhash context, NULL on error and errno is set
180  */
181 RHASH_API rhash rhash_init(unsigned hash_id);
182 
183 /**
184  * Calculate hashes of message.
185  * Can be called repeatedly with chunks of the message to be hashed.
186  *
187  * @param ctx the rhash context
188  * @param message message chunk
189  * @param length length of the message chunk
190  * @return 0 on success; On fail return -1 and set errno
191  */
192 RHASH_API int rhash_update(rhash ctx, const void* message, size_t length);
193 
194 /**
195  * Hash a file or stream. Multiple hashes can be computed.
196  * First, inintialize ctx parameter with rhash_init() before calling
197  * rhash_file_update(). Then use rhash_final() and rhash_print()
198  * to retrive hash values. Finaly call rhash_free() on ctx
199  * to free allocated memory or call rhash_reset() to reuse ctx.
200  *
201  * @param ctx rhash context
202  * @param fd descriptor of the file to hash
203  * @return 0 on success, -1 on error and errno is set
204  */
205 RHASH_API int rhash_file_update(rhash ctx, FILE* fd);
206 
207 /**
208  * Finalize hash calculation and optionally store the first hash.
209  *
210  * @param ctx the rhash context
211  * @param first_result optional buffer to store a calculated hash with the lowest available id
212  * @return 0 on success; On fail return -1 and set errno
213  */
214 RHASH_API int rhash_final(rhash ctx, unsigned char* first_result);
215 
216 /**
217  * Re-initialize RHash context to reuse it.
218  * Useful to speed up processing of many small messages.
219  *
220  * @param ctx context to reinitialize
221  */
222 RHASH_API void rhash_reset(rhash ctx);
223 
224 /**
225  * Free RHash context memory.
226  *
227  * @param ctx the context to free.
228  */
229 RHASH_API void rhash_free(rhash ctx);
230 
231 /**
232  * Set the callback function to be called from the
233  * rhash_file() and rhash_file_update() functions
234  * on processing every file block. The file block
235  * size is set internally by rhash and now is 8 KiB.
236  *
237  * @param ctx rhash context
238  * @param callback pointer to the callback function
239  * @param callback_data pointer to data passed to the callback
240  */
241 RHASH_API void  rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data);
242 
243 
244 /* INFORMATION FUNCTIONS */
245 
246 /**
247  * Returns the number of supported hash algorithms.
248  *
249  * @return the number of supported hash functions
250  */
251 RHASH_API int  rhash_count(void); /* number of supported hashes */
252 
253 /**
254  * Returns size of binary digest for given hash algorithm.
255  *
256  * @param hash_id the id of hash algorithm
257  * @return digest size in bytes
258  */
259 RHASH_API int  rhash_get_digest_size(unsigned hash_id); /* size of binary message digest */
260 
261 /**
262  * Returns length of digest hash string in default output format.
263  *
264  * @param hash_id the id of hash algorithm
265  * @return the length of hash string
266  */
267 RHASH_API int  rhash_get_hash_length(unsigned hash_id); /* length of formatted hash string */
268 
269 /**
270  * Detect default digest output format for given hash algorithm.
271  *
272  * @param hash_id the id of hash algorithm
273  * @return 1 for base32 format, 0 for hexadecimal
274  */
275 RHASH_API int  rhash_is_base32(unsigned hash_id); /* default digest output format */
276 
277 /**
278  * Returns a name of given hash algorithm.
279  *
280  * @param hash_id the id of hash algorithm
281  * @return algorithm name
282  */
283 RHASH_API const char* rhash_get_name(unsigned hash_id); /* get hash function name */
284 
285 /**
286  * Returns a name part of magnet urn of the given hash algorithm.
287  * Such magnet_name is used to generate a magnet link of the form
288  * urn:&lt;magnet_name&gt;=&lt;hash_value&gt;.
289  *
290  * @param hash_id the id of hash algorithm
291  * @return name
292  */
293 RHASH_API const char* rhash_get_magnet_name(unsigned hash_id); /* get name part of magnet urn */
294 
295 /* HASH SUM OUTPUT INTERFACE */
296 
297 #if 0
298 /**
299  * Flags for printing a hash sum.
300  */
301 enum rhash_print_sum_flags
302 {
303 	/*
304 	 * Print in a default format
305 	 */
306 	RHPR_DEFAULT   = 0x0,
307 	/*
308 	 * Output as binary message digest
309 	 */
310 	RHPR_RAW       = 0x1,
311 	/*
312 	 * Print as a hexadecimal string
313 	 */
314 	RHPR_HEX       = 0x2,
315 	/*
316 	 * Print as a base32-encoded string
317 	 */
318 	RHPR_BASE32    = 0x3,
319 	/*
320 	 * Print as a base64-encoded string
321 	 */
322 	RHPR_BASE64    = 0x4,
323 	/*
324 	 * Print as an uppercase string. Can be used
325 	 * for base32 or hexadecimal format only.
326 	 */
327 	RHPR_UPPERCASE = 0x8,
328 	/*
329 	 * Reverse hash bytes. Can be used for GOST hash.
330 	 */
331 	RHPR_REVERSE   = 0x10,
332 	/*
333 	 * Don't print 'magnet:?' prefix in rhash_print_magnet
334 	 */
335 	RHPR_NO_MAGNET  = 0x20,
336 	/*
337 	 * Print file size in rhash_print_magnet
338 	 */
339 	RHPR_FILESIZE  = 0x40,
340 	/*
341 	 * Print as URL-encoded string
342 	 */
343 	RHPR_URLENCODE  = 0x80
344 };
345 #endif
346 
347 
348 /**
349  * Print a text presentation of a given hash sum to the specified buffer.
350  *
351  * @param output a buffer to print the hash to
352  * @param bytes a hash sum to print
353  * @param size a size of hash sum in bytes
354  * @param flags  a bit-mask controlling how to format the hash sum,
355  *               can be a mix of the flags: RHPR_RAW, RHPR_HEX, RHPR_BASE32,
356  *               RHPR_BASE64, RHPR_URLENCODE, RHPR_UPPERCASE, RHPR_REVERSE
357  * @return the number of written characters
358  */
359 RHASH_API size_t rhash_print_bytes(char* output,
360 	const unsigned char* bytes, size_t size, int flags);
361 
362 /**
363  * Print text presentation of a hash sum with given hash_id to the specified
364  * output buffer. If the hash_id is zero, then print the hash sum with
365  * the lowest id stored in the hash context.
366  * The function call fails if the context doesn't include a hash with the
367  * given hash_id.
368  *
369  * @param output a buffer to print the hash to
370  * @param ctx    algorithms state
371  * @param hash_id id of the hash sum to print or 0 to print the first hash
372  *                saved in the context.
373  * @param flags  a bitmask controlling how to print the hash. Can contain flags
374  *               RHPR_UPPERCASE, RHPR_HEX, RHPR_BASE32, RHPR_BASE64, etc.
375  * @return the number of written characters on success or 0 on fail
376  */
377 RHASH_API size_t rhash_print(char* output, rhash ctx, unsigned hash_id,
378 	int flags);
379 
380 /**
381  * Print magnet link with given filepath and calculated hash sums into the
382  * output buffer. The hash_mask can limit which hash values will be printed.
383  * The function returns the size of the required buffer.
384  * If output is NULL the .
385  *
386  * @param output a string buffer to receive the magnet link or NULL
387  * @param filepath the file path to be printed or NULL
388  * @param context algorithms state
389  * @param hash_mask bit mask of the hash sums to add to the link
390  * @param flags   can be combination of bits RHPR_UPPERCASE, RHPR_NO_MAGNET,
391  *                RHPR_FILESIZE
392  * @return number of written characters, including terminating '\0' on success, 0 on fail
393  */
394 RHASH_API size_t rhash_print_magnet(char* output, const char* filepath,
395 	rhash context, unsigned hash_mask, int flags);
396 
397 
398 /* MESSAGE API */
399 
400 /**
401  * The type of an unsigned integer large enough to hold a pointer.
402  */
403 #if defined(UINTPTR_MAX)
404 typedef uintptr_t rhash_uptr_t;
405 #elif defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
406 	defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
407 typedef unsigned long long rhash_uptr_t;
408 #else
409 typedef unsigned long rhash_uptr_t;
410 #endif
411 
412 /**
413  * The value returned by rhash_transmit on error.
414  */
415 #define RHASH_ERROR ((rhash_uptr_t)-1)
416 /**
417  * Convert a pointer to rhash_uptr_t.
418  */
419 #define RHASH_STR2UPTR(str) ((rhash_uptr_t)(char*)(str))
420 /**
421  * Convert a rhash_uptr_t to a void* pointer.
422  */
423 #define RHASH_UPTR2PVOID(u) ((void*)((u) + 0))
424 
425 /**
426  * Process a rhash message.
427  *
428  * @param msg_id message identifier
429  * @param dst message destination (can be NULL for generic messages)
430  * @param ldata data depending on message
431  * @param rdata data depending on message
432  * @return message-specific data
433  */
434 RHASH_API rhash_uptr_t rhash_transmit(
435 	unsigned msg_id, void* dst, rhash_uptr_t ldata, rhash_uptr_t rdata);
436 
437 /* rhash message constants */
438 
439 #define RMSG_GET_CONTEXT 1
440 #define RMSG_CANCEL      2
441 #define RMSG_IS_CANCELED 3
442 #define RMSG_GET_FINALIZED 4
443 #define RMSG_SET_AUTOFINAL 5
444 #define RMSG_SET_OPENSSL_MASK 10
445 #define RMSG_GET_OPENSSL_MASK 11
446 #define RMSG_GET_OPENSSL_SUPPORTED_MASK 12
447 #define RMSG_GET_OPENSSL_AVAILABLE_MASK 13
448 
449 /* HELPER MACROS */
450 
451 /**
452  * Get a pointer to context of the specified hash function.
453  */
454 #define rhash_get_context_ptr(ctx, hash_id) RHASH_UPTR2PVOID(rhash_transmit(RMSG_GET_CONTEXT, ctx, hash_id, 0))
455 /**
456  * Cancel hash calculation of a file.
457  */
458 #define rhash_cancel(ctx) rhash_transmit(RMSG_CANCEL, ctx, 0, 0)
459 /**
460  * Return non-zero if hash calculation was canceled, zero otherwise.
461  */
462 #define rhash_is_canceled(ctx) rhash_transmit(RMSG_IS_CANCELED, ctx, 0, 0)
463 /**
464  * Return non-zero if rhash_final was called for rhash_context.
465  */
466 #define rhash_get_finalized(ctx) rhash_transmit(RMSG_GET_FINALIZED, ctx, 0, 0)
467 
468 /**
469  * Turn on/off the auto-final flag for the given rhash_context. By default
470  * auto-final is on, which means rhash_final is called automatically, if
471  * needed when a hash value is retrieved by rhash_print call.
472  */
473 #define rhash_set_autofinal(ctx, on) rhash_transmit(RMSG_SET_AUTOFINAL, ctx, on, 0)
474 
475 /**
476  * Set the bit-mask of hash algorithms to be calculated by OpenSSL library.
477  * The call rhash_set_openssl_mask(0) made before rhash_library_init(),
478  * turns off loading of the OpenSSL dynamic library.
479  * This call works if the LibRHash was compiled with OpenSSL support.
480  */
481 #define rhash_set_openssl_mask(mask) rhash_transmit(RMSG_SET_OPENSSL_MASK, NULL, mask, 0)
482 
483 /**
484  * Return current bit-mask of hash algorithms selected to be calculated by OpenSSL
485  * library. Return RHASH_ERROR if LibRHash is compiled without OpenSSL support.
486  */
487 #define rhash_get_openssl_mask() rhash_transmit(RMSG_GET_OPENSSL_MASK, NULL, 0, 0)
488 
489 /**
490  * Return the bit-mask of algorithms that can be provided by the OpenSSL plugin,
491  * if the library is compiled with OpenSSL support, 0 otherwise. This bit-mask is
492  * a constant value computed at compile-time.
493  */
494 #define rhash_get_openssl_supported_mask() rhash_transmit(RMSG_GET_OPENSSL_SUPPORTED_MASK, NULL, 0, 0)
495 
496 /**
497  * Return the bit-mask of algorithms that are successfully loaded from
498  * OpenSSL library. If the library is not loaded or not supported by LibRHash,
499  * then return 0.
500  */
501 #define rhash_get_openssl_available_mask() rhash_transmit(RMSG_GET_OPENSSL_AVAILABLE_MASK, NULL, 0, 0)
502 
503 
504 /**
505  * Return non-zero if LibRHash hash been compiled with OpenSSL support,
506  * and zero otherwise.
507  */
508 #define rhash_is_openssl_supported() (rhash_get_openssl_mask() != RHASH_ERROR)
509 
510 /**
511  * Legacy macro. The bit mask of hash algorithms implemented by OpenSSL.
512  */
513 # define RHASH_OPENSSL_SUPPORTED_HASHES (rhash_get_openssl_supported_mask())
514 
515 #ifdef __cplusplus
516 } /* extern "C" */
517 #endif /* __cplusplus */
518 
519 #endif /* RHASH_H */
520