updates.
[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 - 2001 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 /* $Id$ */
21
22 #include "silcincludes.h"
23 #include "ciphers.h"            /* Includes cipher definitions */
24
25 #ifndef SILC_EPOC
26 /* Dynamically registered list of ciphers. */
27 SilcDList silc_cipher_list = NULL;
28 #endif /* SILC_EPOC */
29
30 /* Static list of ciphers for silc_cipher_register_default(). */
31 const SilcCipherObject silc_default_ciphers[] =
32 {
33   { "aes-256-cbc", 16, 256, silc_aes_set_key, 
34     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
35     silc_aes_decrypt_cbc, silc_aes_context_len },
36   { "aes-192-cbc", 16, 192, silc_aes_set_key, 
37     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
38     silc_aes_decrypt_cbc, silc_aes_context_len },
39   { "aes-128-cbc", 16, 128, silc_aes_set_key, 
40     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
41     silc_aes_decrypt_cbc, silc_aes_context_len },
42   { "twofish-256-cbc", 16, 256, silc_twofish_set_key, 
43     silc_twofish_set_key_with_string,
44     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
45     silc_twofish_context_len },
46   { "twofish-192-cbc", 16, 192, silc_twofish_set_key, 
47     silc_twofish_set_key_with_string,
48     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
49     silc_twofish_context_len },
50   { "twofish-128-cbc", 16, 128, silc_twofish_set_key, 
51     silc_twofish_set_key_with_string,
52     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
53     silc_twofish_context_len },
54   { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
55     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
56     silc_rc6_context_len },
57   { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
58     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
59     silc_rc6_context_len },
60   { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
61     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
62     silc_rc6_context_len },
63   { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
64     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
65     silc_mars_context_len },
66   { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
67     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
68     silc_mars_context_len },
69   { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
70     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
71     silc_mars_context_len },
72   { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
73     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
74     silc_cast_context_len },
75   { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
76     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
77     silc_cast_context_len },
78   { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
79     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
80     silc_cast_context_len },
81   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
82     silc_none_encrypt_cbc, silc_none_decrypt_cbc, 
83     silc_none_context_len },
84
85   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
86 };
87
88 /* Register a new cipher into SILC. This is used at the initialization of
89    the SILC. This function allocates a new object for the cipher to be
90    registered. Therefore, if memory has been allocated for the object sent
91    as argument it has to be free'd after this function returns succesfully. */
92
93 bool silc_cipher_register(const SilcCipherObject *cipher)
94 {
95 #ifndef SILC_EPOC
96   SilcCipherObject *new;
97
98   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
99
100   /* Check if exists already */
101   if (silc_cipher_list) {
102     SilcCipherObject *entry;
103     silc_dlist_start(silc_cipher_list);
104     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
105       if (!strcmp(entry->name, cipher->name))
106         return FALSE;
107     }
108   }
109
110   new = silc_calloc(1, sizeof(*new));
111   new->name = strdup(cipher->name);
112   new->block_len = cipher->block_len;
113   new->key_len = cipher->key_len;
114   new->set_key = cipher->set_key;
115   new->set_key_with_string = cipher->set_key_with_string;
116   new->encrypt = cipher->encrypt;
117   new->decrypt = cipher->decrypt;
118   new->context_len = cipher->context_len;
119
120   /* Add to list */
121   if (silc_cipher_list == NULL)
122     silc_cipher_list = silc_dlist_init();
123   silc_dlist_add(silc_cipher_list, new);
124
125 #endif /* SILC_EPOC */
126   return TRUE;
127 }
128
129 /* Unregister a cipher from the SILC. */
130
131 bool silc_cipher_unregister(SilcCipherObject *cipher)
132 {
133 #ifndef SILC_EPOC
134   SilcCipherObject *entry;
135
136   SILC_LOG_DEBUG(("Unregistering cipher"));
137
138   if (!silc_cipher_list)
139     return FALSE;
140
141   silc_dlist_start(silc_cipher_list);
142   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
143     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
144       silc_dlist_del(silc_cipher_list, entry);
145       silc_free(entry->name);
146       silc_free(entry);
147
148       if (silc_dlist_count(silc_cipher_list) == 0) {
149         silc_dlist_uninit(silc_cipher_list);
150         silc_cipher_list = NULL;
151       }
152
153       return TRUE;
154     }
155   }
156
157 #endif /* SILC_EPOC */
158   return FALSE;
159 }
160
161 /* Function that registers all the default ciphers (all builtin ciphers). 
162    The application may use this to register the default ciphers if specific
163    ciphers in any specific order is not wanted. */
164
165 bool silc_cipher_register_default(void)
166 {
167 #ifndef SILC_EPOC
168   int i;
169
170   for (i = 0; silc_default_ciphers[i].name; i++)
171     silc_cipher_register(&(silc_default_ciphers[i]));
172
173 #endif /* SILC_EPOC */
174   return TRUE;
175 }
176
177 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
178    on error. The allocated cipher is returned in new_cipher argument. The
179    caller must set the key to the cipher after this function has returned
180    by calling the ciphers set_key function. */
181
182 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
183 {
184   SilcCipherObject *entry = NULL;
185
186   SILC_LOG_DEBUG(("Allocating new cipher object"));
187   
188 #ifndef SILC_EPOC
189   if (silc_cipher_list) {
190     silc_dlist_start(silc_cipher_list);
191     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
192       if (!strcmp(entry->name, name))
193         break;
194     }
195   }
196 #else
197   {
198     /* On EPOC which don't have globals we check our constant cipher list. */
199     int i;
200     for (i = 0; silc_default_ciphers[i].name; i++) {
201       if (!strcmp(silc_default_ciphers[i].name, name)) {
202         entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
203         break;
204       }
205     }
206   }
207 #endif /* SILC_EPOC */
208
209   if (entry) {
210     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
211     (*new_cipher)->cipher = entry; 
212     (*new_cipher)->context = silc_calloc(1, entry->context_len());
213     (*new_cipher)->set_iv = silc_cipher_set_iv;
214     (*new_cipher)->get_iv = silc_cipher_get_iv;
215     (*new_cipher)->get_key_len = silc_cipher_get_key_len;
216     (*new_cipher)->get_block_len = silc_cipher_get_block_len;
217     return TRUE;
218   }
219
220   return FALSE;
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 bool silc_cipher_is_supported(const unsigned char *name)
236 {
237 #ifndef SILC_EPOC
238   SilcCipherObject *entry;
239
240   if (silc_cipher_list) {
241     silc_dlist_start(silc_cipher_list);
242     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
243       if (!strcmp(entry->name, name))
244         return TRUE;
245     }
246   }
247 #else
248   {
249     int i;
250     for (i = 0; silc_default_ciphers[i].name; i++)
251       if (!strcmp(silc_default_ciphers[i].name, name))
252         return TRUE;
253   }
254 #endif /* SILC_EPOC */
255   return FALSE;
256 }
257
258 /* Returns comma separated list of supported ciphers. */
259
260 char *silc_cipher_get_supported(void)
261 {
262   SilcCipherObject *entry;
263   char *list = NULL;
264   int len = 0;
265
266 #ifndef SILC_EPOC
267   if (silc_cipher_list) {
268     silc_dlist_start(silc_cipher_list);
269     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
270       len += strlen(entry->name);
271       list = silc_realloc(list, len + 1);
272       
273       memcpy(list + (len - strlen(entry->name)), 
274              entry->name, strlen(entry->name));
275       memcpy(list + len, ",", 1);
276       len++;
277     }
278   }
279 #else
280   {
281     int i;
282     for (i = 0; silc_default_ciphers[i].name; i++) {
283       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
284       len += strlen(entry->name);
285       list = silc_realloc(list, len + 1);
286       
287       memcpy(list + (len - strlen(entry->name)), 
288              entry->name, strlen(entry->name));
289       memcpy(list + len, ",", 1);
290       len++;
291     }
292   }
293 #endif /* SILC_EPOC */
294
295   list[len - 1] = 0;
296
297   return list;
298 }
299
300 /* Encrypts */
301
302 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
303                          unsigned char *dst, SilcUInt32 len, 
304                          unsigned char *iv)
305 {
306   return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
307 }
308
309 /* Decrypts */
310
311 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
312                          unsigned char *dst, SilcUInt32 len, 
313                          unsigned char *iv)
314 {
315   return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
316 }
317
318 /* Sets the key for the cipher */
319
320 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
321                          SilcUInt32 keylen)
322 {
323   return cipher->cipher->set_key(cipher->context, key, keylen);
324 }
325
326 /* Sets the IV (initial vector) for the cipher. */
327
328 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
329 {
330   memset(&cipher->iv, 0, sizeof(cipher->iv));
331   memcpy(&cipher->iv, iv, cipher->cipher->block_len);
332 }
333
334 /* Returns the IV (initial vector) of the cipher. The IV is returned 
335    to 'iv' argument. */
336
337 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
338 {
339   memcpy(iv, &cipher->iv, cipher->cipher->block_len);
340 }
341
342 /* Returns the key length of the cipher. */
343
344 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
345 {
346   return cipher->cipher->key_len;
347 }
348
349 /* Returns the block size of the cipher. */
350
351 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
352 {
353   return cipher->cipher->block_len;
354 }