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 { "sha1", 20, 64, silc_sha1_init, silc_sha1_update, silc_sha1_final,
42 silc_sha1_transform, silc_sha1_context_len },
43 { "md5", 16, 64, silc_md5_init, silc_md5_update, silc_md5_final,
44 silc_md5_transform, silc_md5_context_len },
46 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
49 /* Registers a new 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 `%s'", hash->name));
58 new = silc_calloc(1, sizeof(*new));
59 new->hash = silc_calloc(1, sizeof(*new->hash));
61 /* Set the pointers */
62 new->hash->name = strdup(hash->name);
63 new->hash->hash_len = hash->hash_len;
64 new->hash->block_len = hash->block_len;
65 new->hash->init = hash->init;
66 new->hash->update = hash->update;
67 new->hash->final = hash->final;
68 new->hash->context_len = hash->context_len;
71 /* Add the new hash function to the list */
72 if (!silc_hash_list) {
89 /* Unregister a hash function from the SILC. */
91 int silc_hash_unregister(SilcHashObject *hash)
93 struct SilcHashListStruct *h, *tmp;
95 SILC_LOG_DEBUG(("Unregistering hash function"));
99 /* Unregister all hash functions */
100 if (hash == SILC_ALL_HASH_FUNCTIONS) {
101 /* Unregister all ciphers */
104 silc_free(h->hash->name);
112 /* Unregister the hash function */
113 if (h->hash == hash) {
115 silc_free(h->hash->name);
117 silc_hash_list = tmp;
123 if (h->next->hash == hash) {
125 silc_free(h->hash->name);
137 /* Allocates a new SilcHash object. New object is returned into new_hash
140 int silc_hash_alloc(const unsigned char *name, SilcHash *new_hash)
142 struct SilcHashListStruct *h;
145 SILC_LOG_DEBUG(("Allocating new hash object"));
147 /* Allocate the new object */
148 *new_hash = silc_calloc(1, sizeof(**new_hash));
150 if (silc_hash_list) {
153 if (!strcmp(h->hash->name, name))
158 if (!h || !h->hash->context_len)
161 /* Set the pointers */
162 (*new_hash)->hash = h->hash;
163 (*new_hash)->context = silc_calloc(1, h->hash->context_len());
164 (*new_hash)->make_hash = silc_hash_make;
170 for (i = 0; silc_hash_builtin_list[i].name; i++)
171 if (!strcmp(silc_hash_builtin_list[i].name, name))
174 if (silc_hash_builtin_list[i].name == NULL) {
175 silc_free(*new_hash);
180 /* Set the pointers */
181 (*new_hash)->hash = &silc_hash_builtin_list[i];
182 (*new_hash)->context = silc_calloc(1, (*new_hash)->hash->context_len());
183 (*new_hash)->make_hash = silc_hash_make;
188 /* Free's the SilcHash object */
190 void silc_hash_free(SilcHash hash)
193 silc_free(hash->context);
198 /* Returns the length of the hash digest. */
200 uint32 silc_hash_len(SilcHash hash)
202 return hash->hash->hash_len;
205 /* Returns TRUE if hash algorithm `name' is supported. */
207 int silc_hash_is_supported(const unsigned char *name)
209 struct SilcHashListStruct *h;
215 if (silc_hash_list) {
219 if (!strcmp(h->hash->name, name))
225 for (i = 0; silc_hash_builtin_list[i].name; i++)
226 if (!strcmp(silc_hash_builtin_list[i].name, name))
232 /* Returns comma separated list of supported hash functions. */
234 char *silc_hash_get_supported()
238 struct SilcHashListStruct *h;
241 if (silc_hash_list) {
245 len += strlen(h->hash->name);
246 list = silc_realloc(list, len + 1);
248 memcpy(list + (len - strlen(h->hash->name)),
249 h->hash->name, strlen(h->hash->name));
250 memcpy(list + len, ",", 1);
257 for (i = 0; silc_hash_builtin_list[i].name; i++) {
258 len += strlen(silc_hash_builtin_list[i].name);
259 list = silc_realloc(list, len + 1);
261 memcpy(list + (len - strlen(silc_hash_builtin_list[i].name)),
262 silc_hash_builtin_list[i].name,
263 strlen(silc_hash_builtin_list[i].name));
264 memcpy(list + len, ",", 1);
273 /* Creates the hash value and returns it to the return_hash argument. */
275 void silc_hash_make(SilcHash hash, const unsigned char *data,
276 uint32 len, unsigned char *return_hash)
278 hash->hash->init(hash->context);
279 hash->hash->update(hash->context, (unsigned char *)data, len);
280 hash->hash->final(hash->context, return_hash);
283 /* Creates fingerprint of the data. If `hash' is NULL SHA1 is used as
284 default hash function. The returned fingerprint must be free's by the
287 char *silc_hash_fingerprint(SilcHash hash, const unsigned char *data,
290 char fingerprint[64], *cp;
295 silc_hash_alloc("sha1", &hash);
297 silc_hash_make(hash, data, data_len, h);
299 memset(fingerprint, 0, sizeof(fingerprint));
301 for (i = 0; i < hash->hash->hash_len; i++) {
302 snprintf(cp, sizeof(fingerprint), "%02X", h[i]);
305 if ((i + 1) % 2 == 0)
306 snprintf(cp++, sizeof(fingerprint), " ");
308 if ((i + 1) % 10 == 0)
309 snprintf(cp++, sizeof(fingerprint), " ");
312 return strdup(fingerprint);