Symbian compilation fixes.
[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_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##_encrypt,               \
39   silc_##cipher##_decrypt, silc_##cipher##_context_len,                 \
40   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->encrypt = cipher->encrypt;
104   new->decrypt = cipher->decrypt;
105   new->context_len = cipher->context_len;
106   new->mode = cipher->mode;
107
108   /* Add to list */
109   if (silc_cipher_list == NULL)
110     silc_cipher_list = silc_dlist_init();
111   silc_dlist_add(silc_cipher_list, new);
112
113 #endif /* SILC_SYMBIAN */
114   return TRUE;
115 }
116
117 /* Unregister a cipher from the SILC. */
118
119 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
120 {
121 #ifndef SILC_SYMBIAN
122   SilcCipherObject *entry;
123
124   SILC_LOG_DEBUG(("Unregistering cipher"));
125
126   if (!silc_cipher_list)
127     return FALSE;
128
129   silc_dlist_start(silc_cipher_list);
130   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
131     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
132       silc_dlist_del(silc_cipher_list, entry);
133       silc_free(entry->name);
134       silc_free(entry);
135
136       if (silc_dlist_count(silc_cipher_list) == 0) {
137         silc_dlist_uninit(silc_cipher_list);
138         silc_cipher_list = NULL;
139       }
140
141       return TRUE;
142     }
143   }
144
145 #endif /* SILC_SYMBIAN */
146   return FALSE;
147 }
148
149 /* Function that registers all the default ciphers (all builtin ciphers).
150    The application may use this to register the default ciphers if specific
151    ciphers in any specific order is not wanted. */
152
153 SilcBool silc_cipher_register_default(void)
154 {
155 #ifndef SILC_SYMBIAN
156   int i;
157
158   for (i = 0; silc_default_ciphers[i].name; i++)
159     silc_cipher_register(&(silc_default_ciphers[i]));
160
161 #endif /* SILC_SYMBIAN */
162   return TRUE;
163 }
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)) != SILC_LIST_END) {
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 unsigned char *name, SilcCipher *new_cipher)
189 {
190   SilcCipherObject *entry = NULL;
191
192   SILC_LOG_DEBUG(("Allocating new cipher object"));
193
194 #ifndef SILC_SYMBIAN
195   if (silc_cipher_list) {
196     silc_dlist_start(silc_cipher_list);
197     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
198       if (!strcmp(entry->name, name))
199         break;
200     }
201   }
202 #else
203   {
204     /* On EPOC which don't have globals we check our constant cipher list. */
205     int i;
206     for (i = 0; silc_default_ciphers[i].name; i++) {
207       if (!strcmp(silc_default_ciphers[i].name, name)) {
208         entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
209         break;
210       }
211     }
212   }
213 #endif /* SILC_SYMBIAN */
214
215   if (entry) {
216     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
217     (*new_cipher)->cipher = entry;
218     (*new_cipher)->context = silc_calloc(1, entry->context_len());
219     return TRUE;
220   }
221
222   return FALSE;
223 }
224
225 /* Free's the given cipher. */
226
227 void silc_cipher_free(SilcCipher cipher)
228 {
229   if (cipher) {
230     silc_free(cipher->context);
231     silc_free(cipher);
232   }
233 }
234
235 /* Returns TRUE if cipher `name' is supported. */
236
237 SilcBool silc_cipher_is_supported(const unsigned char *name)
238 {
239 #ifndef SILC_SYMBIAN
240   SilcCipherObject *entry;
241
242   if (silc_cipher_list) {
243     silc_dlist_start(silc_cipher_list);
244     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
245       if (!strcmp(entry->name, name))
246         return TRUE;
247     }
248   }
249 #else
250   {
251     int i;
252     for (i = 0; silc_default_ciphers[i].name; i++)
253       if (!strcmp(silc_default_ciphers[i].name, name))
254         return TRUE;
255   }
256 #endif /* SILC_SYMBIAN */
257   return FALSE;
258 }
259
260 /* Returns comma separated list of supported ciphers. */
261
262 char *silc_cipher_get_supported(void)
263 {
264   SilcCipherObject *entry;
265   char *list = NULL;
266   int len = 0;
267
268 #ifndef SILC_SYMBIAN
269   if (silc_cipher_list) {
270     silc_dlist_start(silc_cipher_list);
271     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
272       len += strlen(entry->name);
273       list = silc_realloc(list, len + 1);
274
275       memcpy(list + (len - strlen(entry->name)),
276              entry->name, strlen(entry->name));
277       memcpy(list + len, ",", 1);
278       len++;
279     }
280   }
281 #else
282   {
283     int i;
284     for (i = 0; silc_default_ciphers[i].name; i++) {
285       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
286       len += strlen(entry->name);
287       list = silc_realloc(list, len + 1);
288
289       memcpy(list + (len - strlen(entry->name)),
290              entry->name, strlen(entry->name));
291       memcpy(list + len, ",", 1);
292       len++;
293     }
294   }
295 #endif /* SILC_SYMBIAN */
296
297   list[len - 1] = 0;
298
299   return list;
300 }
301
302 /* Encrypts */
303
304 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
305                              unsigned char *dst, SilcUInt32 len,
306                              unsigned char *iv)
307 {
308   return cipher->cipher->encrypt(cipher->context, src, dst, len,
309                                  iv ? iv : cipher->iv);
310 }
311
312 /* Decrypts */
313
314 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
315                              unsigned char *dst, SilcUInt32 len,
316                              unsigned char *iv)
317 {
318   return cipher->cipher->decrypt(cipher->context, src, dst, len,
319                                  iv ? iv : cipher->iv);
320 }
321
322 /* Sets the key for the cipher */
323
324 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
325                              SilcUInt32 keylen, SilcBool encryption)
326 {
327   return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
328 }
329
330 /* Sets the IV (initial vector) for the cipher. */
331
332 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
333 {
334   memcpy(&cipher->iv, iv, cipher->cipher->iv_len);
335 }
336
337 /* Returns the IV (initial vector) of the cipher. */
338
339 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
340 {
341   return cipher->iv;
342 }
343
344 /* Returns the key length of the cipher. */
345
346 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
347 {
348   return cipher->cipher->key_len;
349 }
350
351 /* Returns the block size of the cipher. */
352
353 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
354 {
355   return cipher->cipher->block_len;
356 }
357
358 /* Returns the IV length of the cipher. */
359
360 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
361 {
362   return cipher->cipher->iv_len;
363 }
364
365 /* Returns the name of the cipher */
366
367 const char *silc_cipher_get_name(SilcCipher cipher)
368 {
369   return (const char *)cipher->cipher->name;
370 }
371
372 /* Returns cipher mode */
373
374 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
375 {
376   return cipher->cipher->mode;
377 }