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