updates.
[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"));
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)
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     return FALSE;
226   }
227
228   /* Set the pointers */
229   (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
230   (*new_cipher)->context = 
231     silc_calloc(1, (*new_cipher)->cipher->context_len());
232   (*new_cipher)->set_iv = silc_cipher_set_iv;
233   (*new_cipher)->get_iv = silc_cipher_get_iv;
234   (*new_cipher)->get_key_len = silc_cipher_get_key_len;
235   (*new_cipher)->get_block_len = silc_cipher_get_block_len;
236   memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
237
238   return TRUE;
239 }
240
241 /* Free's the given cipher. */
242
243 void silc_cipher_free(SilcCipher cipher)
244 {
245   if (cipher) {
246     silc_free(cipher->context);
247     silc_free(cipher);
248   }
249 }
250
251 /* Returns TRUE if cipher `name' is supported. */
252
253 int silc_cipher_is_supported(const unsigned char *name)
254 {
255   struct SilcCipherListStruct *c;
256   int i;
257
258   if (silc_cipher_list) {
259     c = silc_cipher_list;
260
261     while (c) {
262       if (!strcmp(c->cipher->name, name))
263         return TRUE;
264       c = c->next;
265     }
266   }
267
268   for (i = 0; silc_cipher_builtin_list[i].name; i++)
269     if (!strcmp(silc_cipher_builtin_list[i].name, name))
270       return TRUE;
271
272   return FALSE;
273 }
274
275 /* Returns comma separated list of supported ciphers. */
276
277 char *silc_cipher_get_supported()
278 {
279   char *list = NULL;
280   int i, len;
281   struct SilcCipherListStruct *c;
282
283   len = 0;
284   if (silc_cipher_list) {
285     c = silc_cipher_list;
286
287     while (c) {
288       len += strlen(c->cipher->name);
289       list = silc_realloc(list, len + 1);
290       
291       memcpy(list + (len - strlen(c->cipher->name)), 
292              c->cipher->name, strlen(c->cipher->name));
293       memcpy(list + len, ",", 1);
294       len++;
295       
296       c = c->next;
297     }
298   }
299
300   for (i = 0; silc_cipher_builtin_list[i].name; i++) {
301     len += strlen(silc_cipher_builtin_list[i].name);
302     list = silc_realloc(list, len + 1);
303     
304     memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)), 
305            silc_cipher_builtin_list[i].name, 
306            strlen(silc_cipher_builtin_list[i].name));
307     memcpy(list + len, ",", 1);
308     len++;
309   }
310
311   list[len - 1] = 0;
312
313   return list;
314 }
315
316 /* Sets the IV (initial vector) for the cipher. */
317
318 void silc_cipher_set_iv(SilcCipher itself, const unsigned char *iv)
319 {
320   memset(&itself->iv, 0, sizeof(itself->iv));
321   memcpy(&itself->iv, iv, itself->cipher->block_len);
322 }
323
324 /* Returns the IV (initial vector) of the cipher. The IV is returned 
325    to 'iv' argument. */
326
327 void silc_cipher_get_iv(SilcCipher itself, unsigned char *iv)
328 {
329   memcpy(iv, &itself->iv, itself->cipher->block_len);
330 }
331
332 /* Returns the key length of the cipher. */
333
334 unsigned int silc_cipher_get_key_len(SilcCipher itself, 
335                                      const unsigned char *name)
336 {
337   return itself->cipher->key_len;
338 }
339
340 /* Returns the block size of the cipher. */
341
342 unsigned int silc_cipher_get_block_len(SilcCipher itself)
343 {
344   return itself->cipher->block_len;
345 }