Created SILC Client Libary by moving stuff from silc/ directory.
[silc.git] / lib / silccrypt / silccipher.c
1 /*
2
3   silccipher.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:54  priikone
27  *      Imported from internal CVS/Added Log headers.
28  *
29  *
30  */
31
32 #include "silcincludes.h"
33
34 #include "ciphers.h"            /* Includes cipher definitions */
35
36 /* List of all ciphers in SILC. You can dynamically add new ciphers
37    into the list. At the initialization of SILC this list is filled with
38    the configured ciphers. */
39 struct SilcCipherListStruct {
40   SilcCipherObject *cipher;
41   struct SilcCipherListStruct *next;
42 };
43
44 /* Dynamically registered list of ciphers. */
45 struct SilcCipherListStruct *silc_cipher_list = NULL;
46
47 /* XXX: add the other good ciphers here as well */
48
49 /* Staticly declared list of ciphers. This is used if system doesn't
50    support SIM's. */
51 SilcCipherObject silc_cipher_builtin_list[] =
52 {
53   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
54     silc_none_encrypt_cbc, silc_none_decrypt_cbc, 
55     silc_none_context_len },
56   { "twofish", 16, 16, silc_twofish_set_key, silc_twofish_set_key_with_string,
57     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
58     silc_twofish_context_len },
59   { "rc6", 16, 16, silc_rc6_set_key, silc_rc6_set_key_with_string,
60     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
61     silc_rc6_context_len },
62   { "mars", 16, 16, silc_mars_set_key, silc_mars_set_key_with_string,
63     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
64     silc_mars_context_len },
65
66   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
67 };
68
69 /* Register a new cipher into SILC. This is used at the initialization of
70    the SILC. This function allocates a new object for the cipher to be
71    registered. Therefore, if memory has been allocated for the object sent
72    as argument it has to be free'd after this function returns succesfully. */
73
74 int silc_cipher_register(SilcCipherObject *cipher)
75 {
76   struct SilcCipherListStruct *new, *c;
77
78   SILC_LOG_DEBUG(("Registering new cipher"));
79
80   new = silc_calloc(1, sizeof(*new));
81   new->cipher = silc_calloc(1, sizeof(*new->cipher));
82
83   /* Set the pointers */
84   new->cipher->name = strdup(cipher->name);
85   new->cipher->block_len = cipher->block_len;
86   new->cipher->key_len = cipher->key_len;
87   new->cipher->set_key = cipher->set_key;
88   new->cipher->set_key_with_string = cipher->set_key_with_string;
89   new->cipher->encrypt = cipher->encrypt;
90   new->cipher->decrypt = cipher->decrypt;
91   new->cipher->context_len = cipher->context_len;
92   new->next = NULL;
93
94   /* Add the new cipher to the list */
95   if (!silc_cipher_list) {
96     silc_cipher_list = new;
97     return TRUE;
98   }
99
100   c = silc_cipher_list;
101   while (c) {
102     if (!c->next) {
103       c->next = new;
104       break;
105     }
106     c = c->next;
107   }
108
109   return TRUE;
110 }
111
112 /* Unregister a cipher from the SILC. */
113
114 int silc_cipher_unregister(SilcCipherObject *cipher)
115 {
116   struct SilcCipherListStruct *c, *tmp;
117
118   SILC_LOG_DEBUG(("Unregistering cipher"));
119
120   c = silc_cipher_list;
121   
122   if (cipher == SILC_ALL_CIPHERS) {
123     /* Unregister all ciphers */
124     while (c) {
125       tmp = c->next;
126       silc_free(c->cipher->name);
127       silc_free(c);
128       c = tmp;
129     }
130
131     return TRUE;
132   }
133
134   /* Unregister the cipher */
135   if (c->cipher == cipher) {
136     tmp = c->next;
137     silc_free(c->cipher->name);
138     silc_free(c);
139     silc_cipher_list = tmp;
140     
141     return TRUE;
142   }
143
144   while (c) {
145     if (c->next->cipher == cipher) {
146
147       tmp = c->next->next;
148       silc_free(c->cipher->name);
149       silc_free(c);
150       c->next = tmp;
151
152       return TRUE;
153     }
154
155     c = c->next;
156   }
157
158   return FALSE;
159 }
160
161 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
162    on error. The allocated cipher is returned in new_cipher argument. The
163    caller must set the key to the cipher after this function has returned
164    by calling the ciphers set_key function. */
165
166 int silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
167 {
168   struct SilcCipherListStruct *c;
169   int i;
170
171   SILC_LOG_DEBUG(("Allocating new cipher object"));
172
173   /* Allocate the new object */
174   *new_cipher = silc_calloc(1, sizeof(**new_cipher));
175   
176   if (silc_cipher_list) {
177
178     c = silc_cipher_list;
179     while (c) {
180       if (!strcmp(c->cipher->name, name))
181         break;
182       c = c->next;
183     }
184
185     if (!c)
186       goto check_builtin;
187
188     /* Set the pointers */
189     (*new_cipher)->cipher = c->cipher;
190     (*new_cipher)->context = silc_calloc(1, c->cipher->context_len());
191     (*new_cipher)->set_iv = silc_cipher_set_iv;
192     (*new_cipher)->get_iv = silc_cipher_get_iv;
193     (*new_cipher)->get_key_len = silc_cipher_get_key_len;
194     (*new_cipher)->get_block_len = silc_cipher_get_block_len;
195     
196     return TRUE;
197   }
198
199  check_builtin:
200
201   for (i = 0; silc_cipher_builtin_list[i].name; i++)
202     if (!strcmp(silc_cipher_builtin_list[i].name, name))
203       break;
204
205   if (silc_cipher_builtin_list[i].name == NULL) {
206     silc_free(*new_cipher);
207     return FALSE;
208   }
209
210   /* Set the pointers */
211   (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
212   (*new_cipher)->context = 
213     silc_calloc(1, (*new_cipher)->cipher->context_len());
214   (*new_cipher)->set_iv = silc_cipher_set_iv;
215   (*new_cipher)->get_iv = silc_cipher_get_iv;
216   (*new_cipher)->get_key_len = silc_cipher_get_key_len;
217   (*new_cipher)->get_block_len = silc_cipher_get_block_len;
218   memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
219
220   return TRUE;
221 }
222
223 /* Free's the given cipher. */
224
225 void silc_cipher_free(SilcCipher cipher)
226 {
227   if (cipher) {
228     silc_free(cipher->context);
229     silc_free(cipher);
230   }
231 }
232
233 /* Returns TRUE if cipher `name' is supported. */
234
235 int silc_cipher_is_supported(const unsigned char *name)
236 {
237   struct SilcCipherListStruct *c;
238   int i;
239
240   if (silc_cipher_list) {
241     c = silc_cipher_list;
242
243     while (c) {
244       if (!strcmp(c->cipher->name, name))
245         return TRUE;
246       c = c->next;
247     }
248   }
249
250   for (i = 0; silc_cipher_builtin_list[i].name; i++)
251     if (!strcmp(silc_cipher_builtin_list[i].name, name))
252       return TRUE;
253
254   return FALSE;
255 }
256
257 /* Returns comma separated list of supported ciphers. */
258
259 char *silc_cipher_get_supported()
260 {
261   char *list = NULL;
262   int i, len;
263   struct SilcCipherListStruct *c;
264
265   len = 0;
266   if (silc_cipher_list) {
267     c = silc_cipher_list;
268
269     while (c) {
270       len += strlen(c->cipher->name);
271       list = silc_realloc(list, len + 1);
272       
273       memcpy(list + (len - strlen(c->cipher->name)), 
274              c->cipher->name, strlen(c->cipher->name));
275       memcpy(list + len, ",", 1);
276       len++;
277       
278       c = c->next;
279     }
280   }
281
282   for (i = 0; silc_cipher_builtin_list[i].name; i++) {
283     len += strlen(silc_cipher_builtin_list[i].name);
284     list = silc_realloc(list, len + 1);
285     
286     memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)), 
287            silc_cipher_builtin_list[i].name, 
288            strlen(silc_cipher_builtin_list[i].name));
289     memcpy(list + len, ",", 1);
290     len++;
291   }
292
293   list[len - 1] = 0;
294
295   return list;
296 }
297
298 /* Sets the IV (initial vector) for the cipher. */
299
300 void silc_cipher_set_iv(SilcCipher itself, const unsigned char *iv)
301 {
302   memset(&itself->iv, 0, sizeof(itself->iv));
303   memcpy(&itself->iv, iv, itself->cipher->block_len);
304 }
305
306 /* Returns the IV (initial vector) of the cipher. The IV is returned 
307    to 'iv' argument. */
308
309 void silc_cipher_get_iv(SilcCipher itself, unsigned char *iv)
310 {
311   memcpy(iv, &itself->iv, itself->cipher->block_len);
312 }
313
314 /* Returns the key length of the cipher. */
315 /* XXX */
316
317 unsigned int silc_cipher_get_key_len(SilcCipher itself, 
318                                      const unsigned char *name)
319 {
320
321   return TRUE;
322 }
323
324 /* Returns the block size of the cipher. */
325 /* XXX */
326
327 unsigned int silc_cipher_get_block_len(SilcCipher itself)
328 {
329
330   return TRUE;
331 }