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 all hash functions in SILC. You can dynamically add new hash
28 functions into the list. At the initialization of SILC this list is
29 filled with the configured hash functions. */
30 struct SilcHashListStruct {
32 struct SilcHashListStruct *next;
35 /* List of dynamically registered hash functions. */
36 struct SilcHashListStruct *silc_hash_list = NULL;
38 /* Statically declared list of hash functions. */
39 SilcHashObject silc_hash_builtin_list[] =
41 { "md5", 16, 64, silc_md5_init, silc_md5_update, silc_md5_final,
42 silc_md5_transform, silc_md5_context_len },
43 { "sha1", 20, 64, silc_sha1_init, silc_sha1_update, silc_sha1_final,
44 silc_sha1_transform, silc_sha1_context_len },
46 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
49 /* Registers a ned hash function into the SILC. This function is used at
50 the initialization of the SILC. */
52 int silc_hash_register(SilcHashObject *hash)
54 struct SilcHashListStruct *new, *h;
56 SILC_LOG_DEBUG(("Registering new hash function"));
58 new = silc_calloc(1, sizeof(*new));
59 new->hash = silc_calloc(1, sizeof(*new->hash));
61 /* Set the pointers */
62 new->hash->name = silc_calloc(1, strlen(hash->name));
63 memcpy(new->hash->name, hash->name, strlen(hash->name));
64 new->hash->hash_len = hash->hash_len;
65 new->hash->block_len = hash->block_len;
66 new->hash->init = hash->init;
67 new->hash->update = hash->update;
68 new->hash->final = hash->final;
69 new->hash->context_len = hash->context_len;
72 /* Add the new hash function to the list */
73 if (!silc_hash_list) {
90 /* Unregister a hash function from the SILC. */
92 int silc_hash_unregister(SilcHashObject *hash)
94 struct SilcHashListStruct *h, *tmp;
96 SILC_LOG_DEBUG(("Unregistering hash function"));
100 /* Unregister all hash functions */
101 if (hash == SILC_ALL_HASH_FUNCTIONS) {
102 /* Unregister all ciphers */
105 silc_free(h->hash->name);
113 /* Unregister the hash function */
114 if (h->hash == hash) {
116 silc_free(h->hash->name);
118 silc_hash_list = tmp;
124 if (h->next->hash == hash) {
126 silc_free(h->hash->name);
138 /* Allocates a new SilcHash object. New object is returned into new_hash
141 int silc_hash_alloc(const unsigned char *name, SilcHash *new_hash)
143 struct SilcHashListStruct *h;
146 SILC_LOG_DEBUG(("Allocating new hash object"));
148 /* Allocate the new object */
149 *new_hash = silc_calloc(1, sizeof(**new_hash));
151 if (silc_hash_list) {
154 if (!strcmp(h->hash->name, name))
159 if (!h || !h->hash->context_len)
162 /* Set the pointers */
163 (*new_hash)->hash = h->hash;
164 (*new_hash)->context = silc_calloc(1, h->hash->context_len());
165 (*new_hash)->make_hash = silc_hash_make;
171 for (i = 0; silc_hash_builtin_list[i].name; i++)
172 if (!strcmp(silc_hash_builtin_list[i].name, name))
175 if (silc_hash_builtin_list[i].name == NULL) {
176 silc_free(*new_hash);
181 /* Set the pointers */
182 (*new_hash)->hash = &silc_hash_builtin_list[i];
183 (*new_hash)->context = silc_calloc(1, (*new_hash)->hash->context_len());
184 (*new_hash)->make_hash = silc_hash_make;
189 /* Free's the SilcHash object */
191 void silc_hash_free(SilcHash hash)
194 silc_free(hash->context);
199 /* Returns TRUE if hash algorithm `name' is supported. */
201 int silc_hash_is_supported(const unsigned char *name)
203 struct SilcHashListStruct *h;
206 if (silc_hash_list) {
210 if (!strcmp(h->hash->name, name))
216 for (i = 0; silc_hash_builtin_list[i].name; i++)
217 if (!strcmp(silc_hash_builtin_list[i].name, name))
223 /* Returns comma separated list of supported hash functions. */
225 char *silc_hash_get_supported()
229 struct SilcHashListStruct *h;
232 if (silc_hash_list) {
236 len += strlen(h->hash->name);
237 list = silc_realloc(list, len + 1);
239 memcpy(list + (len - strlen(h->hash->name)),
240 h->hash->name, strlen(h->hash->name));
241 memcpy(list + len, ",", 1);
248 for (i = 0; silc_hash_builtin_list[i].name; i++) {
249 len += strlen(silc_hash_builtin_list[i].name);
250 list = silc_realloc(list, len + 1);
252 memcpy(list + (len - strlen(silc_hash_builtin_list[i].name)),
253 silc_hash_builtin_list[i].name,
254 strlen(silc_hash_builtin_list[i].name));
255 memcpy(list + len, ",", 1);
264 /* Creates the hash value and returns it to the return_hash argument. */
266 void silc_hash_make(SilcHash hash, const unsigned char *data,
267 unsigned int len, unsigned char *return_hash)
269 hash->hash->init(hash->context);
270 hash->hash->update(hash->context, (unsigned char *)data, len);
271 hash->hash->final(hash->context, return_hash);
274 /* Creates fingerprint of the data. If `hash' is NULL SHA1 is used as
275 default hash function. The returned fingerprint must be free's by the
278 char *silc_hash_fingerprint(SilcHash hash, const unsigned char *data,
279 unsigned int data_len)
281 char fingerprint[64], *cp;
286 silc_hash_alloc("sha1", &hash);
288 silc_hash_make(hash, data, data_len, h);
290 memset(fingerprint, 0, sizeof(fingerprint));
292 for (i = 0; i < hash->hash->hash_len; i++) {
293 snprintf(cp, sizeof(fingerprint), "%02X", h[i]);
296 if ((i + 1) % 2 == 0)
297 snprintf(cp++, sizeof(fingerprint), " ");
299 if ((i + 1) % 10 == 0)
300 snprintf(cp++, sizeof(fingerprint), " ");
303 return strdup(fingerprint);