Added CFB mode to aes, twofish and cast5. Unified the CBC, CFB and
[crypto.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 #ifdef SILC_DEBUG
67   SILC_CDEF("none", none, 0, 0, 0, 0),
68 #endif /* SILC_DEBUG */
69   { NULL, NULL, 0, 0, 0, 0 }
70 };
71
72 /* Register new cipher */
73
74 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
75 {
76 #ifndef SILC_SYMBIAN
77   SilcCipherObject *new;
78
79   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
80
81   /* Check if exists already */
82   if (silc_cipher_list) {
83     SilcCipherObject *entry;
84     silc_dlist_start(silc_cipher_list);
85     while ((entry = silc_dlist_get(silc_cipher_list))) {
86       if (!strcmp(entry->name, cipher->name))
87         return FALSE;
88     }
89   }
90
91   new = silc_calloc(1, sizeof(*new));
92   if (!new)
93     return FALSE;
94   new->name = strdup(cipher->name);
95   if (!new->name) {
96     silc_free(new);
97     return FALSE;
98   }
99   new->key_len = cipher->key_len;
100   new->block_len = cipher->block_len;
101   new->iv_len = cipher->iv_len;
102   new->set_key = cipher->set_key;
103   new->set_iv = cipher->set_iv;
104   new->encrypt = cipher->encrypt;
105   new->decrypt = cipher->decrypt;
106   new->context_len = cipher->context_len;
107   new->mode = cipher->mode;
108
109   /* Add to list */
110   if (silc_cipher_list == NULL)
111     silc_cipher_list = silc_dlist_init();
112   silc_dlist_add(silc_cipher_list, new);
113
114 #endif /* SILC_SYMBIAN */
115   return TRUE;
116 }
117
118 /* Unregister a cipher */
119
120 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
121 {
122 #ifndef SILC_SYMBIAN
123   SilcCipherObject *entry;
124
125   SILC_LOG_DEBUG(("Unregistering cipher"));
126
127   if (!silc_cipher_list)
128     return FALSE;
129
130   silc_dlist_start(silc_cipher_list);
131   while ((entry = silc_dlist_get(silc_cipher_list))) {
132     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
133       silc_dlist_del(silc_cipher_list, entry);
134       silc_free(entry->name);
135       silc_free(entry);
136
137       if (silc_dlist_count(silc_cipher_list) == 0) {
138         silc_dlist_uninit(silc_cipher_list);
139         silc_cipher_list = NULL;
140       }
141
142       return TRUE;
143     }
144   }
145
146 #endif /* SILC_SYMBIAN */
147   return FALSE;
148 }
149
150 /* Register default ciphers */
151
152 SilcBool silc_cipher_register_default(void)
153 {
154   /* We use builtin ciphers */
155   return TRUE;
156 }
157
158 /* Unregister all ciphers */
159
160 SilcBool silc_cipher_unregister_all(void)
161 {
162 #ifndef SILC_SYMBIAN
163   SilcCipherObject *entry;
164
165   if (!silc_cipher_list)
166     return FALSE;
167
168   silc_dlist_start(silc_cipher_list);
169   while ((entry = silc_dlist_get(silc_cipher_list))) {
170     silc_cipher_unregister(entry);
171     if (!silc_cipher_list)
172       break;
173   }
174 #endif /* SILC_SYMBIAN */
175   return TRUE;
176 }
177
178 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
179    on error. The allocated cipher is returned in new_cipher argument. The
180    caller must set the key to the cipher after this function has returned
181    by calling the ciphers set_key function. */
182
183 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
184 {
185   SilcCipherObject *entry = NULL;
186   int i;
187
188   SILC_LOG_DEBUG(("Allocating new cipher object"));
189
190 #ifndef SILC_SYMBIAN
191   /* First check registered list of ciphers */
192   if (silc_cipher_list) {
193     silc_dlist_start(silc_cipher_list);
194     while ((entry = silc_dlist_get(silc_cipher_list))) {
195       if (!strcmp(entry->name, name))
196         break;
197     }
198   }
199 #endif /* SILC_SYMBIAN */
200
201   if (!entry) {
202     /* Check builtin list of ciphers */
203     for (i = 0; silc_default_ciphers[i].name; i++) {
204       if (!strcmp(silc_default_ciphers[i].name, name)) {
205         entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
206         break;
207       }
208     }
209   }
210
211   if (entry) {
212     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
213     if (!(*new_cipher))
214       return FALSE;
215     (*new_cipher)->cipher = entry;
216     (*new_cipher)->context = silc_calloc(1, entry->context_len());
217     if (!(*new_cipher)->context) {
218       silc_free(*new_cipher);
219       return FALSE;
220     }
221
222     return TRUE;
223   }
224
225   return FALSE;
226 }
227
228 /* Free's the given cipher. */
229
230 void silc_cipher_free(SilcCipher cipher)
231 {
232   if (cipher) {
233     silc_free(cipher->context);
234     silc_free(cipher);
235   }
236 }
237
238 /* Returns TRUE if cipher `name' is supported. */
239
240 SilcBool silc_cipher_is_supported(const unsigned char *name)
241 {
242   SilcCipherObject *entry;
243   int i;
244
245 #ifndef SILC_SYMBIAN
246   /* First check registered list of ciphers */
247   if (silc_cipher_list) {
248     silc_dlist_start(silc_cipher_list);
249     while ((entry = silc_dlist_get(silc_cipher_list))) {
250       if (!strcmp(entry->name, name))
251         return TRUE;
252     }
253   }
254 #endif /* SILC_SYMBIAN */
255
256   /* Check builtin list of ciphers */
257   for (i = 0; silc_default_ciphers[i].name; i++)
258     if (!strcmp(silc_default_ciphers[i].name, name))
259       return TRUE;
260
261   return FALSE;
262 }
263
264 /* Returns comma separated list of supported ciphers. */
265
266 char *silc_cipher_get_supported(SilcBool only_registered)
267 {
268   SilcCipherObject *entry, *entry2;
269   char *list = NULL;
270   int i, len = 0;
271
272 #ifndef SILC_SYMBIAN
273   if (silc_cipher_list) {
274     silc_dlist_start(silc_cipher_list);
275     while ((entry = silc_dlist_get(silc_cipher_list))) {
276       len += strlen(entry->name);
277       list = silc_realloc(list, len + 1);
278
279       memcpy(list + (len - strlen(entry->name)),
280              entry->name, strlen(entry->name));
281       memcpy(list + len, ",", 1);
282       len++;
283     }
284   }
285 #endif /* SILC_SYMBIAN */
286
287   if (!only_registered || !silc_cipher_list) {
288     for (i = 0; silc_default_ciphers[i].name; i++) {
289       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
290
291       if (silc_cipher_list) {
292         silc_dlist_start(silc_cipher_list);
293         while ((entry2 = silc_dlist_get(silc_cipher_list))) {
294           if (!strcmp(entry2->name, entry->name))
295             break;
296         }
297         if (entry2)
298           continue;
299       }
300
301       len += strlen(entry->name);
302       list = silc_realloc(list, len + 1);
303
304       memcpy(list + (len - strlen(entry->name)),
305              entry->name, strlen(entry->name));
306       memcpy(list + len, ",", 1);
307       len++;
308     }
309   }
310
311   list[len - 1] = 0;
312
313   return list;
314 }
315
316 /* Encrypts */
317
318 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
319                              unsigned char *dst, SilcUInt32 len,
320                              unsigned char *iv)
321 {
322   return cipher->cipher->encrypt(cipher->cipher, cipher->context, src, dst, len,
323                                  iv ? iv : cipher->iv);
324 }
325
326 /* Decrypts */
327
328 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
329                              unsigned char *dst, SilcUInt32 len,
330                              unsigned char *iv)
331 {
332   return cipher->cipher->decrypt(cipher->cipher, cipher->context, src, dst, len,
333                                  iv ? iv : cipher->iv);
334 }
335
336 /* Sets the key for the cipher */
337
338 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
339                              SilcUInt32 keylen, SilcBool encryption)
340 {
341   return cipher->cipher->set_key(cipher->cipher, cipher->context, key, keylen,
342                                  encryption);
343 }
344
345 /* Sets the IV (initial vector) for the cipher. */
346
347 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
348 {
349   if (iv)
350     memmove(&cipher->iv, iv, cipher->cipher->iv_len);
351   cipher->cipher->set_iv(cipher->cipher, cipher->context, cipher->iv);
352 }
353
354 /* Returns the IV (initial vector) of the cipher. */
355
356 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
357 {
358   return cipher->iv;
359 }
360
361 /* Returns the key length of the cipher. */
362
363 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
364 {
365   return cipher->cipher->key_len;
366 }
367
368 /* Returns the block size of the cipher. */
369
370 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
371 {
372   return cipher->cipher->block_len;
373 }
374
375 /* Returns the IV length of the cipher. */
376
377 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
378 {
379   return cipher->cipher->iv_len;
380 }
381
382 /* Returns the name of the cipher */
383
384 const char *silc_cipher_get_name(SilcCipher cipher)
385 {
386   return (const char *)cipher->cipher->name;
387 }
388
389 /* Returns cipher mode */
390
391 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
392 {
393   return cipher->cipher->mode;
394 }