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