Added CTR mode to AES. Simplified cipher implementation API more.
[crypto.git] / lib / silccrypt / silccipher.c
1 /*
2
3   silccipher.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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_EPOC
32 /* Dynamically registered list of ciphers. */
33 SilcDList silc_cipher_list = NULL;
34 #endif /* SILC_EPOC */
35
36 /* Macro to define cipher to cipher list */
37 #define SILC_CIPHER_API_DEF(name, cipher, keylen, blocklen, ivlen)      \
38 { name, silc_##cipher##_set_key, silc_##cipher##_encrypt,               \
39   silc_##cipher##_decrypt, silc_##cipher##_context_len,                 \
40   keylen, blocklen, ivlen }
41
42 /* Static list of ciphers for silc_cipher_register_default(). */
43 const SilcCipherObject silc_default_ciphers[] =
44 {
45   SILC_CIPHER_API_DEF("aes-256-ctr", aes_ctr, 256, 16, 16),
46   SILC_CIPHER_API_DEF("aes-192-ctr", aes_ctr, 192, 16, 16),
47   SILC_CIPHER_API_DEF("aes-128-ctr", aes_ctr, 128, 16, 16),
48   SILC_CIPHER_API_DEF("aes-256-cbc", aes_cbc, 256, 16, 16),
49   SILC_CIPHER_API_DEF("aes-192-cbc", aes_cbc, 192, 16, 16),
50   SILC_CIPHER_API_DEF("aes-128-cbc", aes_cbc, 128, 16, 16),
51   SILC_CIPHER_API_DEF("twofish-256-cbc", twofish_cbc, 256, 16, 16),
52   SILC_CIPHER_API_DEF("twofish-192-cbc", twofish_cbc, 192, 16, 16),
53   SILC_CIPHER_API_DEF("twofish-128-cbc", twofish_cbc, 128, 16, 16),
54   SILC_CIPHER_API_DEF("cast-256-cbc", cast_cbc, 256, 16, 16),
55   SILC_CIPHER_API_DEF("cast-192-cbc", cast_cbc, 192, 16, 16),
56   SILC_CIPHER_API_DEF("cast-128-cbc", cast_cbc, 128, 16, 16),
57 #ifdef SILC_DEBUG
58   SILC_CIPHER_API_DEF("none", none, 0, 0, 0),
59 #endif /* SILC_DEBUG */
60   { NULL, NULL, 0, 0, 0 }
61 };
62
63 /* Register a new cipher into SILC. This is used at the initialization of
64    the SILC. This function allocates a new object for the cipher to be
65    registered. Therefore, if memory has been allocated for the object sent
66    as argument it has to be free'd after this function returns succesfully. */
67
68 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
69 {
70 #ifndef SILC_EPOC
71   SilcCipherObject *new;
72
73   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
74
75   /* Check if exists already */
76   if (silc_cipher_list) {
77     SilcCipherObject *entry;
78     silc_dlist_start(silc_cipher_list);
79     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
80       if (!strcmp(entry->name, cipher->name))
81         return FALSE;
82     }
83   }
84
85   new = silc_calloc(1, sizeof(*new));
86   new->name = strdup(cipher->name);
87   new->key_len = cipher->key_len;
88   new->block_len = cipher->block_len;
89   new->iv_len = cipher->iv_len;
90   new->set_key = cipher->set_key;
91   new->encrypt = cipher->encrypt;
92   new->decrypt = cipher->decrypt;
93   new->context_len = cipher->context_len;
94
95   /* Add to list */
96   if (silc_cipher_list == NULL)
97     silc_cipher_list = silc_dlist_init();
98   silc_dlist_add(silc_cipher_list, new);
99
100 #endif /* SILC_EPOC */
101   return TRUE;
102 }
103
104 /* Unregister a cipher from the SILC. */
105
106 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
107 {
108 #ifndef SILC_EPOC
109   SilcCipherObject *entry;
110
111   SILC_LOG_DEBUG(("Unregistering cipher"));
112
113   if (!silc_cipher_list)
114     return FALSE;
115
116   silc_dlist_start(silc_cipher_list);
117   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
118     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
119       silc_dlist_del(silc_cipher_list, entry);
120       silc_free(entry->name);
121       silc_free(entry);
122
123       if (silc_dlist_count(silc_cipher_list) == 0) {
124         silc_dlist_uninit(silc_cipher_list);
125         silc_cipher_list = NULL;
126       }
127
128       return TRUE;
129     }
130   }
131
132 #endif /* SILC_EPOC */
133   return FALSE;
134 }
135
136 /* Function that registers all the default ciphers (all builtin ciphers).
137    The application may use this to register the default ciphers if specific
138    ciphers in any specific order is not wanted. */
139
140 SilcBool silc_cipher_register_default(void)
141 {
142 #ifndef SILC_EPOC
143   int i;
144
145   for (i = 0; silc_default_ciphers[i].name; i++)
146     silc_cipher_register(&(silc_default_ciphers[i]));
147
148 #endif /* SILC_EPOC */
149   return TRUE;
150 }
151
152 SilcBool silc_cipher_unregister_all(void)
153 {
154 #ifndef SILC_EPOC
155   SilcCipherObject *entry;
156
157   if (!silc_cipher_list)
158     return FALSE;
159
160   silc_dlist_start(silc_cipher_list);
161   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
162     silc_cipher_unregister(entry);
163     if (!silc_cipher_list)
164       break;
165   }
166 #endif /* SILC_EPOC */
167   return TRUE;
168 }
169
170 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
171    on error. The allocated cipher is returned in new_cipher argument. The
172    caller must set the key to the cipher after this function has returned
173    by calling the ciphers set_key function. */
174
175 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
176 {
177   SilcCipherObject *entry = NULL;
178
179   SILC_LOG_DEBUG(("Allocating new cipher object"));
180
181 #ifndef SILC_EPOC
182   if (silc_cipher_list) {
183     silc_dlist_start(silc_cipher_list);
184     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
185       if (!strcmp(entry->name, name))
186         break;
187     }
188   }
189 #else
190   {
191     /* On EPOC which don't have globals we check our constant cipher list. */
192     int i;
193     for (i = 0; silc_default_ciphers[i].name; i++) {
194       if (!strcmp(silc_default_ciphers[i].name, name)) {
195         entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
196         break;
197       }
198     }
199   }
200 #endif /* SILC_EPOC */
201
202   if (entry) {
203     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
204     (*new_cipher)->cipher = entry;
205     (*new_cipher)->context = silc_calloc(1, entry->context_len());
206     return TRUE;
207   }
208
209   return FALSE;
210 }
211
212 /* Free's the given cipher. */
213
214 void silc_cipher_free(SilcCipher cipher)
215 {
216   if (cipher) {
217     silc_free(cipher->context);
218     silc_free(cipher);
219   }
220 }
221
222 /* Returns TRUE if cipher `name' is supported. */
223
224 SilcBool silc_cipher_is_supported(const unsigned char *name)
225 {
226 #ifndef SILC_EPOC
227   SilcCipherObject *entry;
228
229   if (silc_cipher_list) {
230     silc_dlist_start(silc_cipher_list);
231     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
232       if (!strcmp(entry->name, name))
233         return TRUE;
234     }
235   }
236 #else
237   {
238     int i;
239     for (i = 0; silc_default_ciphers[i].name; i++)
240       if (!strcmp(silc_default_ciphers[i].name, name))
241         return TRUE;
242   }
243 #endif /* SILC_EPOC */
244   return FALSE;
245 }
246
247 /* Returns comma separated list of supported ciphers. */
248
249 char *silc_cipher_get_supported(void)
250 {
251   SilcCipherObject *entry;
252   char *list = NULL;
253   int len = 0;
254
255 #ifndef SILC_EPOC
256   if (silc_cipher_list) {
257     silc_dlist_start(silc_cipher_list);
258     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
259       len += strlen(entry->name);
260       list = silc_realloc(list, len + 1);
261
262       memcpy(list + (len - strlen(entry->name)),
263              entry->name, strlen(entry->name));
264       memcpy(list + len, ",", 1);
265       len++;
266     }
267   }
268 #else
269   {
270     int i;
271     for (i = 0; silc_default_ciphers[i].name; i++) {
272       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
273       len += strlen(entry->name);
274       list = silc_realloc(list, len + 1);
275
276       memcpy(list + (len - strlen(entry->name)),
277              entry->name, strlen(entry->name));
278       memcpy(list + len, ",", 1);
279       len++;
280     }
281   }
282 #endif /* SILC_EPOC */
283
284   list[len - 1] = 0;
285
286   return list;
287 }
288
289 /* Encrypts */
290
291 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
292                              unsigned char *dst, SilcUInt32 len,
293                              unsigned char *iv)
294 {
295   return cipher->cipher->encrypt(cipher->context, src, dst, len,
296                                  iv ? iv : cipher->iv);
297 }
298
299 /* Decrypts */
300
301 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
302                              unsigned char *dst, SilcUInt32 len,
303                              unsigned char *iv)
304 {
305   return cipher->cipher->decrypt(cipher->context, src, dst, len,
306                                  iv ? iv : cipher->iv);
307 }
308
309 /* Sets the key for the cipher */
310
311 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
312                              SilcUInt32 keylen, SilcBool encryption)
313 {
314   return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
315 }
316
317 /* Sets the IV (initial vector) for the cipher. */
318
319 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
320 {
321   memcpy(&cipher->iv, iv, cipher->cipher->iv_len);
322 }
323
324 /* Returns the IV (initial vector) of the cipher. */
325
326 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
327 {
328   return cipher->iv;
329 }
330
331 /* Returns the key length of the cipher. */
332
333 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
334 {
335   return cipher->cipher->key_len;
336 }
337
338 /* Returns the block size of the cipher. */
339
340 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
341 {
342   return cipher->cipher->block_len;
343 }
344
345 /* Returns the IV length of the cipher. */
346
347 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
348 {
349   return cipher->cipher->iv_len;
350 }
351
352 /* Returns the name of the cipher */
353
354 const char *silc_cipher_get_name(SilcCipher cipher)
355 {
356   return (const char *)cipher->cipher->name;
357 }