5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
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.
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.
22 #include "silcincludes.h"
24 #include "ciphers.h" /* Includes cipher definitions */
26 /* Dynamically registered list of ciphers. */
27 SilcDList silc_cipher_list = NULL;
29 /* Static list of ciphers for silc_cipher_register_default(). */
30 const SilcCipherObject silc_default_ciphers[] =
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 },
84 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
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. */
92 bool silc_cipher_register(SilcCipherObject *cipher)
94 SilcCipherObject *new;
96 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
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))
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;
119 if (silc_cipher_list == NULL)
120 silc_cipher_list = silc_dlist_init();
121 silc_dlist_add(silc_cipher_list, new);
126 /* Unregister a cipher from the SILC. */
128 bool silc_cipher_unregister(SilcCipherObject *cipher)
130 SilcCipherObject *entry;
132 SILC_LOG_DEBUG(("Unregistering cipher"));
134 if (!silc_cipher_list)
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);
144 if (silc_dlist_count(silc_cipher_list) == 0) {
145 silc_dlist_uninit(silc_cipher_list);
146 silc_cipher_list = NULL;
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. */
160 bool silc_cipher_register_default(void)
164 for (i = 0; silc_default_ciphers[i].name; i++)
165 silc_cipher_register((SilcCipherObject *)&(silc_default_ciphers[i]));
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. */
175 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
177 SilcCipherObject *entry;
179 SILC_LOG_DEBUG(("Allocating new cipher object"));
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;
200 /* Free's the given cipher. */
202 void silc_cipher_free(SilcCipher cipher)
205 silc_free(cipher->context);
210 /* Returns TRUE if cipher `name' is supported. */
212 bool silc_cipher_is_supported(const unsigned char *name)
214 SilcCipherObject *entry;
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))
227 /* Returns comma separated list of supported ciphers. */
229 char *silc_cipher_get_supported(void)
231 SilcCipherObject *entry;
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);
242 memcpy(list + (len - strlen(entry->name)),
243 entry->name, strlen(entry->name));
244 memcpy(list + len, ",", 1);
255 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
256 unsigned char *dst, SilcUInt32 len,
259 return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
264 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
265 unsigned char *dst, SilcUInt32 len,
268 return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
271 /* Sets the key for the cipher */
273 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
276 return cipher->cipher->set_key(cipher->context, key, keylen);
279 /* Sets the IV (initial vector) for the cipher. */
281 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
283 memset(&cipher->iv, 0, sizeof(cipher->iv));
284 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
287 /* Returns the IV (initial vector) of the cipher. The IV is returned
290 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
292 memcpy(iv, &cipher->iv, cipher->cipher->block_len);
295 /* Returns the key length of the cipher. */
297 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
299 return cipher->cipher->key_len;
302 /* Returns the block size of the cipher. */
304 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
306 return cipher->cipher->block_len;