5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 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##_set_iv, \
39 silc_##cipher##_encrypt, silc_##cipher##_decrypt, \
40 silc_##cipher##_context_len, 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));
100 new->name = strdup(cipher->name);
105 new->key_len = cipher->key_len;
106 new->block_len = cipher->block_len;
107 new->iv_len = cipher->iv_len;
108 new->set_key = cipher->set_key;
109 new->set_iv = cipher->set_iv;
110 new->encrypt = cipher->encrypt;
111 new->decrypt = cipher->decrypt;
112 new->context_len = cipher->context_len;
113 new->mode = cipher->mode;
116 if (silc_cipher_list == NULL)
117 silc_cipher_list = silc_dlist_init();
118 silc_dlist_add(silc_cipher_list, new);
120 #endif /* SILC_SYMBIAN */
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_SYMBIAN */
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_SYMBIAN */
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_SYMBIAN */
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_SYMBIAN */
223 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
226 (*new_cipher)->cipher = entry;
227 (*new_cipher)->context = silc_calloc(1, entry->context_len());
228 if (!(*new_cipher)->context) {
229 silc_free(*new_cipher);
238 /* Free's the given cipher. */
240 void silc_cipher_free(SilcCipher cipher)
243 silc_free(cipher->context);
248 /* Returns TRUE if cipher `name' is supported. */
250 SilcBool silc_cipher_is_supported(const unsigned char *name)
253 SilcCipherObject *entry;
255 if (silc_cipher_list) {
256 silc_dlist_start(silc_cipher_list);
257 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
258 if (!strcmp(entry->name, name))
265 for (i = 0; silc_default_ciphers[i].name; i++)
266 if (!strcmp(silc_default_ciphers[i].name, name))
269 #endif /* SILC_SYMBIAN */
273 /* Returns comma separated list of supported ciphers. */
275 char *silc_cipher_get_supported(void)
277 SilcCipherObject *entry;
282 if (silc_cipher_list) {
283 silc_dlist_start(silc_cipher_list);
284 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
285 len += strlen(entry->name);
286 list = silc_realloc(list, len + 1);
288 memcpy(list + (len - strlen(entry->name)),
289 entry->name, strlen(entry->name));
290 memcpy(list + len, ",", 1);
297 for (i = 0; silc_default_ciphers[i].name; i++) {
298 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
299 len += strlen(entry->name);
300 list = silc_realloc(list, len + 1);
302 memcpy(list + (len - strlen(entry->name)),
303 entry->name, strlen(entry->name));
304 memcpy(list + len, ",", 1);
308 #endif /* SILC_SYMBIAN */
317 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
318 unsigned char *dst, SilcUInt32 len,
321 return cipher->cipher->encrypt(cipher->context, src, dst, len,
322 iv ? iv : cipher->iv);
327 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
328 unsigned char *dst, SilcUInt32 len,
331 return cipher->cipher->decrypt(cipher->context, src, dst, len,
332 iv ? iv : cipher->iv);
335 /* Sets the key for the cipher */
337 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
338 SilcUInt32 keylen, SilcBool encryption)
340 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
343 /* Sets the IV (initial vector) for the cipher. */
345 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
348 memmove(&cipher->iv, iv, cipher->cipher->iv_len);
349 cipher->cipher->set_iv(cipher->context, iv);
352 /* Returns the IV (initial vector) of the cipher. */
354 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
359 /* Returns the key length of the cipher. */
361 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
363 return cipher->cipher->key_len;
366 /* Returns the block size of the cipher. */
368 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
370 return cipher->cipher->block_len;
373 /* Returns the IV length of the cipher. */
375 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
377 return cipher->cipher->iv_len;
380 /* Returns the name of the cipher */
382 const char *silc_cipher_get_name(SilcCipher cipher)
384 return (const char *)cipher->cipher->name;
387 /* Returns cipher mode */
389 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
391 return cipher->cipher->mode;