summaryrefslogtreecommitdiff
path: root/Utilities/cmlibrhash/librhash/rhash.h
blob: 73ee537e185f85e5d12a8c0267115802ccff1422 (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
/** @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
{
	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_GOST      = 0x800,
	RHASH_GOST_CRYPTOPRO = 0x1000,
	RHASH_HAS160    = 0x2000,
	RHASH_SNEFRU128 = 0x4000,
	RHASH_SNEFRU256 = 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,

	/** The bit-mask containing all supported hashe functions */
	RHASH_ALL_HASHES = RHASH_CRC32 | RHASH_MD4 | RHASH_MD5 | RHASH_ED2K | RHASH_SHA1 |
		RHASH_TIGER | RHASH_TTH | RHASH_GOST | RHASH_GOST_CRYPTOPRO |
		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,

	/** The number of supported hash functions */
	RHASH_HASH_COUNT = 26
};

/**
 * 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);

RHASH_API void rhash_library_init(void); /* initialize static data */

/* hi-level hashing functions */
RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result);
RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result);
RHASH_API int rhash_file_update(rhash ctx, FILE* fd);

#ifdef _WIN32 /* windows only function */
RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result);
#endif

/* lo-level interface */
RHASH_API rhash rhash_init(unsigned hash_id);
/*RHASH_API rhash rhash_init_by_ids(unsigned hash_ids[], unsigned count);*/
RHASH_API int  rhash_update(rhash ctx, const void* message, size_t length);
RHASH_API int  rhash_final(rhash ctx, unsigned char* first_result);
RHASH_API void rhash_reset(rhash ctx); /* reinitialize the context */
RHASH_API void rhash_free(rhash ctx);

/* additional lo-level functions */
RHASH_API void  rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data);

/** bit-flag: default hash output format is base32 */
#define RHASH_INFO_BASE32 1

/**
 * Information about a hash function.
 */
typedef struct rhash_info
{
	/** hash function indentifier */
	unsigned hash_id;
	/** flags bit-mask, including RHASH_INFO_BASE32 bit */
	unsigned flags;
	/** size of binary message digest in bytes */
	size_t digest_size;
	const char* name;
	const char* magnet_name;
} rhash_info;

/* information functions */
RHASH_API int  rhash_count(void); /* number of supported hashes */
RHASH_API int  rhash_get_digest_size(unsigned hash_id); /* size of binary message digest */
RHASH_API int  rhash_get_hash_length(unsigned hash_id); /* length of formated hash string */
RHASH_API int  rhash_is_base32(unsigned hash_id); /* default digest output format */
RHASH_API const char* rhash_get_name(unsigned hash_id); /* get hash function name */
RHASH_API const char* rhash_get_magnet_name(unsigned hash_id); /* get name part of magnet urn */

/* note, that rhash_info_by_id() is not exported to a shared library or DLL */
const rhash_info* rhash_info_by_id(unsigned hash_id); /* get hash sum info by hash id */

/**
 * 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,
};

/* output hash into the given buffer */
RHASH_API size_t rhash_print_bytes(char* output,
	const unsigned char* bytes, size_t size, int flags);

RHASH_API size_t rhash_print(char* output, rhash ctx, unsigned hash_id,
	int flags);

/* output magnet URL into the given buffer */
RHASH_API size_t rhash_print_magnet(char* output, const char* filepath,
	rhash context, unsigned hash_mask, int flags);

/* macros for 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*)((char*)0 + (u)))

/* rhash API to set/get data via messages */
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_BT_ADD_FILE 32
#define RMSG_BT_SET_OPTIONS 33
#define RMSG_BT_SET_ANNOUNCE 34
#define RMSG_BT_SET_PIECE_LENGTH 35
#define RMSG_BT_SET_PROGRAM_NAME 36
#define RMSG_BT_GET_TEXT 37
#define RMSG_BT_SET_BATCH_SIZE 38

/* possible BitTorrent options for the RMSG_BT_SET_OPTIONS message */
#define RHASH_BT_OPT_PRIVATE 1
#define RHASH_BT_OPT_INFOHASH_ONLY 2

/* 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 retrived 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.
 */
#define rhash_get_openssl_mask() rhash_transmit(RMSG_GET_OPENSSL_MASK, NULL, 0, 0)

/** The bit mask of hash algorithms implemented by OpenSSL */
#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME)
# define RHASH_OPENSSL_SUPPORTED_HASHES (RHASH_MD4 | RHASH_MD5 | \
	RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | \
	RHASH_SHA512 | RHASH_RIPEMD160 | RHASH_WHIRLPOOL)
#else
# define RHASH_OPENSSL_SUPPORTED_HASHES 0
#endif

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

#endif /* RHASH_H */