5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
22 #include "ciphers.h" /* Includes cipher definitions */
24 /* The SilcCipher context */
25 struct SilcCipherStruct {
26 SilcCipherObject *cipher;
28 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
32 /* Dynamically registered list of ciphers. */
33 SilcDList silc_cipher_list = NULL;
34 #endif /* SILC_EPOC */
36 /* Static list of ciphers for silc_cipher_register_default(). */
37 const SilcCipherObject silc_default_ciphers[] =
39 { "aes-256-cbc", 16, 256, silc_aes_set_key,
40 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
41 silc_aes_decrypt_cbc, silc_aes_context_len },
42 { "aes-192-cbc", 16, 192, silc_aes_set_key,
43 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
44 silc_aes_decrypt_cbc, silc_aes_context_len },
45 { "aes-128-cbc", 16, 128, silc_aes_set_key,
46 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
47 silc_aes_decrypt_cbc, silc_aes_context_len },
48 { "twofish-256-cbc", 16, 256, silc_twofish_set_key,
49 silc_twofish_set_key_with_string,
50 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
51 silc_twofish_context_len },
52 { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
53 silc_twofish_set_key_with_string,
54 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
55 silc_twofish_context_len },
56 { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
57 silc_twofish_set_key_with_string,
58 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
59 silc_twofish_context_len },
60 { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
61 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
62 silc_cast_context_len },
63 { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
64 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
65 silc_cast_context_len },
66 { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
67 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
68 silc_cast_context_len },
69 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
70 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
71 silc_none_context_len },
73 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
76 /* Register a new cipher into SILC. This is used at the initialization of
77 the SILC. This function allocates a new object for the cipher to be
78 registered. Therefore, if memory has been allocated for the object sent
79 as argument it has to be free'd after this function returns succesfully. */
81 bool silc_cipher_register(const SilcCipherObject *cipher)
84 SilcCipherObject *new;
86 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
88 /* Check if exists already */
89 if (silc_cipher_list) {
90 SilcCipherObject *entry;
91 silc_dlist_start(silc_cipher_list);
92 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
93 if (!strcmp(entry->name, cipher->name))
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;
109 if (silc_cipher_list == NULL)
110 silc_cipher_list = silc_dlist_init();
111 silc_dlist_add(silc_cipher_list, new);
113 #endif /* SILC_EPOC */
117 /* Unregister a cipher from the SILC. */
119 bool silc_cipher_unregister(SilcCipherObject *cipher)
122 SilcCipherObject *entry;
124 SILC_LOG_DEBUG(("Unregistering cipher"));
126 if (!silc_cipher_list)
129 silc_dlist_start(silc_cipher_list);
130 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
131 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
132 silc_dlist_del(silc_cipher_list, entry);
133 silc_free(entry->name);
136 if (silc_dlist_count(silc_cipher_list) == 0) {
137 silc_dlist_uninit(silc_cipher_list);
138 silc_cipher_list = NULL;
145 #endif /* SILC_EPOC */
149 /* Function that registers all the default ciphers (all builtin ciphers).
150 The application may use this to register the default ciphers if specific
151 ciphers in any specific order is not wanted. */
153 bool silc_cipher_register_default(void)
158 for (i = 0; silc_default_ciphers[i].name; i++)
159 silc_cipher_register(&(silc_default_ciphers[i]));
161 #endif /* SILC_EPOC */
165 bool silc_cipher_unregister_all(void)
168 SilcCipherObject *entry;
170 if (!silc_cipher_list)
173 silc_dlist_start(silc_cipher_list);
174 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
175 silc_cipher_unregister(entry);
176 if (!silc_cipher_list)
179 #endif /* SILC_EPOC */
183 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
184 on error. The allocated cipher is returned in new_cipher argument. The
185 caller must set the key to the cipher after this function has returned
186 by calling the ciphers set_key function. */
188 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
190 SilcCipherObject *entry = NULL;
192 SILC_LOG_DEBUG(("Allocating new cipher object"));
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))
204 /* On EPOC which don't have globals we check our constant cipher list. */
206 for (i = 0; silc_default_ciphers[i].name; i++) {
207 if (!strcmp(silc_default_ciphers[i].name, name)) {
208 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
213 #endif /* SILC_EPOC */
216 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
217 (*new_cipher)->cipher = entry;
218 (*new_cipher)->context = silc_calloc(1, entry->context_len());
225 /* Free's the given cipher. */
227 void silc_cipher_free(SilcCipher cipher)
230 silc_free(cipher->context);
235 /* Returns TRUE if cipher `name' is supported. */
237 bool silc_cipher_is_supported(const unsigned char *name)
240 SilcCipherObject *entry;
242 if (silc_cipher_list) {
243 silc_dlist_start(silc_cipher_list);
244 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
245 if (!strcmp(entry->name, name))
252 for (i = 0; silc_default_ciphers[i].name; i++)
253 if (!strcmp(silc_default_ciphers[i].name, name))
256 #endif /* SILC_EPOC */
260 /* Returns comma separated list of supported ciphers. */
262 char *silc_cipher_get_supported(void)
264 SilcCipherObject *entry;
269 if (silc_cipher_list) {
270 silc_dlist_start(silc_cipher_list);
271 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
272 len += strlen(entry->name);
273 list = silc_realloc(list, len + 1);
275 memcpy(list + (len - strlen(entry->name)),
276 entry->name, strlen(entry->name));
277 memcpy(list + len, ",", 1);
284 for (i = 0; silc_default_ciphers[i].name; i++) {
285 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
286 len += strlen(entry->name);
287 list = silc_realloc(list, len + 1);
289 memcpy(list + (len - strlen(entry->name)),
290 entry->name, strlen(entry->name));
291 memcpy(list + len, ",", 1);
295 #endif /* SILC_EPOC */
304 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
305 unsigned char *dst, SilcUInt32 len,
309 assert((len & (cipher->cipher->block_len - 1)) == 0);
311 if (len & (cipher->cipher->block_len - 1))
313 return cipher->cipher->encrypt(cipher->context, src, dst, len,
314 iv ? iv : cipher->iv);
319 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
320 unsigned char *dst, SilcUInt32 len,
324 /* assert((len & (cipher->cipher->block_len - 1)) == 0); */
326 if (len & (cipher->cipher->block_len - 1))
328 return cipher->cipher->decrypt(cipher->context, src, dst, len,
329 iv ? iv : cipher->iv);
332 /* Sets the key for the cipher */
334 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
337 return cipher->cipher->set_key(cipher->context, key, keylen);
340 /* Sets the IV (initial vector) for the cipher. */
342 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
344 memset(&cipher->iv, 0, sizeof(cipher->iv));
345 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
348 /* Returns the IV (initial vector) of the cipher. */
350 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
355 /* Returns the key length of the cipher. */
357 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
359 return cipher->cipher->key_len;
362 /* Returns the block size of the cipher. */
364 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
366 return cipher->cipher->block_len;
369 /* Returns the name of the cipher */
371 const char *silc_cipher_get_name(SilcCipher cipher)
373 return (const char *)cipher->cipher->name;