c321f6f9ea3258d76bb75ed499de3280d1387917
[silc.git] / lib / silccrypt / silccipher.c
1 /*
2
3   silccipher.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "silcincludes.h"
23
24 #include "ciphers.h"            /* Includes cipher definitions */
25
26 /* List of all ciphers in SILC. You can dynamically add new ciphers
27    into the list. At the initialization of SILC this list is filled with
28    the configured ciphers. */
29 struct SilcCipherListStruct {
30   SilcCipherObject *cipher;
31   struct SilcCipherListStruct *next;
32 };
33
34 /* Dynamically registered list of ciphers. */
35 struct SilcCipherListStruct *silc_cipher_list = NULL;
36
37 /* Staticly declared list of ciphers. This is used if system doesn't
38    support SIM's. */
39 SilcCipherObject silc_cipher_builtin_list[] =
40 {
41   { "aes-256-cbc", 16, 256, silc_aes_set_key, 
42     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
43     silc_aes_decrypt_cbc, silc_aes_context_len },
44   { "aes-192-cbc", 16, 192, silc_aes_set_key, 
45     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
46     silc_aes_decrypt_cbc, silc_aes_context_len },
47   { "aes-128-cbc", 16, 128, silc_aes_set_key, 
48     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
49     silc_aes_decrypt_cbc, silc_aes_context_len },
50   { "twofish-256-cbc", 16, 256, silc_twofish_set_key, 
51     silc_twofish_set_key_with_string,
52     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
53     silc_twofish_context_len },
54   { "twofish-192-cbc", 16, 192, silc_twofish_set_key, 
55     silc_twofish_set_key_with_string,
56     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
57     silc_twofish_context_len },
58   { "twofish-128-cbc", 16, 128, silc_twofish_set_key, 
59     silc_twofish_set_key_with_string,
60     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
61     silc_twofish_context_len },
62   { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
63     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
64     silc_rc6_context_len },
65   { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
66     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
67     silc_rc6_context_len },
68   { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
69     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
70     silc_rc6_context_len },
71   { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
72     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
73     silc_mars_context_len },
74   { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
75     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
76     silc_mars_context_len },
77   { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
78     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
79     silc_mars_context_len },
80   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
81     silc_none_encrypt_cbc, silc_none_decrypt_cbc, 
82     silc_none_context_len },
83
84   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
85 };
86
87 /* Register a new cipher into SILC. This is used at the initialization of
88    the SILC. This function allocates a new object for the cipher to be
89    registered. Therefore, if memory has been allocated for the object sent
90    as argument it has to be free'd after this function returns succesfully. */
91
92 int silc_cipher_register(SilcCipherObject *cipher)
93 {
94   struct SilcCipherListStruct *new, *c;
95
96   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
97
98   new = silc_calloc(1, sizeof(*new));
99   new->cipher = silc_calloc(1, sizeof(*new->cipher));
100
101   /* Set the pointers */
102   new->cipher->name = strdup(cipher->name);
103   new->cipher->block_len = cipher->block_len;
104   new->cipher->key_len = cipher->key_len;
105   new->cipher->set_key = cipher->set_key;
106   new->cipher->set_key_with_string = cipher->set_key_with_string;
107   new->cipher->encrypt = cipher->encrypt;
108   new->cipher->decrypt = cipher->decrypt;
109   new->cipher->context_len = cipher->context_len;
110   new->next = NULL;
111
112   /* Add the new cipher to the list */
113   if (!silc_cipher_list) {
114     silc_cipher_list = new;
115     return TRUE;
116   }
117
118   c = silc_cipher_list;
119   while (c) {
120     if (!c->next) {
121       c->next = new;
122       break;
123     }
124     c = c->next;
125   }
126
127   return TRUE;
128 }
129
130 /* Unregister a cipher from the SILC. */
131
132 int silc_cipher_unregister(SilcCipherObject *cipher)
133 {
134   struct SilcCipherListStruct *c, *tmp;
135
136   SILC_LOG_DEBUG(("Unregistering cipher"));
137
138   c = silc_cipher_list;
139   
140   if (cipher == SILC_ALL_CIPHERS) {
141     /* Unregister all ciphers */
142     while (c) {
143       tmp = c->next;
144       silc_free(c->cipher->name);
145       silc_free(c);
146       c = tmp;
147     }
148
149     return TRUE;
150   }
151
152   /* Unregister the cipher */
153   if (c->cipher == cipher) {
154     tmp = c->next;
155     silc_free(c->cipher->name);
156     silc_free(c);
157     silc_cipher_list = tmp;
158     
159     return TRUE;
160   }
161
162   while (c) {
163     if (c->next->cipher == cipher) {
164
165       tmp = c->next->next;
166       silc_free(c->cipher->name);
167       silc_free(c);
168       c->next = tmp;
169
170       return TRUE;
171     }
172
173     c = c->next;
174   }
175
176   return FALSE;
177 }
178
179 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
180    on error. The allocated cipher is returned in new_cipher argument. The
181    caller must set the key to the cipher after this function has returned
182    by calling the ciphers set_key function. */
183
184 int silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
185 {
186   struct SilcCipherListStruct *c;
187   int i;
188
189   SILC_LOG_DEBUG(("Allocating new cipher object"));
190
191   /* Allocate the new object */
192   *new_cipher = silc_calloc(1, sizeof(**new_cipher));
193   
194   if (silc_cipher_list) {
195
196     c = silc_cipher_list;
197     while (c) {
198       if (!strcmp(c->cipher->name, name))
199         break;
200       c = c->next;
201     }
202
203     if (!c || !c->cipher->context_len)
204       goto check_builtin;
205
206     /* Set the pointers */
207     (*new_cipher)->cipher = c->cipher;
208     (*new_cipher)->context = silc_calloc(1, c->cipher->context_len());
209     (*new_cipher)->set_iv = silc_cipher_set_iv;
210     (*new_cipher)->get_iv = silc_cipher_get_iv;
211     (*new_cipher)->get_key_len = silc_cipher_get_key_len;
212     (*new_cipher)->get_block_len = silc_cipher_get_block_len;
213     
214     return TRUE;
215   }
216
217  check_builtin:
218
219   for (i = 0; silc_cipher_builtin_list[i].name; i++)
220     if (!strcmp(silc_cipher_builtin_list[i].name, name))
221       break;
222
223   if (silc_cipher_builtin_list[i].name == NULL) {
224     silc_free(*new_cipher);
225     *new_cipher = NULL;
226     return FALSE;
227   }
228
229   /* Set the pointers */
230   (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
231   (*new_cipher)->context = 
232     silc_calloc(1, (*new_cipher)->cipher->context_len());
233   (*new_cipher)->set_iv = silc_cipher_set_iv;
234   (*new_cipher)->get_iv = silc_cipher_get_iv;
235   (*new_cipher)->get_key_len = silc_cipher_get_key_len;
236   (*new_cipher)->get_block_len = silc_cipher_get_block_len;
237   memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
238
239   return TRUE;
240 }
241
242 /* Free's the given cipher. */
243
244 void silc_cipher_free(SilcCipher cipher)
245 {
246   if (cipher) {
247     silc_free(cipher->context);
248     silc_free(cipher);
249   }
250 }
251
252 /* Returns TRUE if cipher `name' is supported. */
253
254 int silc_cipher_is_supported(const unsigned char *name)
255 {
256   struct SilcCipherListStruct *c;
257   int i;
258
259   if (silc_cipher_list) {
260     c = silc_cipher_list;
261
262     while (c) {
263       if (!strcmp(c->cipher->name, name))
264         return TRUE;
265       c = c->next;
266     }
267   }
268
269   for (i = 0; silc_cipher_builtin_list[i].name; i++)
270     if (!strcmp(silc_cipher_builtin_list[i].name, name))
271       return TRUE;
272
273   return FALSE;
274 }
275
276 /* Returns comma separated list of supported ciphers. */
277
278 char *silc_cipher_get_supported()
279 {
280   char *list = NULL;
281   int i, len;
282   struct SilcCipherListStruct *c;
283
284   len = 0;
285   if (silc_cipher_list) {
286     c = silc_cipher_list;
287
288     while (c) {
289       len += strlen(c->cipher->name);
290       list = silc_realloc(list, len + 1);
291       
292       memcpy(list + (len - strlen(c->cipher->name)), 
293              c->cipher->name, strlen(c->cipher->name));
294       memcpy(list + len, ",", 1);
295       len++;
296       
297       c = c->next;
298     }
299   }
300
301   for (i = 0; silc_cipher_builtin_list[i].name; i++) {
302     len += strlen(silc_cipher_builtin_list[i].name);
303     list = silc_realloc(list, len + 1);
304     
305     memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)), 
306            silc_cipher_builtin_list[i].name, 
307            strlen(silc_cipher_builtin_list[i].name));
308     memcpy(list + len, ",", 1);
309     len++;
310   }
311
312   list[len - 1] = 0;
313
314   return list;
315 }
316
317 /* Encrypts */
318
319 int silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
320                         unsigned char *dst, uint32 len, 
321                         unsigned char *iv)
322 {
323   return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
324 }
325
326 /* Decrypts */
327
328 int silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
329                         unsigned char *dst, uint32 len, 
330                         unsigned char *iv)
331 {
332   return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
333 }
334
335 /* Sets the key for the cipher */
336
337 int silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
338                         uint32 keylen)
339 {
340   return cipher->cipher->set_key(cipher->context, key, keylen);
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   memset(&cipher->iv, 0, sizeof(cipher->iv));
348   memcpy(&cipher->iv, iv, cipher->cipher->block_len);
349 }
350
351 /* Returns the IV (initial vector) of the cipher. The IV is returned 
352    to 'iv' argument. */
353
354 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
355 {
356   memcpy(iv, &cipher->iv, cipher->cipher->block_len);
357 }
358
359 /* Returns the key length of the cipher. */
360
361 uint32 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 uint32 silc_cipher_get_block_len(SilcCipher cipher)
369 {
370   return cipher->cipher->block_len;
371 }