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_SYMBIAN */
36 /* Macro to define cipher to cipher list */
37 #define SILC_CIPHER_API_DEF(name, cipher, keylen, blocklen, ivlen, mode) \
38 { name, silc_##cipher##_set_key, silc_##cipher##_encrypt, \
39 silc_##cipher##_decrypt, silc_##cipher##_context_len, \
40 keylen, blocklen, ivlen, mode }
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_MODE_CTR),
47 SILC_CIPHER_API_DEF("aes-192-ctr", aes_ctr, 192, 16, 16,
48 SILC_CIPHER_MODE_CTR),
49 SILC_CIPHER_API_DEF("aes-128-ctr", aes_ctr, 128, 16, 16,
50 SILC_CIPHER_MODE_CTR),
51 SILC_CIPHER_API_DEF("aes-256-cbc", aes_cbc, 256, 16, 16,
52 SILC_CIPHER_MODE_CBC),
53 SILC_CIPHER_API_DEF("aes-192-cbc", aes_cbc, 192, 16, 16,
54 SILC_CIPHER_MODE_CBC),
55 SILC_CIPHER_API_DEF("aes-128-cbc", aes_cbc, 128, 16, 16,
56 SILC_CIPHER_MODE_CBC),
57 SILC_CIPHER_API_DEF("twofish-256-cbc", twofish_cbc, 256, 16, 16,
58 SILC_CIPHER_MODE_CBC),
59 SILC_CIPHER_API_DEF("twofish-192-cbc", twofish_cbc, 192, 16, 16,
60 SILC_CIPHER_MODE_CBC),
61 SILC_CIPHER_API_DEF("twofish-128-cbc", twofish_cbc, 128, 16, 16,
62 SILC_CIPHER_MODE_CBC),
63 SILC_CIPHER_API_DEF("cast-256-cbc", cast_cbc, 256, 16, 16,
64 SILC_CIPHER_MODE_CBC),
65 SILC_CIPHER_API_DEF("cast-192-cbc", cast_cbc, 192, 16, 16,
66 SILC_CIPHER_MODE_CBC),
67 SILC_CIPHER_API_DEF("cast-128-cbc", cast_cbc, 128, 16, 16,
68 SILC_CIPHER_MODE_CBC),
70 SILC_CIPHER_API_DEF("none", none, 0, 0, 0, 0),
71 #endif /* SILC_DEBUG */
72 { NULL, NULL, 0, 0, 0, 0 }
75 /* Register a new cipher into SILC. This is used at the initialization of
76 the SILC. This function allocates a new object for the cipher to be
77 registered. Therefore, if memory has been allocated for the object sent
78 as argument it has to be free'd after this function returns succesfully. */
80 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
83 SilcCipherObject *new;
85 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
87 /* Check if exists already */
88 if (silc_cipher_list) {
89 SilcCipherObject *entry;
90 silc_dlist_start(silc_cipher_list);
91 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
92 if (!strcmp(entry->name, cipher->name))
97 new = silc_calloc(1, sizeof(*new));
98 new->name = strdup(cipher->name);
99 new->key_len = cipher->key_len;
100 new->block_len = cipher->block_len;
101 new->iv_len = cipher->iv_len;
102 new->set_key = cipher->set_key;
103 new->encrypt = cipher->encrypt;
104 new->decrypt = cipher->decrypt;
105 new->context_len = cipher->context_len;
106 new->mode = cipher->mode;
109 if (silc_cipher_list == NULL)
110 silc_cipher_list = silc_dlist_init();
111 silc_dlist_add(silc_cipher_list, new);
113 #endif /* SILC_SYMBIAN */
117 /* Unregister a cipher from the SILC. */
119 SilcBool 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_SYMBIAN */
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 SilcBool 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_SYMBIAN */
165 SilcBool 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_SYMBIAN */
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 SilcBool 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_SYMBIAN */
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 SilcBool 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_SYMBIAN */
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_SYMBIAN */
304 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
305 unsigned char *dst, SilcUInt32 len,
308 return cipher->cipher->encrypt(cipher->context, src, dst, len,
309 iv ? iv : cipher->iv);
314 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
315 unsigned char *dst, SilcUInt32 len,
318 return cipher->cipher->decrypt(cipher->context, src, dst, len,
319 iv ? iv : cipher->iv);
322 /* Sets the key for the cipher */
324 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
325 SilcUInt32 keylen, SilcBool encryption)
327 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
330 /* Sets the IV (initial vector) for the cipher. */
332 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
334 memcpy(&cipher->iv, iv, cipher->cipher->iv_len);
337 /* Returns the IV (initial vector) of the cipher. */
339 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
344 /* Returns the key length of the cipher. */
346 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
348 return cipher->cipher->key_len;
351 /* Returns the block size of the cipher. */
353 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
355 return cipher->cipher->block_len;
358 /* Returns the IV length of the cipher. */
360 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
362 return cipher->cipher->iv_len;
365 /* Returns the name of the cipher */
367 const char *silc_cipher_get_name(SilcCipher cipher)
369 return (const char *)cipher->cipher->name;
372 /* Returns cipher mode */
374 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
376 return cipher->cipher->mode;