Global cosmetic change.
[silc.git] / lib / silccrypt / silchash.c
1 /*
2
3   silchash.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /*
21  * $Id$
22  * $Log$
23  * Revision 1.2  2000/07/05 06:08:43  priikone
24  *      Global cosmetic change.
25  *
26  * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
27  *      Imported from internal CVS/Added Log headers.
28  *
29  *
30  */
31
32 #include "silcincludes.h"
33
34 #include "md5.h"
35 #include "sha1.h"
36
37 /* List of all hash functions in SILC. You can dynamically add new hash
38    functions into the list. At the initialization of SILC this list is 
39    filled with the configured hash functions. */
40 struct SilcHashListStruct {
41   SilcHashObject *hash;
42   struct SilcHashListStruct *next;
43 };
44
45 /* List of dynamically registered hash functions. */
46 struct SilcHashListStruct *silc_hash_list = NULL;
47
48 /* Statically declared list of hash functions. */
49 SilcHashObject silc_hash_builtin_list[] = 
50 {
51   { "md5", 16, 64, silc_md5_init, silc_md5_update, silc_md5_final,
52     silc_md5_transform, silc_md5_context_len },
53   { "sha1", 20, 64, silc_sha1_init, silc_sha1_update, silc_sha1_final,
54     silc_sha1_transform, silc_sha1_context_len },
55
56   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
57 };
58
59 /* Registers a ned hash function into the SILC. This function is used at
60    the initialization of the SILC. */
61
62 int silc_hash_register(SilcHashObject *hash)
63 {
64   struct SilcHashListStruct *new, *h;
65
66   SILC_LOG_DEBUG(("Registering new hash function"));
67
68   new = silc_calloc(1, sizeof(*new));
69   new->hash = silc_calloc(1, sizeof(*new->hash));
70
71   /* Set the pointers */
72   new->hash->name = silc_calloc(1, strlen(hash->name));
73   memcpy(new->hash->name, hash->name, strlen(hash->name));
74   new->hash->hash_len = hash->hash_len;
75   new->hash->block_len = hash->block_len;
76   new->hash->init = hash->init;
77   new->hash->update = hash->update;
78   new->hash->final = hash->final;
79   new->hash->context_len = hash->context_len;
80   new->next = NULL;
81
82   /* Add the new hash function to the list */
83   if (!silc_hash_list) {
84     silc_hash_list = new;
85     return TRUE;
86   }
87
88   h = silc_hash_list;
89   while (h) {
90     if (!h->next) {
91       h->next = new;
92       break;
93     }
94     h = h->next;
95   }
96
97   return TRUE;
98 }
99
100 /* Unregister a hash function from the SILC. */
101
102 int silc_hash_unregister(SilcHashObject *hash)
103 {
104   struct SilcHashListStruct *h, *tmp;
105
106   SILC_LOG_DEBUG(("Unregistering hash function"));
107
108   h = silc_hash_list;
109
110   /* Unregister all hash functions */
111   if (hash == SILC_ALL_HASH_FUNCTIONS) {
112     /* Unregister all ciphers */
113     while (h) {
114       tmp = h->next;
115       silc_free(h->hash->name);
116       silc_free(h);
117       h = tmp;
118     }
119
120     return TRUE;
121   }
122
123   /* Unregister the hash function */
124   if (h->hash == hash) {
125     tmp = h->next;
126     silc_free(h->hash->name);
127     silc_free(h);
128     silc_hash_list = tmp;
129
130     return TRUE;
131   }
132
133   while (h) {
134     if (h->next->hash == hash) {
135       tmp = h->next->next;
136       silc_free(h->hash->name);
137       silc_free(h);
138       h->next = tmp;
139       return TRUE;
140     }
141
142     h = h->next;
143   }
144
145   return FALSE;
146 }
147
148 /* Allocates a new SilcHash object. New object is returned into new_hash
149    argument. */
150
151 int silc_hash_alloc(const unsigned char *name, SilcHash *new_hash)
152 {
153   struct SilcHashListStruct *h;
154   int i;
155   
156   SILC_LOG_DEBUG(("Allocating new hash object"));
157
158   /* Allocate the new object */
159   *new_hash = silc_calloc(1, sizeof(**new_hash));
160
161   if (silc_hash_list) {
162     h = silc_hash_list;
163     while (h) {
164       if (!strcmp(h->hash->name, name))
165         break;
166       h = h->next;
167     }
168
169     if (!h)
170       goto check_builtin;
171
172     /* Set the pointers */
173     (*new_hash)->hash = h->hash;
174     (*new_hash)->context = silc_calloc(1, h->hash->context_len());
175     (*new_hash)->make_hash = silc_hash_make;
176
177     return TRUE;
178   }
179
180  check_builtin:
181   for (i = 0; silc_hash_builtin_list[i].name; i++)
182     if (!strcmp(silc_hash_builtin_list[i].name, name))
183       break;
184
185   if (silc_hash_builtin_list[i].name == NULL) {
186     silc_free(*new_hash);
187     return FALSE;
188   }
189   
190   /* Set the pointers */
191   (*new_hash)->hash = &silc_hash_builtin_list[i];
192   (*new_hash)->context = silc_calloc(1, (*new_hash)->hash->context_len());
193   (*new_hash)->make_hash = silc_hash_make;
194   
195   return TRUE;
196 }
197
198 /* Free's the SilcHash object */
199
200 void silc_hash_free(SilcHash hash)
201 {
202   if (hash) {
203     silc_free(hash->context);
204     silc_free(hash);
205   }
206 }
207
208 /* Returns TRUE if hash algorithm `name' is supported. */
209
210 int silc_hash_is_supported(const unsigned char *name)
211 {
212   struct SilcHashListStruct *h;
213   int i;
214   
215   if (silc_hash_list) {
216     h = silc_hash_list;
217
218     while (h) {
219       if (!strcmp(h->hash->name, name))
220         return TRUE;
221       h = h->next;
222     }
223   }
224
225   for (i = 0; silc_hash_builtin_list[i].name; i++)
226     if (!strcmp(silc_hash_builtin_list[i].name, name))
227       return TRUE;
228
229   return FALSE;
230 }
231
232 /* Returns comma separated list of supported hash functions. */
233
234 char *silc_hash_get_supported()
235 {
236   char *list = NULL;
237   int i, len;
238   struct SilcHashListStruct *h;
239
240   len = 0;
241   if (silc_hash_list) {
242     h = silc_hash_list;
243
244     while (h) {
245       len += strlen(h->hash->name);
246       list = silc_realloc(list, len + 1);
247       
248       memcpy(list + (len - strlen(h->hash->name)), 
249              h->hash->name, strlen(h->hash->name));
250       memcpy(list + len, ",", 1);
251       len++;
252       
253       h = h->next;
254     }
255   }
256
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);
260     
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);
265     len++;
266   }
267
268   list[len - 1] = 0;
269
270   return list;
271 }
272
273 /* Creates the hash value and returns it to the return_hash argument. */
274
275 void silc_hash_make(SilcHash hash, const unsigned char *data, 
276                     unsigned int len, unsigned char *return_hash)
277 {
278   hash->hash->init(hash->context);
279   hash->hash->update(hash->context, (unsigned char *)data, len);
280   hash->hash->final(hash->context, return_hash);
281 }