5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 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.
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", silc_aes_set_key, silc_aes_set_key_with_string,
40 silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
42 { "aes-192-cbc", silc_aes_set_key, silc_aes_set_key_with_string,
43 silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
45 { "aes-128-cbc", silc_aes_set_key, silc_aes_set_key_with_string,
46 silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
48 { "twofish-256-cbc", silc_twofish_set_key, silc_twofish_set_key_with_string,
49 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
50 silc_twofish_context_len,
52 { "twofish-192-cbc", silc_twofish_set_key, silc_twofish_set_key_with_string,
53 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
54 silc_twofish_context_len,
56 { "twofish-128-cbc", silc_twofish_set_key, silc_twofish_set_key_with_string,
57 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
58 silc_twofish_context_len,
60 { "cast-256-cbc", silc_cast_set_key, silc_cast_set_key_with_string,
61 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
62 silc_cast_context_len,
64 { "cast-192-cbc", silc_cast_set_key, silc_cast_set_key_with_string,
65 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
66 silc_cast_context_len,
68 { "cast-128-cbc", silc_cast_set_key, silc_cast_set_key_with_string,
69 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
70 silc_cast_context_len,
73 { "none", silc_none_set_key, silc_none_set_key_with_string,
74 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
75 silc_none_context_len,
77 #endif /* SILC_DEBUG */
79 { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }
82 /* Register a new cipher into SILC. This is used at the initialization of
83 the SILC. This function allocates a new object for the cipher to be
84 registered. Therefore, if memory has been allocated for the object sent
85 as argument it has to be free'd after this function returns succesfully. */
87 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
90 SilcCipherObject *new;
92 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
94 /* Check if exists already */
95 if (silc_cipher_list) {
96 SilcCipherObject *entry;
97 silc_dlist_start(silc_cipher_list);
98 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
99 if (!strcmp(entry->name, cipher->name))
104 new = silc_calloc(1, sizeof(*new));
105 new->name = strdup(cipher->name);
106 new->key_len = cipher->key_len;
107 new->block_len = cipher->block_len;
108 new->iv_len = cipher->iv_len;
109 new->set_key = cipher->set_key;
110 new->set_key_with_string = cipher->set_key_with_string;
111 new->encrypt = cipher->encrypt;
112 new->decrypt = cipher->decrypt;
113 new->context_len = cipher->context_len;
116 if (silc_cipher_list == NULL)
117 silc_cipher_list = silc_dlist_init();
118 silc_dlist_add(silc_cipher_list, new);
120 #endif /* SILC_EPOC */
124 /* Unregister a cipher from the SILC. */
126 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
129 SilcCipherObject *entry;
131 SILC_LOG_DEBUG(("Unregistering cipher"));
133 if (!silc_cipher_list)
136 silc_dlist_start(silc_cipher_list);
137 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
138 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
139 silc_dlist_del(silc_cipher_list, entry);
140 silc_free(entry->name);
143 if (silc_dlist_count(silc_cipher_list) == 0) {
144 silc_dlist_uninit(silc_cipher_list);
145 silc_cipher_list = NULL;
152 #endif /* SILC_EPOC */
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 SilcBool silc_cipher_register_default(void)
165 for (i = 0; silc_default_ciphers[i].name; i++)
166 silc_cipher_register(&(silc_default_ciphers[i]));
168 #endif /* SILC_EPOC */
172 SilcBool silc_cipher_unregister_all(void)
175 SilcCipherObject *entry;
177 if (!silc_cipher_list)
180 silc_dlist_start(silc_cipher_list);
181 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
182 silc_cipher_unregister(entry);
183 if (!silc_cipher_list)
186 #endif /* SILC_EPOC */
190 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
191 on error. The allocated cipher is returned in new_cipher argument. The
192 caller must set the key to the cipher after this function has returned
193 by calling the ciphers set_key function. */
195 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
197 SilcCipherObject *entry = NULL;
199 SILC_LOG_DEBUG(("Allocating new cipher object"));
202 if (silc_cipher_list) {
203 silc_dlist_start(silc_cipher_list);
204 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
205 if (!strcmp(entry->name, name))
211 /* On EPOC which don't have globals we check our constant cipher list. */
213 for (i = 0; silc_default_ciphers[i].name; i++) {
214 if (!strcmp(silc_default_ciphers[i].name, name)) {
215 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
220 #endif /* SILC_EPOC */
223 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
224 (*new_cipher)->cipher = entry;
225 (*new_cipher)->context = silc_calloc(1, entry->context_len());
232 /* Free's the given cipher. */
234 void silc_cipher_free(SilcCipher cipher)
237 silc_free(cipher->context);
242 /* Returns TRUE if cipher `name' is supported. */
244 SilcBool silc_cipher_is_supported(const unsigned char *name)
247 SilcCipherObject *entry;
249 if (silc_cipher_list) {
250 silc_dlist_start(silc_cipher_list);
251 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
252 if (!strcmp(entry->name, name))
259 for (i = 0; silc_default_ciphers[i].name; i++)
260 if (!strcmp(silc_default_ciphers[i].name, name))
263 #endif /* SILC_EPOC */
267 /* Returns comma separated list of supported ciphers. */
269 char *silc_cipher_get_supported(void)
271 SilcCipherObject *entry;
276 if (silc_cipher_list) {
277 silc_dlist_start(silc_cipher_list);
278 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
279 len += strlen(entry->name);
280 list = silc_realloc(list, len + 1);
282 memcpy(list + (len - strlen(entry->name)),
283 entry->name, strlen(entry->name));
284 memcpy(list + len, ",", 1);
291 for (i = 0; silc_default_ciphers[i].name; i++) {
292 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
293 len += strlen(entry->name);
294 list = silc_realloc(list, len + 1);
296 memcpy(list + (len - strlen(entry->name)),
297 entry->name, strlen(entry->name));
298 memcpy(list + len, ",", 1);
302 #endif /* SILC_EPOC */
311 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
312 unsigned char *dst, SilcUInt32 len,
315 SILC_ASSERT((len & (cipher->cipher->block_len - 1)) == 0);
316 if (len & (cipher->cipher->block_len - 1))
318 return cipher->cipher->encrypt(cipher->context, src, dst, len,
319 iv ? iv : cipher->iv);
324 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
325 unsigned char *dst, SilcUInt32 len,
328 if (len & (cipher->cipher->block_len - 1))
330 return cipher->cipher->decrypt(cipher->context, src, dst, len,
331 iv ? iv : cipher->iv);
334 /* Sets the key for the cipher */
336 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
339 return cipher->cipher->set_key(cipher->context, key, keylen);
342 /* Sets the IV (initial vector) for the cipher. */
344 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
346 memcpy(&cipher->iv, iv, cipher->cipher->iv_len);
349 /* Returns the IV (initial vector) of the cipher. */
351 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
356 /* Returns the key length of the cipher. */
358 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
360 return cipher->cipher->key_len;
363 /* Returns the block size of the cipher. */
365 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
367 return cipher->cipher->block_len;
370 /* Returns the IV length of the cipher. */
372 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
374 return cipher->cipher->iv_len;
377 /* Returns the name of the cipher */
379 const char *silc_cipher_get_name(SilcCipher cipher)
381 return (const char *)cipher->cipher->name;