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,
40 silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
42 { "aes-192-cbc", silc_aes_set_key,
43 silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
45 { "aes-128-cbc", silc_aes_set_key,
46 silc_aes_encrypt_cbc, silc_aes_decrypt_cbc, silc_aes_context_len,
48 { "twofish-256-cbc", silc_twofish_set_key,
49 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
50 silc_twofish_context_len,
52 { "twofish-192-cbc", silc_twofish_set_key,
53 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
54 silc_twofish_context_len,
56 { "twofish-128-cbc", silc_twofish_set_key,
57 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
58 silc_twofish_context_len,
60 { "cast-256-cbc", silc_cast_set_key,
61 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
62 silc_cast_context_len,
64 { "cast-192-cbc", silc_cast_set_key,
65 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
66 silc_cast_context_len,
68 { "cast-128-cbc", silc_cast_set_key,
69 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
70 silc_cast_context_len,
73 { "none", silc_none_set_key,
74 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
75 silc_none_context_len,
77 #endif /* SILC_DEBUG */
79 { 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->encrypt = cipher->encrypt;
111 new->decrypt = cipher->decrypt;
112 new->context_len = cipher->context_len;
115 if (silc_cipher_list == NULL)
116 silc_cipher_list = silc_dlist_init();
117 silc_dlist_add(silc_cipher_list, new);
119 #endif /* SILC_EPOC */
123 /* Unregister a cipher from the SILC. */
125 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
128 SilcCipherObject *entry;
130 SILC_LOG_DEBUG(("Unregistering cipher"));
132 if (!silc_cipher_list)
135 silc_dlist_start(silc_cipher_list);
136 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
137 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
138 silc_dlist_del(silc_cipher_list, entry);
139 silc_free(entry->name);
142 if (silc_dlist_count(silc_cipher_list) == 0) {
143 silc_dlist_uninit(silc_cipher_list);
144 silc_cipher_list = NULL;
151 #endif /* SILC_EPOC */
155 /* Function that registers all the default ciphers (all builtin ciphers).
156 The application may use this to register the default ciphers if specific
157 ciphers in any specific order is not wanted. */
159 SilcBool silc_cipher_register_default(void)
164 for (i = 0; silc_default_ciphers[i].name; i++)
165 silc_cipher_register(&(silc_default_ciphers[i]));
167 #endif /* SILC_EPOC */
171 SilcBool silc_cipher_unregister_all(void)
174 SilcCipherObject *entry;
176 if (!silc_cipher_list)
179 silc_dlist_start(silc_cipher_list);
180 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
181 silc_cipher_unregister(entry);
182 if (!silc_cipher_list)
185 #endif /* SILC_EPOC */
189 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
190 on error. The allocated cipher is returned in new_cipher argument. The
191 caller must set the key to the cipher after this function has returned
192 by calling the ciphers set_key function. */
194 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
196 SilcCipherObject *entry = NULL;
198 SILC_LOG_DEBUG(("Allocating new cipher object"));
201 if (silc_cipher_list) {
202 silc_dlist_start(silc_cipher_list);
203 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
204 if (!strcmp(entry->name, name))
210 /* On EPOC which don't have globals we check our constant cipher list. */
212 for (i = 0; silc_default_ciphers[i].name; i++) {
213 if (!strcmp(silc_default_ciphers[i].name, name)) {
214 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
219 #endif /* SILC_EPOC */
222 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
223 (*new_cipher)->cipher = entry;
224 (*new_cipher)->context = silc_calloc(1, entry->context_len());
231 /* Free's the given cipher. */
233 void silc_cipher_free(SilcCipher cipher)
236 silc_free(cipher->context);
241 /* Returns TRUE if cipher `name' is supported. */
243 SilcBool silc_cipher_is_supported(const unsigned char *name)
246 SilcCipherObject *entry;
248 if (silc_cipher_list) {
249 silc_dlist_start(silc_cipher_list);
250 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
251 if (!strcmp(entry->name, name))
258 for (i = 0; silc_default_ciphers[i].name; i++)
259 if (!strcmp(silc_default_ciphers[i].name, name))
262 #endif /* SILC_EPOC */
266 /* Returns comma separated list of supported ciphers. */
268 char *silc_cipher_get_supported(void)
270 SilcCipherObject *entry;
275 if (silc_cipher_list) {
276 silc_dlist_start(silc_cipher_list);
277 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
278 len += strlen(entry->name);
279 list = silc_realloc(list, len + 1);
281 memcpy(list + (len - strlen(entry->name)),
282 entry->name, strlen(entry->name));
283 memcpy(list + len, ",", 1);
290 for (i = 0; silc_default_ciphers[i].name; i++) {
291 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
292 len += strlen(entry->name);
293 list = silc_realloc(list, len + 1);
295 memcpy(list + (len - strlen(entry->name)),
296 entry->name, strlen(entry->name));
297 memcpy(list + len, ",", 1);
301 #endif /* SILC_EPOC */
310 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
311 unsigned char *dst, SilcUInt32 len,
314 SILC_ASSERT((len & (cipher->cipher->block_len - 1)) == 0);
315 if (silc_unlikely(len & (cipher->cipher->block_len - 1)))
317 return cipher->cipher->encrypt(cipher->context, src, dst, len,
318 iv ? iv : cipher->iv);
323 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
324 unsigned char *dst, SilcUInt32 len,
327 if (silc_unlikely(len & (cipher->cipher->block_len - 1)))
329 return cipher->cipher->decrypt(cipher->context, src, dst, len,
330 iv ? iv : cipher->iv);
333 /* Sets the key for the cipher */
335 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
336 SilcUInt32 keylen, SilcBool encryption)
338 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
341 /* Sets the IV (initial vector) for the cipher. */
343 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
345 memcpy(&cipher->iv, iv, cipher->cipher->iv_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 IV length of the cipher. */
371 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
373 return cipher->cipher->iv_len;
376 /* Returns the name of the cipher */
378 const char *silc_cipher_get_name(SilcCipher cipher)
380 return (const char *)cipher->cipher->name;