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   }
227
228   list[len - 1] = 0;
229
230   return list;
231 }
232
233 /* Encrypts */
234
235 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
236                          unsigned char *dst, uint32 len, 
237                          unsigned char *iv)
238 {
239   return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
240 }
241
242 /* Decrypts */
243
244 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
245                          unsigned char *dst, uint32 len, 
246                          unsigned char *iv)
247 {
248   return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
249 }
250
251 /* Sets the key for the cipher */
252
253 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
254                          uint32 keylen)
255 {
256   return cipher->cipher->set_key(cipher->context, key, keylen);
257 }
258
259 /* Sets the IV (initial vector) for the cipher. */
260
261 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
262 {
263   memset(&cipher->iv, 0, sizeof(cipher->iv));
264   memcpy(&cipher->iv, iv, cipher->cipher->block_len);
265 }
266
267 /* Returns the IV (initial vector) of the cipher. The IV is returned 
268    to 'iv' argument. */
269
270 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
271 {
272   memcpy(iv, &cipher->iv, cipher->cipher->block_len);
273 }
274
275 /* Returns the key length of the cipher. */
276
277 uint32 silc_cipher_get_key_len(SilcCipher cipher)
278 {
279   return cipher->cipher->key_len;
280 }
281
282 /* Returns the block size of the cipher. */
283
284 uint32 silc_cipher_get_block_len(SilcCipher cipher)
285 {
286   return cipher->cipher->block_len;
287 }