785cec1f5e07a99e26bc968871c4bae89269d456
[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   { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
72     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
73     silc_cast_context_len },
74   { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
75     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
76     silc_cast_context_len },
77   { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
78     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
79     silc_cast_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 bool silc_cipher_register(SilcCipherObject *cipher)
93 {
94   SilcCipherObject *new;
95
96   SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
97
98   new = silc_calloc(1, sizeof(*new));
99   new->name = strdup(cipher->name);
100   new->block_len = cipher->block_len;
101   new->key_len = cipher->key_len;
102   new->set_key = cipher->set_key;
103   new->set_key_with_string = cipher->set_key_with_string;
104   new->encrypt = cipher->encrypt;
105   new->decrypt = cipher->decrypt;
106   new->context_len = cipher->context_len;
107
108   /* Add to list */
109   if (silc_cipher_list == NULL)
110     silc_cipher_list = silc_dlist_init();
111   silc_dlist_add(silc_cipher_list, new);
112
113   return TRUE;
114 }
115
116 /* Unregister a cipher from the SILC. */
117
118 bool silc_cipher_unregister(SilcCipherObject *cipher)
119 {
120   SilcCipherObject *entry;
121
122   SILC_LOG_DEBUG(("Unregistering cipher"));
123
124   if (!silc_cipher_list)
125     return FALSE;
126
127   silc_dlist_start(silc_cipher_list);
128   while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
129     if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
130       silc_dlist_del(silc_cipher_list, entry);
131
132       if (silc_dlist_count(silc_cipher_list) == 0) {
133         silc_dlist_uninit(silc_cipher_list);
134         silc_cipher_list = NULL;
135       }
136
137       return TRUE;
138     }
139   }
140
141   return FALSE;
142 }
143
144 /* Function that registers all the default ciphers (all builtin ciphers). 
145    The application may use this to register the default ciphers if specific
146    ciphers in any specific order is not wanted. */
147
148 bool silc_cipher_register_default(void)
149 {
150   int i;
151
152   for (i = 0; silc_default_ciphers[i].name; i++)
153     silc_cipher_register(&(silc_default_ciphers[i]));
154
155   return TRUE;
156 }
157
158 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
159    on error. The allocated cipher is returned in new_cipher argument. The
160    caller must set the key to the cipher after this function has returned
161    by calling the ciphers set_key function. */
162
163 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
164 {
165   SilcCipherObject *entry;
166
167   SILC_LOG_DEBUG(("Allocating new cipher object"));
168   
169   if (silc_cipher_list) {
170     silc_dlist_start(silc_cipher_list);
171     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
172       if (!strcmp(entry->name, name)) {
173         *new_cipher = silc_calloc(1, sizeof(**new_cipher));
174         (*new_cipher)->cipher = entry; 
175         (*new_cipher)->context = silc_calloc(1, entry->context_len());
176         (*new_cipher)->set_iv = silc_cipher_set_iv;
177         (*new_cipher)->get_iv = silc_cipher_get_iv;
178         (*new_cipher)->get_key_len = silc_cipher_get_key_len;
179         (*new_cipher)->get_block_len = silc_cipher_get_block_len;
180         return TRUE;
181       }
182     }
183   }
184
185   return FALSE;
186 }
187
188 /* Free's the given cipher. */
189
190 void silc_cipher_free(SilcCipher cipher)
191 {
192   if (cipher) {
193     silc_free(cipher->context);
194     silc_free(cipher);
195   }
196 }
197
198 /* Returns TRUE if cipher `name' is supported. */
199
200 bool silc_cipher_is_supported(const unsigned char *name)
201 {
202   SilcCipherObject *entry;
203
204   if (silc_cipher_list) {
205     silc_dlist_start(silc_cipher_list);
206     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
207       if (!strcmp(entry->name, name))
208         return TRUE;
209     }
210   }
211
212   return FALSE;
213 }
214
215 /* Returns comma separated list of supported ciphers. */
216
217 char *silc_cipher_get_supported(void)
218 {
219   SilcCipherObject *entry;
220   char *list = NULL;
221   int len;
222
223   len = 0;
224   if (silc_cipher_list) {
225     silc_dlist_start(silc_cipher_list);
226     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
227       len += strlen(entry->name);
228       list = silc_realloc(list, len + 1);
229       
230       memcpy(list + (len - strlen(entry->name)), 
231              entry->name, strlen(entry->name));
232       memcpy(list + len, ",", 1);
233       len++;
234     }
235     list[len - 1] = 0;
236   }
237
238   return list;
239 }
240
241 /* Encrypts */
242
243 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
244                          unsigned char *dst, uint32 len, 
245                          unsigned char *iv)
246 {
247   return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
248 }
249
250 /* Decrypts */
251
252 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
253                          unsigned char *dst, uint32 len, 
254                          unsigned char *iv)
255 {
256   return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
257 }
258
259 /* Sets the key for the cipher */
260
261 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
262                          uint32 keylen)
263 {
264   return cipher->cipher->set_key(cipher->context, key, keylen);
265 }
266
267 /* Sets the IV (initial vector) for the cipher. */
268
269 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
270 {
271   memset(&cipher->iv, 0, sizeof(cipher->iv));
272   memcpy(&cipher->iv, iv, cipher->cipher->block_len);
273 }
274
275 /* Returns the IV (initial vector) of the cipher. The IV is returned 
276    to 'iv' argument. */
277
278 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
279 {
280   memcpy(iv, &cipher->iv, cipher->cipher->block_len);
281 }
282
283 /* Returns the key length of the cipher. */
284
285 uint32 silc_cipher_get_key_len(SilcCipher cipher)
286 {
287   return cipher->cipher->key_len;
288 }
289
290 /* Returns the block size of the cipher. */
291
292 uint32 silc_cipher_get_block_len(SilcCipher cipher)
293 {
294   return cipher->cipher->block_len;
295 }