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