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));
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->set_iv = cipher->set_iv;
104 new->encrypt = cipher->encrypt;
105 new->decrypt = cipher->decrypt;
106 new->context_len = cipher->context_len;
107 new->mode = cipher->mode;
110 if (silc_cipher_list == NULL)
111 silc_cipher_list = silc_dlist_init();
112 silc_dlist_add(silc_cipher_list, new);
114 #endif /* SILC_SYMBIAN */
118 /* Unregister a cipher from the SILC. */
120 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
123 SilcCipherObject *entry;
125 SILC_LOG_DEBUG(("Unregistering cipher"));
127 if (!silc_cipher_list)
130 silc_dlist_start(silc_cipher_list);
131 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
132 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
133 silc_dlist_del(silc_cipher_list, entry);
134 silc_free(entry->name);
137 if (silc_dlist_count(silc_cipher_list) == 0) {
138 silc_dlist_uninit(silc_cipher_list);
139 silc_cipher_list = NULL;
146 #endif /* SILC_SYMBIAN */
150 /* Function that registers all the default ciphers (all builtin ciphers).
151 The application may use this to register the default ciphers if specific
152 ciphers in any specific order is not wanted. */
154 SilcBool silc_cipher_register_default(void)
159 for (i = 0; silc_default_ciphers[i].name; i++)
160 silc_cipher_register(&(silc_default_ciphers[i]));
162 #endif /* SILC_SYMBIAN */
166 SilcBool silc_cipher_unregister_all(void)
169 SilcCipherObject *entry;
171 if (!silc_cipher_list)
174 silc_dlist_start(silc_cipher_list);
175 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
176 silc_cipher_unregister(entry);
177 if (!silc_cipher_list)
180 #endif /* SILC_SYMBIAN */
184 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
185 on error. The allocated cipher is returned in new_cipher argument. The
186 caller must set the key to the cipher after this function has returned
187 by calling the ciphers set_key function. */
189 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
191 SilcCipherObject *entry = NULL;
193 SILC_LOG_DEBUG(("Allocating new cipher object"));
196 if (silc_cipher_list) {
197 silc_dlist_start(silc_cipher_list);
198 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
199 if (!strcmp(entry->name, name))
205 /* On EPOC which don't have globals we check our constant cipher list. */
207 for (i = 0; silc_default_ciphers[i].name; i++) {
208 if (!strcmp(silc_default_ciphers[i].name, name)) {
209 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
214 #endif /* SILC_SYMBIAN */
217 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
218 (*new_cipher)->cipher = entry;
219 (*new_cipher)->context = silc_calloc(1, entry->context_len());
226 /* Free's the given cipher. */
228 void silc_cipher_free(SilcCipher cipher)
231 silc_free(cipher->context);
236 /* Returns TRUE if cipher `name' is supported. */
238 SilcBool silc_cipher_is_supported(const unsigned char *name)
241 SilcCipherObject *entry;
243 if (silc_cipher_list) {
244 silc_dlist_start(silc_cipher_list);
245 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
246 if (!strcmp(entry->name, name))
253 for (i = 0; silc_default_ciphers[i].name; i++)
254 if (!strcmp(silc_default_ciphers[i].name, name))
257 #endif /* SILC_SYMBIAN */
261 /* Returns comma separated list of supported ciphers. */
263 char *silc_cipher_get_supported(void)
265 SilcCipherObject *entry;
270 if (silc_cipher_list) {
271 silc_dlist_start(silc_cipher_list);
272 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
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);
285 for (i = 0; silc_default_ciphers[i].name; i++) {
286 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
287 len += strlen(entry->name);
288 list = silc_realloc(list, len + 1);
290 memcpy(list + (len - strlen(entry->name)),
291 entry->name, strlen(entry->name));
292 memcpy(list + len, ",", 1);
296 #endif /* SILC_SYMBIAN */
305 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
306 unsigned char *dst, SilcUInt32 len,
309 return cipher->cipher->encrypt(cipher->context, src, dst, len,
310 iv ? iv : cipher->iv);
315 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
316 unsigned char *dst, SilcUInt32 len,
319 return cipher->cipher->decrypt(cipher->context, src, dst, len,
320 iv ? iv : cipher->iv);
323 /* Sets the key for the cipher */
325 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
326 SilcUInt32 keylen, SilcBool encryption)
328 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
331 /* Sets the IV (initial vector) for the cipher. */
333 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
336 memmove(&cipher->iv, iv, cipher->cipher->iv_len);
337 cipher->cipher->set_iv(cipher->context, iv);
340 /* Returns the IV (initial vector) of the cipher. */
342 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
347 /* Returns the key length of the cipher. */
349 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
351 return cipher->cipher->key_len;
354 /* Returns the block size of the cipher. */
356 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
358 return cipher->cipher->block_len;
361 /* Returns the IV length of the cipher. */
363 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
365 return cipher->cipher->iv_len;
368 /* Returns the name of the cipher */
370 const char *silc_cipher_get_name(SilcCipher cipher)
372 return (const char *)cipher->cipher->name;
375 /* Returns cipher mode */
377 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
379 return cipher->cipher->mode;