Added SILC Thread Queue API
[silc.git] / lib / silccrypt / silccipher.c
1 /*
2
3   silccipher.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2007 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22 #include "ciphers.h"            /* Includes cipher definitions */
23
24 /* The SilcCipher context */
25 struct SilcCipherStruct {
26   SilcCipherObject *cipher;
27   void *context;
28   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
29 };
30
31 #ifndef SILC_SYMBIAN
32 /* Dynamically registered list of ciphers. */
33 SilcDList silc_cipher_list = NULL;
34 #endif /* SILC_SYMBIAN */
35
36 /* Macro to define cipher to cipher list */
37 #define SILC_CDEF(name, cipher, keylen, blocklen, ivlen, mode)          \
38 { name, silc_##cipher##_set_key, silc_##cipher##_set_iv,                \
39   silc_##cipher##_encrypt, silc_##cipher##_decrypt,                     \
40   silc_##cipher##_context_len, keylen, blocklen, ivlen, mode }
41
42 /* Static list of ciphers for silc_cipher_register_default(). */
43 const SilcCipherObject silc_default_ciphers[] =
44 {
45   SILC_CDEF("aes-256-ctr", aes, 256, 16, 16, SILC_CIPHER_MODE_CTR),
46   SILC_CDEF("aes-192-ctr", aes, 192, 16, 16, SILC_CIPHER_MODE_CTR),
47   SILC_CDEF("aes-128-ctr", aes, 128, 16, 16, SILC_CIPHER_MODE_CTR),
48   SILC_CDEF("aes-256-cbc", aes, 256, 16, 16, SILC_CIPHER_MODE_CBC),
49   SILC_CDEF("aes-192-cbc", aes, 192, 16, 16, SILC_CIPHER_MODE_CBC),
50   SILC_CDEF("aes-128-cbc", aes, 128, 16, 16, SILC_CIPHER_MODE_CBC),
51   SILC_CDEF("aes-256-cfb", aes, 256, 16, 16, SILC_CIPHER_MODE_CFB),
52   SILC_CDEF("aes-192-cfb", aes, 192, 16, 16, SILC_CIPHER_MODE_CFB),
53   SILC_CDEF("aes-128-cfb", aes, 128, 16, 16, SILC_CIPHER_MODE_CFB),
54   SILC_CDEF("twofish-256-ctr", twofish, 256, 16, 16, SILC_CIPHER_MODE_CTR),
55   SILC_CDEF("twofish-192-ctr", twofish, 192, 16, 16, SILC_CIPHER_MODE_CTR),
56   SILC_CDEF("twofish-128-ctr", twofish, 128, 16, 16, SILC_CIPHER_MODE_CTR),
57   SILC_CDEF("twofish-256-cbc", twofish, 256, 16, 16, SILC_CIPHER_MODE_CBC),
58   SILC_CDEF("twofish-192-cbc", twofish, 192, 16, 16, SILC_CIPHER_MODE_CBC),
59   SILC_CDEF("twofish-128-cbc", twofish, 128, 16, 16, SILC_CIPHER_MODE_CBC),
60   SILC_CDEF("twofish-256-cfb", twofish, 256, 16, 16, SILC_CIPHER_MODE_CFB),
61   SILC_CDEF("twofish-192-cfb", twofish, 192, 16, 16, SILC_CIPHER_MODE_CFB),
62   SILC_CDEF("twofish-128-cfb", twofish, 128, 16, 16, SILC_CIPHER_MODE_CFB),
63   SILC_CDEF("cast5-128-ctr", cast5, 128, 8, 8, SILC_CIPHER_MODE_CTR),
64   SILC_CDEF("cast5-128-cbc", cast5, 128, 8, 8, SILC_CIPHER_MODE_CBC),
65   SILC_CDEF("cast5-128-cfb", cast5, 128, 8, 8, SILC_CIPHER_MODE_CFB),
66   SILC_CDEF("des-56-ctr", des, 56, 8, 8, SILC_CIPHER_MODE_CTR),
67   SILC_CDEF("des-56-cbc", des, 56, 8, 8, SILC_CIPHER_MODE_CBC),
68   SILC_CDEF("des-56-cfb", des, 56, 8, 8, SILC_CIPHER_MODE_CFB),
69   SILC_CDEF("3des-168-ctr", 3des, 168, 8, 8, SILC_CIPHER_MODE_CTR),
70   SILC_CDEF("3des-168-cbc", 3des, 168, 8, 8, SILC_CIPHER_MODE_CBC),
71   SILC_CDEF("3des-168-cfb", 3des, 168, 8, 8, SILC_CIPHER_MODE_CFB),
72 #ifdef SILC_DEBUG
73   SILC_CDEF("none", none, 0, 0, 0, 0),
74 #endif /* SILC_DEBUG */
75   { NULL, NULL, 0, 0, 0, 0 }
76 };
77
78 /* Register new cipher */
79
80 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
81 {
82 #ifndef SILC_SYMBIAN
83   SilcCipherObject *new;
84
85   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
86
87   /* Check if exists already */
88   if (silc_cipher_list) {
89     SilcCipherObject *entry;
90     silc_dlist_start(silc_cipher_list);
91     while ((entry = silc_dlist_get(silc_cipher_list))) {
92       if (!strcmp(entry->name, cipher->name))
93         return FALSE;
94     }
95   }
96
97   new = silc_calloc(1, sizeof(*new));
98   if (!new)
99     return FALSE;
100   new->name = strdup(cipher->name);
101   if (!new->name) {
102     silc_free(new);
103     return FALSE;
104   }
105   new->key_len = cipher->key_len;
106   new->block_len = cipher->block_len;
107   new->iv_len = cipher->iv_len;
108   new->set_key = cipher->set_key;
109   new->set_iv = cipher->set_iv;
110   new->encrypt = cipher->encrypt;
111   new->decrypt = cipher->decrypt;
112   new->context_len = cipher->context_len;
113   new->mode = cipher->mode;
114
115   /* Add to list */
116   if (silc_cipher_list == NULL)
117     silc_cipher_list = silc_dlist_init();
118   silc_dlist_add(silc_cipher_list, new);
119
120 #endif /* SILC_SYMBIAN */
121   return TRUE;
122 }
123
124 /* Unregister a cipher */
125
126 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
127 {
128 #ifndef SILC_SYMBIAN
129   SilcCipherObject *entry;
130
131   SILC_LOG_DEBUG(("Unregistering cipher"));
132
133   if (!silc_cipher_list)
134     return FALSE;
135
136   silc_dlist_start(silc_cipher_list);
137   while ((entry = silc_dlist_get(silc_cipher_list))) {
138     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
139       silc_dlist_del(silc_cipher_list, entry);
140       silc_free(entry->name);
141       silc_free(entry);
142
143       if (silc_dlist_count(silc_cipher_list) == 0) {
144         silc_dlist_uninit(silc_cipher_list);
145         silc_cipher_list = NULL;
146       }
147
148       return TRUE;
149     }
150   }
151
152 #endif /* SILC_SYMBIAN */
153   return FALSE;
154 }
155
156 /* Register default ciphers */
157
158 SilcBool silc_cipher_register_default(void)
159 {
160   /* We use builtin ciphers */
161   return TRUE;
162 }
163
164 /* Unregister all ciphers */
165
166 SilcBool silc_cipher_unregister_all(void)
167 {
168 #ifndef SILC_SYMBIAN
169   SilcCipherObject *entry;
170
171   if (!silc_cipher_list)
172     return FALSE;
173
174   silc_dlist_start(silc_cipher_list);
175   while ((entry = silc_dlist_get(silc_cipher_list))) {
176     silc_cipher_unregister(entry);
177     if (!silc_cipher_list)
178       break;
179   }
180 #endif /* SILC_SYMBIAN */
181   return TRUE;
182 }
183
184 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
185    on error. The allocated cipher is returned in new_cipher argument. The
186    caller must set the key to the cipher after this function has returned
187    by calling the ciphers set_key function. */
188
189 SilcBool silc_cipher_alloc(const char *name, SilcCipher *new_cipher)
190 {
191   SilcCipherObject *entry = NULL;
192   int i;
193
194   SILC_LOG_DEBUG(("Allocating new cipher object"));
195
196 #ifndef SILC_SYMBIAN
197   /* First check registered list of ciphers */
198   if (silc_cipher_list) {
199     silc_dlist_start(silc_cipher_list);
200     while ((entry = silc_dlist_get(silc_cipher_list))) {
201       if (!strcmp(entry->name, name))
202         break;
203     }
204   }
205 #endif /* SILC_SYMBIAN */
206
207   if (!entry) {
208     /* Check builtin list of ciphers */
209     for (i = 0; silc_default_ciphers[i].name; i++) {
210       if (!strcmp(silc_default_ciphers[i].name, name)) {
211         entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
212         break;
213       }
214     }
215   }
216
217   if (entry) {
218     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
219     if (!(*new_cipher))
220       return FALSE;
221     (*new_cipher)->cipher = entry;
222     (*new_cipher)->context = silc_calloc(1, entry->context_len());
223     if (!(*new_cipher)->context) {
224       silc_free(*new_cipher);
225       return FALSE;
226     }
227
228     return TRUE;
229   }
230
231   return FALSE;
232 }
233
234 /* Free's the given cipher. */
235
236 void silc_cipher_free(SilcCipher cipher)
237 {
238   if (cipher) {
239     silc_free(cipher->context);
240     silc_free(cipher);
241   }
242 }
243
244 /* Returns TRUE if cipher `name' is supported. */
245
246 SilcBool silc_cipher_is_supported(const char *name)
247 {
248   SilcCipherObject *entry;
249   int i;
250
251 #ifndef SILC_SYMBIAN
252   /* First check registered list of ciphers */
253   if (silc_cipher_list) {
254     silc_dlist_start(silc_cipher_list);
255     while ((entry = silc_dlist_get(silc_cipher_list))) {
256       if (!strcmp(entry->name, name))
257         return TRUE;
258     }
259   }
260 #endif /* SILC_SYMBIAN */
261
262   /* Check builtin list of ciphers */
263   for (i = 0; silc_default_ciphers[i].name; i++)
264     if (!strcmp(silc_default_ciphers[i].name, name))
265       return TRUE;
266
267   return FALSE;
268 }
269
270 /* Returns comma separated list of supported ciphers. */
271
272 char *silc_cipher_get_supported(SilcBool only_registered)
273 {
274   SilcCipherObject *entry, *entry2;
275   char *list = NULL;
276   int i, len = 0;
277
278 #ifndef SILC_SYMBIAN
279   if (silc_cipher_list) {
280     silc_dlist_start(silc_cipher_list);
281     while ((entry = silc_dlist_get(silc_cipher_list))) {
282       len += strlen(entry->name);
283       list = silc_realloc(list, len + 1);
284
285       memcpy(list + (len - strlen(entry->name)),
286              entry->name, strlen(entry->name));
287       memcpy(list + len, ",", 1);
288       len++;
289     }
290   }
291 #endif /* SILC_SYMBIAN */
292
293   if (!only_registered || !silc_cipher_list) {
294     for (i = 0; silc_default_ciphers[i].name; i++) {
295       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
296
297       if (silc_cipher_list) {
298         silc_dlist_start(silc_cipher_list);
299         while ((entry2 = silc_dlist_get(silc_cipher_list))) {
300           if (!strcmp(entry2->name, entry->name))
301             break;
302         }
303         if (entry2)
304           continue;
305       }
306
307       len += strlen(entry->name);
308       list = silc_realloc(list, len + 1);
309
310       memcpy(list + (len - strlen(entry->name)),
311              entry->name, strlen(entry->name));
312       memcpy(list + len, ",", 1);
313       len++;
314     }
315   }
316
317   list[len - 1] = 0;
318
319   return list;
320 }
321
322 /* Encrypts */
323
324 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
325                              unsigned char *dst, SilcUInt32 len,
326                              unsigned char *iv)
327 {
328   return cipher->cipher->encrypt(cipher->cipher, cipher->context, src, dst, len,
329                                  iv ? iv : cipher->iv);
330 }
331
332 /* Decrypts */
333
334 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
335                              unsigned char *dst, SilcUInt32 len,
336                              unsigned char *iv)
337 {
338   return cipher->cipher->decrypt(cipher->cipher, cipher->context, src, dst, len,
339                                  iv ? iv : cipher->iv);
340 }
341
342 /* Sets the key for the cipher */
343
344 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
345                              SilcUInt32 keylen, SilcBool encryption)
346 {
347   return cipher->cipher->set_key(cipher->cipher, cipher->context, key, keylen,
348                                  encryption);
349 }
350
351 /* Sets the IV (initial vector) for the cipher. */
352
353 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
354 {
355   if (iv)
356     memmove(&cipher->iv, iv, cipher->cipher->iv_len);
357   cipher->cipher->set_iv(cipher->cipher, cipher->context, cipher->iv);
358 }
359
360 /* Returns the IV (initial vector) of the cipher. */
361
362 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
363 {
364   return cipher->iv;
365 }
366
367 /* Returns the key length of the cipher. */
368
369 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
370 {
371   return cipher->cipher->key_len;
372 }
373
374 /* Returns the block size of the cipher. */
375
376 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
377 {
378   return cipher->cipher->block_len;
379 }
380
381 /* Returns the IV length of the cipher. */
382
383 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
384 {
385   return cipher->cipher->iv_len;
386 }
387
388 /* Returns the name of the cipher */
389
390 const char *silc_cipher_get_name(SilcCipher cipher)
391 {
392   return (const char *)cipher->cipher->name;
393 }
394
395 /* Returns cipher mode */
396
397 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
398 {
399   return cipher->cipher->mode;
400 }