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