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