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 /* Dynamically registered list of ciphers. */
27 SilcDList silc_cipher_list = NULL;
28
29 /* Static list of ciphers for silc_cipher_register_default(). */
30 SilcCipherObject silc_default_ciphers[] =
31 {
32   { "aes-256-cbc", 16, 256, silc_aes_set_key, 
33     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
34     silc_aes_decrypt_cbc, silc_aes_context_len },
35   { "aes-192-cbc", 16, 192, silc_aes_set_key, 
36     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
37     silc_aes_decrypt_cbc, silc_aes_context_len },
38   { "aes-128-cbc", 16, 128, silc_aes_set_key, 
39     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
40     silc_aes_decrypt_cbc, silc_aes_context_len },
41   { "twofish-256-cbc", 16, 256, silc_twofish_set_key, 
42     silc_twofish_set_key_with_string,
43     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
44     silc_twofish_context_len },
45   { "twofish-192-cbc", 16, 192, silc_twofish_set_key, 
46     silc_twofish_set_key_with_string,
47     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
48     silc_twofish_context_len },
49   { "twofish-128-cbc", 16, 128, silc_twofish_set_key, 
50     silc_twofish_set_key_with_string,
51     silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
52     silc_twofish_context_len },
53   { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
54     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
55     silc_rc6_context_len },
56   { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
57     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
58     silc_rc6_context_len },
59   { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
60     silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
61     silc_rc6_context_len },
62   { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
63     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
64     silc_mars_context_len },
65   { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
66     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
67     silc_mars_context_len },
68   { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
69     silc_mars_encrypt_cbc, silc_mars_decrypt_cbc, 
70     silc_mars_context_len },
71   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
72     silc_none_encrypt_cbc, silc_none_decrypt_cbc, 
73     silc_none_context_len },
74
75   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
76 };
77
78 /* Register a new cipher into SILC. This is used at the initialization of
79    the SILC. This function allocates a new object for the cipher to be
80    registered. Therefore, if memory has been allocated for the object sent
81    as argument it has to be free'd after this function returns succesfully. */
82
83 bool silc_cipher_register(SilcCipherObject *cipher)
84 {
85   SilcCipherObject *new;
86
87   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
88
89   new = silc_calloc(1, sizeof(*new));
90   new->name = strdup(cipher->name);
91   new->block_len = cipher->block_len;
92   new->key_len = cipher->key_len;
93   new->set_key = cipher->set_key;
94   new->set_key_with_string = cipher->set_key_with_string;
95   new->encrypt = cipher->encrypt;
96   new->decrypt = cipher->decrypt;
97   new->context_len = cipher->context_len;
98
99   /* Add to list */
100   if (silc_cipher_list == NULL)
101     silc_cipher_list = silc_dlist_init();
102   silc_dlist_add(silc_cipher_list, new);
103
104   return TRUE;
105 }
106
107 /* Unregister a cipher from the SILC. */
108
109 bool silc_cipher_unregister(SilcCipherObject *cipher)
110 {
111   SilcCipherObject *entry;
112
113   SILC_LOG_DEBUG(("Unregistering cipher"));
114
115   if (!silc_cipher_list)
116     return FALSE;
117
118   silc_dlist_start(silc_cipher_list);
119   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
120     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
121       silc_dlist_del(silc_cipher_list, entry);
122
123       if (silc_dlist_count(silc_cipher_list) == 0) {
124         silc_dlist_uninit(silc_cipher_list);
125         silc_cipher_list = NULL;
126       }
127
128       return TRUE;
129     }
130   }
131
132   return FALSE;
133 }
134
135 /* Function that registers all the default ciphers (all builtin ciphers). 
136    The application may use this to register the default ciphers if specific
137    ciphers in any specific order is not wanted. */
138
139 bool silc_cipher_register_default(void)
140 {
141   int i;
142
143   for (i = 0; silc_default_ciphers[i].name; i++)
144     silc_cipher_register(&(silc_default_ciphers[i]));
145
146   return TRUE;
147 }
148
149 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
150    on error. The allocated cipher is returned in new_cipher argument. The
151    caller must set the key to the cipher after this function has returned
152    by calling the ciphers set_key function. */
153
154 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
155 {
156   SilcCipherObject *entry;
157
158   SILC_LOG_DEBUG(("Allocating new cipher object"));
159   
160   if (silc_cipher_list) {
161     silc_dlist_start(silc_cipher_list);
162     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
163       if (!strcmp(entry->name, name)) {
164         *new_cipher = silc_calloc(1, sizeof(**new_cipher));
165         (*new_cipher)->cipher = entry; 
166         (*new_cipher)->context = silc_calloc(1, entry->context_len());
167         (*new_cipher)->set_iv = silc_cipher_set_iv;
168         (*new_cipher)->get_iv = silc_cipher_get_iv;
169         (*new_cipher)->get_key_len = silc_cipher_get_key_len;
170         (*new_cipher)->get_block_len = silc_cipher_get_block_len;
171         return TRUE;
172       }
173     }
174   }
175
176   return FALSE;
177 }
178
179 /* Free's the given cipher. */
180
181 void silc_cipher_free(SilcCipher cipher)
182 {
183   if (cipher) {
184     silc_free(cipher->context);
185     silc_free(cipher);
186   }
187 }
188
189 /* Returns TRUE if cipher `name' is supported. */
190
191 bool silc_cipher_is_supported(const unsigned char *name)
192 {
193   SilcCipherObject *entry;
194
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         return TRUE;
200     }
201   }
202
203   return FALSE;
204 }
205
206 /* Returns comma separated list of supported ciphers. */
207
208 char *silc_cipher_get_supported(void)
209 {
210   SilcCipherObject *entry;
211   char *list = NULL;
212   int len;
213
214   len = 0;
215   if (silc_cipher_list) {
216     silc_dlist_start(silc_cipher_list);
217     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
218       len += strlen(entry->name);
219       list = silc_realloc(list, len + 1);
220       
221       memcpy(list + (len - strlen(entry->name)), 
222              entry->name, strlen(entry->name));
223       memcpy(list + len, ",", 1);
224       len++;
225     }
226     list[len - 1] = 0;
227   }
228
229   return list;
230 }
231
232 /* Encrypts */
233
234 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
235                          unsigned char *dst, uint32 len, 
236                          unsigned char *iv)
237 {
238   return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
239 }
240
241 /* Decrypts */
242
243 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
244                          unsigned char *dst, uint32 len, 
245                          unsigned char *iv)
246 {
247   return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
248 }
249
250 /* Sets the key for the cipher */
251
252 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
253                          uint32 keylen)
254 {
255   return cipher->cipher->set_key(cipher->context, key, keylen);
256 }
257
258 /* Sets the IV (initial vector) for the cipher. */
259
260 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
261 {
262   memset(&cipher->iv, 0, sizeof(cipher->iv));
263   memcpy(&cipher->iv, iv, cipher->cipher->block_len);
264 }
265
266 /* Returns the IV (initial vector) of the cipher. The IV is returned 
267    to 'iv' argument. */
268
269 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
270 {
271   memcpy(iv, &cipher->iv, cipher->cipher->block_len);
272 }
273
274 /* Returns the key length of the cipher. */
275
276 uint32 silc_cipher_get_key_len(SilcCipher cipher)
277 {
278   return cipher->cipher->key_len;
279 }
280
281 /* Returns the block size of the cipher. */
282
283 uint32 silc_cipher_get_block_len(SilcCipher cipher)
284 {
285   return cipher->cipher->block_len;
286 }