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 /* Macro to define cipher to cipher list */
37 #define SILC_CIPHER_API_DEF(name, cipher, keylen, blocklen, ivlen) \
38 { name, silc_##cipher##_set_key, silc_##cipher##_encrypt, \
39 silc_##cipher##_decrypt, silc_##cipher##_context_len, \
40 keylen, blocklen, ivlen }
42 /* Static list of ciphers for silc_cipher_register_default(). */
43 const SilcCipherObject silc_default_ciphers[] =
45 SILC_CIPHER_API_DEF("aes-256-ctr", aes_ctr, 256, 16, 16),
46 SILC_CIPHER_API_DEF("aes-192-ctr", aes_ctr, 192, 16, 16),
47 SILC_CIPHER_API_DEF("aes-128-ctr", aes_ctr, 128, 16, 16),
48 SILC_CIPHER_API_DEF("aes-256-cbc", aes_cbc, 256, 16, 16),
49 SILC_CIPHER_API_DEF("aes-192-cbc", aes_cbc, 192, 16, 16),
50 SILC_CIPHER_API_DEF("aes-128-cbc", aes_cbc, 128, 16, 16),
51 SILC_CIPHER_API_DEF("twofish-256-cbc", twofish_cbc, 256, 16, 16),
52 SILC_CIPHER_API_DEF("twofish-192-cbc", twofish_cbc, 192, 16, 16),
53 SILC_CIPHER_API_DEF("twofish-128-cbc", twofish_cbc, 128, 16, 16),
54 SILC_CIPHER_API_DEF("cast-256-cbc", cast_cbc, 256, 16, 16),
55 SILC_CIPHER_API_DEF("cast-192-cbc", cast_cbc, 192, 16, 16),
56 SILC_CIPHER_API_DEF("cast-128-cbc", cast_cbc, 128, 16, 16),
58 SILC_CIPHER_API_DEF("none", none, 0, 0, 0),
59 #endif /* SILC_DEBUG */
60 { NULL, NULL, 0, 0, 0 }
63 /* Register a new cipher into SILC. This is used at the initialization of
64 the SILC. This function allocates a new object for the cipher to be
65 registered. Therefore, if memory has been allocated for the object sent
66 as argument it has to be free'd after this function returns succesfully. */
68 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
71 SilcCipherObject *new;
73 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
75 /* Check if exists already */
76 if (silc_cipher_list) {
77 SilcCipherObject *entry;
78 silc_dlist_start(silc_cipher_list);
79 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
80 if (!strcmp(entry->name, cipher->name))
85 new = silc_calloc(1, sizeof(*new));
86 new->name = strdup(cipher->name);
87 new->key_len = cipher->key_len;
88 new->block_len = cipher->block_len;
89 new->iv_len = cipher->iv_len;
90 new->set_key = cipher->set_key;
91 new->encrypt = cipher->encrypt;
92 new->decrypt = cipher->decrypt;
93 new->context_len = cipher->context_len;
96 if (silc_cipher_list == NULL)
97 silc_cipher_list = silc_dlist_init();
98 silc_dlist_add(silc_cipher_list, new);
100 #endif /* SILC_EPOC */
104 /* Unregister a cipher from the SILC. */
106 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
109 SilcCipherObject *entry;
111 SILC_LOG_DEBUG(("Unregistering cipher"));
113 if (!silc_cipher_list)
116 silc_dlist_start(silc_cipher_list);
117 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
118 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
119 silc_dlist_del(silc_cipher_list, entry);
120 silc_free(entry->name);
123 if (silc_dlist_count(silc_cipher_list) == 0) {
124 silc_dlist_uninit(silc_cipher_list);
125 silc_cipher_list = NULL;
132 #endif /* SILC_EPOC */
136 /* Function that registers all the default ciphers (all builtin ciphers).
137 The application may use this to register the default ciphers if specific
138 ciphers in any specific order is not wanted. */
140 SilcBool silc_cipher_register_default(void)
145 for (i = 0; silc_default_ciphers[i].name; i++)
146 silc_cipher_register(&(silc_default_ciphers[i]));
148 #endif /* SILC_EPOC */
152 SilcBool silc_cipher_unregister_all(void)
155 SilcCipherObject *entry;
157 if (!silc_cipher_list)
160 silc_dlist_start(silc_cipher_list);
161 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
162 silc_cipher_unregister(entry);
163 if (!silc_cipher_list)
166 #endif /* SILC_EPOC */
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 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
177 SilcCipherObject *entry = NULL;
179 SILC_LOG_DEBUG(("Allocating new cipher object"));
182 if (silc_cipher_list) {
183 silc_dlist_start(silc_cipher_list);
184 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
185 if (!strcmp(entry->name, name))
191 /* On EPOC which don't have globals we check our constant cipher list. */
193 for (i = 0; silc_default_ciphers[i].name; i++) {
194 if (!strcmp(silc_default_ciphers[i].name, name)) {
195 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
200 #endif /* SILC_EPOC */
203 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
204 (*new_cipher)->cipher = entry;
205 (*new_cipher)->context = silc_calloc(1, entry->context_len());
212 /* Free's the given cipher. */
214 void silc_cipher_free(SilcCipher cipher)
217 silc_free(cipher->context);
222 /* Returns TRUE if cipher `name' is supported. */
224 SilcBool silc_cipher_is_supported(const unsigned char *name)
227 SilcCipherObject *entry;
229 if (silc_cipher_list) {
230 silc_dlist_start(silc_cipher_list);
231 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
232 if (!strcmp(entry->name, name))
239 for (i = 0; silc_default_ciphers[i].name; i++)
240 if (!strcmp(silc_default_ciphers[i].name, name))
243 #endif /* SILC_EPOC */
247 /* Returns comma separated list of supported ciphers. */
249 char *silc_cipher_get_supported(void)
251 SilcCipherObject *entry;
256 if (silc_cipher_list) {
257 silc_dlist_start(silc_cipher_list);
258 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
259 len += strlen(entry->name);
260 list = silc_realloc(list, len + 1);
262 memcpy(list + (len - strlen(entry->name)),
263 entry->name, strlen(entry->name));
264 memcpy(list + len, ",", 1);
271 for (i = 0; silc_default_ciphers[i].name; i++) {
272 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
273 len += strlen(entry->name);
274 list = silc_realloc(list, len + 1);
276 memcpy(list + (len - strlen(entry->name)),
277 entry->name, strlen(entry->name));
278 memcpy(list + len, ",", 1);
282 #endif /* SILC_EPOC */
291 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
292 unsigned char *dst, SilcUInt32 len,
295 return cipher->cipher->encrypt(cipher->context, src, dst, len,
296 iv ? iv : cipher->iv);
301 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
302 unsigned char *dst, SilcUInt32 len,
305 return cipher->cipher->decrypt(cipher->context, src, dst, len,
306 iv ? iv : cipher->iv);
309 /* Sets the key for the cipher */
311 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
312 SilcUInt32 keylen, SilcBool encryption)
314 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
317 /* Sets the IV (initial vector) for the cipher. */
319 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
321 memcpy(&cipher->iv, iv, cipher->cipher->iv_len);
324 /* Returns the IV (initial vector) of the cipher. */
326 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
331 /* Returns the key length of the cipher. */
333 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
335 return cipher->cipher->key_len;
338 /* Returns the block size of the cipher. */
340 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
342 return cipher->cipher->block_len;
345 /* Returns the IV length of the cipher. */
347 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
349 return cipher->cipher->iv_len;
352 /* Returns the name of the cipher */
354 const char *silc_cipher_get_name(SilcCipher cipher)
356 return (const char *)cipher->cipher->name;