5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
27 /* The main SILC hash structure. */
28 struct SilcHashStruct {
34 /* List of dynamically registered hash functions. */
35 SilcDList silc_hash_list = NULL;
36 #endif /* SILC_SYMBIAN */
38 /* Default hash functions for silc_hash_register_default(). */
39 const SilcHashObject silc_default_hash[] =
41 { "sha256", 32, 64, silc_sha256_init, silc_sha256_update, silc_sha256_final,
42 silc_sha256_transform, silc_sha256_context_len },
43 { "sha1", 20, 64, silc_sha1_init, silc_sha1_update, silc_sha1_final,
44 silc_sha1_transform, silc_sha1_context_len },
45 { "md5", 16, 64, silc_md5_init, silc_md5_update, silc_md5_final,
46 silc_md5_transform, silc_md5_context_len },
48 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
51 /* Registers a new hash function into the SILC. This function is used at
52 the initialization of the SILC. */
54 SilcBool silc_hash_register(const SilcHashObject *hash)
59 SILC_LOG_DEBUG(("Registering new hash function `%s'", hash->name));
61 /* Check for existing */
63 SilcHashObject *entry;
64 silc_dlist_start(silc_hash_list);
65 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
66 if (!strcmp(entry->name, hash->name))
71 new = silc_calloc(1, sizeof(*new));
74 new->name = strdup(hash->name);
79 new->hash_len = hash->hash_len;
80 new->block_len = hash->block_len;
81 new->init = hash->init;
82 new->update = hash->update;
83 new->final = hash->final;
84 new->transform = hash->transform;
85 new->context_len = hash->context_len;
88 if (silc_hash_list == NULL)
89 silc_hash_list = silc_dlist_init();
90 silc_dlist_add(silc_hash_list, new);
92 #endif /* SILC_SYMBIAN */
96 /* Unregister a hash function from the SILC. */
98 SilcBool silc_hash_unregister(SilcHashObject *hash)
101 SilcHashObject *entry;
103 SILC_LOG_DEBUG(("Unregistering hash function"));
108 silc_dlist_start(silc_hash_list);
109 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
110 if (hash == SILC_ALL_HASH_FUNCTIONS || entry == hash) {
111 silc_dlist_del(silc_hash_list, entry);
112 silc_free(entry->name);
115 if (silc_dlist_count(silc_hash_list) == 0) {
116 silc_dlist_uninit(silc_hash_list);
117 silc_hash_list = NULL;
124 #endif /* SILC_SYMBIAN */
128 /* Function that registers all the default hash funcs (all builtin ones).
129 The application may use this to register the default hash funcs if
130 specific hash funcs in any specific order is not wanted. */
132 SilcBool silc_hash_register_default(void)
137 for (i = 0; silc_default_hash[i].name; i++)
138 silc_hash_register(&(silc_default_hash[i]));
140 #endif /* SILC_SYMBIAN */
144 SilcBool silc_hash_unregister_all(void)
147 SilcHashObject *entry;
152 silc_dlist_start(silc_hash_list);
153 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
154 silc_hash_unregister(entry);
158 #endif /* SILC_SYMBIAN */
162 /* Allocates a new SilcHash object. New object is returned into new_hash
165 SilcBool silc_hash_alloc(const unsigned char *name, SilcHash *new_hash)
167 SilcHashObject *entry = NULL;
169 SILC_LOG_DEBUG(("Allocating new hash object"));
172 if (silc_hash_list) {
173 silc_dlist_start(silc_hash_list);
174 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
175 if (!strcmp(entry->name, name))
181 /* On EPOC which don't have globals we check our constant hash list. */
183 for (i = 0; silc_default_hash[i].name; i++) {
184 if (!strcmp(silc_default_hash[i].name, name)) {
185 entry = (SilcHashObject *)&(silc_default_hash[i]);
190 #endif /* SILC_SYMBIAN */
193 *new_hash = silc_calloc(1, sizeof(**new_hash));
196 (*new_hash)->hash = entry;
197 (*new_hash)->context = silc_calloc(1, entry->context_len());
198 if (!(*new_hash)->context) {
199 silc_free(*new_hash);
208 /* Free's the SilcHash object */
210 void silc_hash_free(SilcHash hash)
213 silc_free(hash->context);
218 /* Returns the length of the hash digest. */
220 SilcUInt32 silc_hash_len(SilcHash hash)
222 return hash->hash->hash_len;
225 /* Returns the block lenght of the hash. */
227 SilcUInt32 silc_hash_block_len(SilcHash hash)
229 return hash->hash->block_len;
232 /* Returns the name of the hash function */
234 const char *silc_hash_get_name(SilcHash hash)
236 return hash->hash->name;
239 /* Returns TRUE if hash algorithm `name' is supported. */
241 SilcBool silc_hash_is_supported(const unsigned char *name)
244 SilcHashObject *entry;
246 if (silc_hash_list) {
247 silc_dlist_start(silc_hash_list);
248 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
249 if (!strcmp(entry->name, name))
256 for (i = 0; silc_default_hash[i].name; i++)
257 if (!strcmp(silc_default_hash[i].name, name))
260 #endif /* SILC_SYMBIAN */
264 /* Returns comma separated list of supported hash functions. */
266 char *silc_hash_get_supported(void)
268 SilcHashObject *entry;
273 if (silc_hash_list) {
274 silc_dlist_start(silc_hash_list);
275 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
276 len += strlen(entry->name);
277 list = silc_realloc(list, len + 1);
279 memcpy(list + (len - strlen(entry->name)),
280 entry->name, strlen(entry->name));
281 memcpy(list + len, ",", 1);
288 for (i = 0; silc_default_hash[i].name; i++) {
289 entry = (SilcHashObject *)&(silc_default_hash[i]);
290 len += strlen(entry->name);
291 list = silc_realloc(list, len + 1);
293 memcpy(list + (len - strlen(entry->name)),
294 entry->name, strlen(entry->name));
295 memcpy(list + len, ",", 1);
299 #endif /* SILC_SYMBIAN */
306 /* Creates the hash value and returns it to the return_hash argument. */
308 void silc_hash_make(SilcHash hash, const unsigned char *data,
309 SilcUInt32 len, unsigned char *return_hash)
311 silc_hash_init(hash);
312 silc_hash_update(hash, data, len);
313 silc_hash_final(hash, return_hash);
316 void silc_hash_init(SilcHash hash)
318 hash->hash->init(hash->context);
321 void silc_hash_update(SilcHash hash, const unsigned char *data,
324 hash->hash->update(hash->context, (unsigned char *)data, data_len);
327 void silc_hash_final(SilcHash hash, unsigned char *return_hash)
329 hash->hash->final(hash->context, return_hash);
332 void silc_hash_transform(SilcHash hash, SilcUInt32 *state,
333 const unsigned char *data)
335 hash->hash->transform(state, data);
338 /* Creates fingerprint of the data. If `hash' is NULL SHA1 is used as
339 default hash function. The returned fingerprint must be freed by the
342 char *silc_hash_fingerprint(SilcHash hash, const unsigned char *data,
345 SilcHash new_hash = NULL;
350 if (!silc_hash_alloc("sha1", &new_hash))
355 silc_hash_make(hash, data, data_len, h);
356 ret = silc_fingerprint(h, hash->hash->hash_len);
358 if (new_hash != NULL)
359 silc_hash_free(new_hash);
363 static const char vo[]= "aeiouy";
364 static const char co[]= "bcdfghklmnprstvzx";
366 /* Creates a babbleprint (Bubble Babble Encoding, developed by Antti
367 Huima (draft-huima-babble-01.txt)), by first computing real fingerprint
368 using `hash' or if NULL, then using SHA1, and then encoding the
369 fingerprint to the babbleprint. */
371 char *silc_hash_babbleprint(SilcHash hash, const unsigned char *data,
374 SilcHash new_hash = NULL;
376 unsigned char hval[32];
377 unsigned int a, b, c, d, e, check;
381 if (!silc_hash_alloc("sha1", &new_hash))
386 /* Take fingerprint */
387 silc_hash_make(hash, data, data_len, hval);
389 /* Encode babbleprint */
390 out_len = (((hash->hash->hash_len + 1) / 2) + 1) * 6;
391 babbleprint = silc_calloc(out_len, sizeof(*babbleprint));
393 silc_hash_free(new_hash);
396 babbleprint[0] = co[16];
399 for (i = 0, k = 1; i < hash->hash->hash_len - 1; i += 2, k += 6) {
400 a = (((hval[i] >> 6) & 3) + check) % 6;
401 b = (hval[i] >> 2) & 15;
402 c = ((hval[i] & 3) + (check / 6)) % 6;
403 d = (hval[i + 1] >> 4) & 15;
404 e = hval[i + 1] & 15;
406 check = ((check * 5) + (hval[i] * 7) + hval[i + 1]) % 36;
408 babbleprint[k + 0] = vo[a];
409 babbleprint[k + 1] = co[b];
410 babbleprint[k + 2] = vo[c];
411 babbleprint[k + 3] = co[d];
412 babbleprint[k + 4] = '-';
413 babbleprint[k + 5] = co[e];
416 if ((hash->hash->hash_len % 2) != 0) {
417 a = (((hval[i] >> 6) & 3) + check) % 6;
418 b = (hval[i] >> 2) & 15;
419 c = ((hval[i] & 3) + (check / 6)) % 6;
420 babbleprint[k + 0] = vo[a];
421 babbleprint[k + 1] = co[b];
422 babbleprint[k + 2] = vo[c];
427 babbleprint[k + 0] = vo[a];
428 babbleprint[k + 1] = co[b];
429 babbleprint[k + 2] = vo[c];
431 babbleprint[k + 3] = co[16];
433 if (new_hash != NULL)
434 silc_hash_free(new_hash);