5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
27 /* List of dynamically registered hash functions. */
28 SilcDList silc_hash_list = NULL;
30 /* Default hash functions for silc_hash_register_default(). */
31 SilcHashObject silc_default_hash[] =
33 { "sha1", 20, 64, silc_sha1_init, silc_sha1_update, silc_sha1_final,
34 silc_sha1_transform, silc_sha1_context_len },
35 { "md5", 16, 64, silc_md5_init, silc_md5_update, silc_md5_final,
36 silc_md5_transform, silc_md5_context_len },
38 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
41 /* Registers a new hash function into the SILC. This function is used at
42 the initialization of the SILC. */
44 bool silc_hash_register(SilcHashObject *hash)
48 SILC_LOG_DEBUG(("Registering new hash function `%s'", hash->name));
50 /* Check for existing */
52 SilcHashObject *entry;
53 silc_dlist_start(silc_hash_list);
54 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
55 if (!strcmp(entry->name, hash->name))
60 new = silc_calloc(1, sizeof(*new));
61 new->name = strdup(hash->name);
62 new->hash_len = hash->hash_len;
63 new->block_len = hash->block_len;
64 new->init = hash->init;
65 new->update = hash->update;
66 new->final = hash->final;
67 new->transform = hash->transform;
68 new->context_len = hash->context_len;
71 if (silc_hash_list == NULL)
72 silc_hash_list = silc_dlist_init();
73 silc_dlist_add(silc_hash_list, new);
78 /* Unregister a hash function from the SILC. */
80 bool silc_hash_unregister(SilcHashObject *hash)
82 SilcHashObject *entry;
84 SILC_LOG_DEBUG(("Unregistering hash function"));
89 silc_dlist_start(silc_hash_list);
90 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
91 if (hash == SILC_ALL_HASH_FUNCTIONS || entry == hash) {
92 silc_dlist_del(silc_hash_list, entry);
94 if (silc_dlist_count(silc_hash_list) == 0) {
95 silc_dlist_uninit(silc_hash_list);
96 silc_hash_list = NULL;
106 /* Function that registers all the default hash funcs (all builtin ones).
107 The application may use this to register the default hash funcs if
108 specific hash funcs in any specific order is not wanted. */
110 bool silc_hash_register_default(void)
114 for (i = 0; silc_default_hash[i].name; i++)
115 silc_hash_register(&(silc_default_hash[i]));
120 /* Allocates a new SilcHash object. New object is returned into new_hash
123 bool silc_hash_alloc(const unsigned char *name, SilcHash *new_hash)
125 SilcHashObject *entry;
127 SILC_LOG_DEBUG(("Allocating new hash object"));
129 if (silc_hash_list) {
130 silc_dlist_start(silc_hash_list);
131 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
132 if (!strcmp(entry->name, name)) {
133 *new_hash = silc_calloc(1, sizeof(**new_hash));
134 (*new_hash)->hash = entry;
135 (*new_hash)->context = silc_calloc(1, entry->context_len());
136 (*new_hash)->make_hash = silc_hash_make;
145 /* Free's the SilcHash object */
147 void silc_hash_free(SilcHash hash)
150 silc_free(hash->context);
155 /* Returns the length of the hash digest. */
157 uint32 silc_hash_len(SilcHash hash)
159 return hash->hash->hash_len;
162 /* Returns TRUE if hash algorithm `name' is supported. */
164 bool silc_hash_is_supported(const unsigned char *name)
166 SilcHashObject *entry;
168 if (silc_hash_list) {
169 silc_dlist_start(silc_hash_list);
170 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
171 if (!strcmp(entry->name, name))
179 /* Returns comma separated list of supported hash functions. */
181 char *silc_hash_get_supported(void)
183 SilcHashObject *entry;
188 if (silc_hash_list) {
189 silc_dlist_start(silc_hash_list);
190 while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
191 len += strlen(entry->name);
192 list = silc_realloc(list, len + 1);
194 memcpy(list + (len - strlen(entry->name)),
195 entry->name, strlen(entry->name));
196 memcpy(list + len, ",", 1);
205 /* Creates the hash value and returns it to the return_hash argument. */
207 void silc_hash_make(SilcHash hash, const unsigned char *data,
208 uint32 len, unsigned char *return_hash)
210 hash->hash->init(hash->context);
211 hash->hash->update(hash->context, (unsigned char *)data, len);
212 hash->hash->final(hash->context, return_hash);
215 /* Creates fingerprint of the data. If `hash' is NULL SHA1 is used as
216 default hash function. The returned fingerprint must be free's by the
219 char *silc_hash_fingerprint(SilcHash hash, const unsigned char *data,
222 SilcHash new_hash = NULL;
227 silc_hash_alloc("sha1", &new_hash);
231 silc_hash_make(hash, data, data_len, h);
232 ret = silc_fingerprint(h, hash->hash->hash_len);
234 if (new_hash != NULL)
235 silc_hash_free(new_hash);
239 static const char vo[]= "aeiouy";
240 static const char co[]= "bcdfghklmnprstvzx";
242 /* Creates a babbleprint (Bubble Babble Encoding, developed by Antti
243 Huima (draft-huima-babble-01.txt)), by first computing real fingerprint
244 using `hash' or if NULL, then using SHA1, and then encoding the
245 fingerprint to the babbleprint. */
247 char *silc_hash_babbleprint(SilcHash hash, const unsigned char *data,
250 SilcHash new_hash = NULL;
252 unsigned char hval[32];
253 unsigned int a, b, c, d, e, check;
257 silc_hash_alloc("sha1", &new_hash);
261 /* Take fingerprint */
262 silc_hash_make(hash, data, data_len, hval);
264 /* Encode babbleprint */
265 out_len = (((hash->hash->hash_len + 1) / 2) + 1) * 6;
266 babbleprint = silc_calloc(out_len, sizeof(*babbleprint));
267 babbleprint[0] = co[16];
270 for (i = 0, k = 1; i < hash->hash->hash_len - 1; i += 2, k += 6) {
271 a = (((hval[i] >> 6) & 3) + check) % 6;
272 b = (hval[i] >> 2) & 15;
273 c = ((hval[i] & 3) + (check / 6)) % 6;
274 d = (hval[i + 1] >> 4) & 15;
275 e = hval[i + 1] & 15;
277 check = ((check * 5) + (hval[i] * 7) + hval[i + 1]) % 36;
279 babbleprint[k + 0] = vo[a];
280 babbleprint[k + 1] = co[b];
281 babbleprint[k + 2] = vo[c];
282 babbleprint[k + 3] = co[d];
283 babbleprint[k + 4] = '-';
284 babbleprint[k + 5] = co[e];
287 if ((hash->hash->hash_len % 2) != 0) {
288 a = (((hval[i] >> 6) & 3) + check) % 6;
289 b = (hval[i] >> 2) & 15;
290 c = ((hval[i] & 3) + (check / 6)) % 6;
291 babbleprint[k + 0] = vo[a];
292 babbleprint[k + 1] = co[b];
293 babbleprint[k + 2] = vo[c];
298 babbleprint[k + 0] = vo[a];
299 babbleprint[k + 1] = co[b];
300 babbleprint[k + 2] = vo[c];
302 babbleprint[k + 3] = co[16];
304 if (new_hash != NULL)
305 silc_hash_free(new_hash);