Fixed counter mode encryption/decryption.
[silc.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_CIPHER_API_DEF(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_CIPHER_API_DEF("aes-256-ctr", aes_ctr, 256, 16, 16,
46                       SILC_CIPHER_MODE_CTR),
47   SILC_CIPHER_API_DEF("aes-192-ctr", aes_ctr, 192, 16, 16,
48                       SILC_CIPHER_MODE_CTR),
49   SILC_CIPHER_API_DEF("aes-128-ctr", aes_ctr, 128, 16, 16,
50                       SILC_CIPHER_MODE_CTR),
51   SILC_CIPHER_API_DEF("aes-256-cbc", aes_cbc, 256, 16, 16,
52                       SILC_CIPHER_MODE_CBC),
53   SILC_CIPHER_API_DEF("aes-192-cbc", aes_cbc, 192, 16, 16,
54                       SILC_CIPHER_MODE_CBC),
55   SILC_CIPHER_API_DEF("aes-128-cbc", aes_cbc, 128, 16, 16,
56                       SILC_CIPHER_MODE_CBC),
57   SILC_CIPHER_API_DEF("twofish-256-cbc", twofish_cbc, 256, 16, 16,
58                       SILC_CIPHER_MODE_CBC),
59   SILC_CIPHER_API_DEF("twofish-192-cbc", twofish_cbc, 192, 16, 16,
60                       SILC_CIPHER_MODE_CBC),
61   SILC_CIPHER_API_DEF("twofish-128-cbc", twofish_cbc, 128, 16, 16,
62                       SILC_CIPHER_MODE_CBC),
63   SILC_CIPHER_API_DEF("cast-256-cbc", cast_cbc, 256, 16, 16,
64                       SILC_CIPHER_MODE_CBC),
65   SILC_CIPHER_API_DEF("cast-192-cbc", cast_cbc, 192, 16, 16,
66                       SILC_CIPHER_MODE_CBC),
67   SILC_CIPHER_API_DEF("cast-128-cbc", cast_cbc, 128, 16, 16,
68                       SILC_CIPHER_MODE_CBC),
69 #ifdef SILC_DEBUG
70   SILC_CIPHER_API_DEF("none", none, 0, 0, 0, 0),
71 #endif /* SILC_DEBUG */
72   { NULL, NULL, 0, 0, 0, 0 }
73 };
74
75 /* Register a new cipher into SILC. This is used at the initialization of
76    the SILC. This function allocates a new object for the cipher to be
77    registered. Therefore, if memory has been allocated for the object sent
78    as argument it has to be free'd after this function returns succesfully. */
79
80 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
81 {
82 #ifndef SILC_SYMBIAN
83   SilcCipherObject *new;
84
85   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
86
87   /* Check if exists already */
88   if (silc_cipher_list) {
89     SilcCipherObject *entry;
90     silc_dlist_start(silc_cipher_list);
91     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
92       if (!strcmp(entry->name, cipher->name))
93         return FALSE;
94     }
95   }
96
97   new = silc_calloc(1, sizeof(*new));
98   new->name = strdup(cipher->name);
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 from the SILC. */
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)) != SILC_LIST_END) {
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 /* Function that registers all the default ciphers (all builtin ciphers).
151    The application may use this to register the default ciphers if specific
152    ciphers in any specific order is not wanted. */
153
154 SilcBool silc_cipher_register_default(void)
155 {
156 #ifndef SILC_SYMBIAN
157   int i;
158
159   for (i = 0; silc_default_ciphers[i].name; i++)
160     silc_cipher_register(&(silc_default_ciphers[i]));
161
162 #endif /* SILC_SYMBIAN */
163   return TRUE;
164 }
165
166 SilcBool silc_cipher_unregister_all(void)
167 {
168 #ifndef SILC_SYMBIAN
169   SilcCipherObject *entry;
170
171   if (!silc_cipher_list)
172     return FALSE;
173
174   silc_dlist_start(silc_cipher_list);
175   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
176     silc_cipher_unregister(entry);
177     if (!silc_cipher_list)
178       break;
179   }
180 #endif /* SILC_SYMBIAN */
181   return TRUE;
182 }
183
184 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
185    on error. The allocated cipher is returned in new_cipher argument. The
186    caller must set the key to the cipher after this function has returned
187    by calling the ciphers set_key function. */
188
189 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
190 {
191   SilcCipherObject *entry = NULL;
192
193   SILC_LOG_DEBUG(("Allocating new cipher object"));
194
195 #ifndef SILC_SYMBIAN
196   if (silc_cipher_list) {
197     silc_dlist_start(silc_cipher_list);
198     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
199       if (!strcmp(entry->name, name))
200         break;
201     }
202   }
203 #else
204   {
205     /* On EPOC which don't have globals we check our constant cipher list. */
206     int i;
207     for (i = 0; silc_default_ciphers[i].name; i++) {
208       if (!strcmp(silc_default_ciphers[i].name, name)) {
209         entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
210         break;
211       }
212     }
213   }
214 #endif /* SILC_SYMBIAN */
215
216   if (entry) {
217     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
218     (*new_cipher)->cipher = entry;
219     (*new_cipher)->context = silc_calloc(1, entry->context_len());
220     return TRUE;
221   }
222
223   return FALSE;
224 }
225
226 /* Free's the given cipher. */
227
228 void silc_cipher_free(SilcCipher cipher)
229 {
230   if (cipher) {
231     silc_free(cipher->context);
232     silc_free(cipher);
233   }
234 }
235
236 /* Returns TRUE if cipher `name' is supported. */
237
238 SilcBool silc_cipher_is_supported(const unsigned char *name)
239 {
240 #ifndef SILC_SYMBIAN
241   SilcCipherObject *entry;
242
243   if (silc_cipher_list) {
244     silc_dlist_start(silc_cipher_list);
245     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
246       if (!strcmp(entry->name, name))
247         return TRUE;
248     }
249   }
250 #else
251   {
252     int i;
253     for (i = 0; silc_default_ciphers[i].name; i++)
254       if (!strcmp(silc_default_ciphers[i].name, name))
255         return TRUE;
256   }
257 #endif /* SILC_SYMBIAN */
258   return FALSE;
259 }
260
261 /* Returns comma separated list of supported ciphers. */
262
263 char *silc_cipher_get_supported(void)
264 {
265   SilcCipherObject *entry;
266   char *list = NULL;
267   int len = 0;
268
269 #ifndef SILC_SYMBIAN
270   if (silc_cipher_list) {
271     silc_dlist_start(silc_cipher_list);
272     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
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 #else
283   {
284     int i;
285     for (i = 0; silc_default_ciphers[i].name; i++) {
286       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
287       len += strlen(entry->name);
288       list = silc_realloc(list, len + 1);
289
290       memcpy(list + (len - strlen(entry->name)),
291              entry->name, strlen(entry->name));
292       memcpy(list + len, ",", 1);
293       len++;
294     }
295   }
296 #endif /* SILC_SYMBIAN */
297
298   list[len - 1] = 0;
299
300   return list;
301 }
302
303 /* Encrypts */
304
305 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
306                              unsigned char *dst, SilcUInt32 len,
307                              unsigned char *iv)
308 {
309   return cipher->cipher->encrypt(cipher->context, src, dst, len,
310                                  iv ? iv : cipher->iv);
311 }
312
313 /* Decrypts */
314
315 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
316                              unsigned char *dst, SilcUInt32 len,
317                              unsigned char *iv)
318 {
319   return cipher->cipher->decrypt(cipher->context, src, dst, len,
320                                  iv ? iv : cipher->iv);
321 }
322
323 /* Sets the key for the cipher */
324
325 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
326                              SilcUInt32 keylen, SilcBool encryption)
327 {
328   return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
329 }
330
331 /* Sets the IV (initial vector) for the cipher. */
332
333 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
334 {
335   if (iv)
336     memmove(&cipher->iv, iv, cipher->cipher->iv_len);
337   cipher->cipher->set_iv(cipher->context, iv);
338 }
339
340 /* Returns the IV (initial vector) of the cipher. */
341
342 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
343 {
344   return cipher->iv;
345 }
346
347 /* Returns the key length of the cipher. */
348
349 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
350 {
351   return cipher->cipher->key_len;
352 }
353
354 /* Returns the block size of the cipher. */
355
356 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
357 {
358   return cipher->cipher->block_len;
359 }
360
361 /* Returns the IV length of the cipher. */
362
363 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
364 {
365   return cipher->cipher->iv_len;
366 }
367
368 /* Returns the name of the cipher */
369
370 const char *silc_cipher_get_name(SilcCipher cipher)
371 {
372   return (const char *)cipher->cipher->name;
373 }
374
375 /* Returns cipher mode */
376
377 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
378 {
379   return cipher->cipher->mode;
380 }