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),
64 SILC_CIPHER_API_DEF("none", none, 0, 0, 0, 0),
65 #endif /* SILC_DEBUG */
66 { NULL, NULL, 0, 0, 0, 0 }
69 /* Register a new cipher into SILC. This is used at the initialization of
70 the SILC. This function allocates a new object for the cipher to be
71 registered. Therefore, if memory has been allocated for the object sent
72 as argument it has to be free'd after this function returns succesfully. */
74 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
77 SilcCipherObject *new;
79 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
81 /* Check if exists already */
82 if (silc_cipher_list) {
83 SilcCipherObject *entry;
84 silc_dlist_start(silc_cipher_list);
85 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
86 if (!strcmp(entry->name, cipher->name))
91 new = silc_calloc(1, sizeof(*new));
94 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));
220 (*new_cipher)->cipher = entry;
221 (*new_cipher)->context = silc_calloc(1, entry->context_len());
222 if (!(*new_cipher)->context) {
223 silc_free(*new_cipher);
232 /* Free's the given cipher. */
234 void silc_cipher_free(SilcCipher cipher)
237 silc_free(cipher->context);
242 /* Returns TRUE if cipher `name' is supported. */
244 SilcBool silc_cipher_is_supported(const unsigned char *name)
247 SilcCipherObject *entry;
249 if (silc_cipher_list) {
250 silc_dlist_start(silc_cipher_list);
251 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
252 if (!strcmp(entry->name, name))
259 for (i = 0; silc_default_ciphers[i].name; i++)
260 if (!strcmp(silc_default_ciphers[i].name, name))
263 #endif /* SILC_SYMBIAN */
267 /* Returns comma separated list of supported ciphers. */
269 char *silc_cipher_get_supported(void)
271 SilcCipherObject *entry;
276 if (silc_cipher_list) {
277 silc_dlist_start(silc_cipher_list);
278 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
279 len += strlen(entry->name);
280 list = silc_realloc(list, len + 1);
282 memcpy(list + (len - strlen(entry->name)),
283 entry->name, strlen(entry->name));
284 memcpy(list + len, ",", 1);
291 for (i = 0; silc_default_ciphers[i].name; i++) {
292 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
293 len += strlen(entry->name);
294 list = silc_realloc(list, len + 1);
296 memcpy(list + (len - strlen(entry->name)),
297 entry->name, strlen(entry->name));
298 memcpy(list + len, ",", 1);
302 #endif /* SILC_SYMBIAN */
311 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
312 unsigned char *dst, SilcUInt32 len,
315 return cipher->cipher->encrypt(cipher->context, src, dst, len,
316 iv ? iv : cipher->iv);
321 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
322 unsigned char *dst, SilcUInt32 len,
325 return cipher->cipher->decrypt(cipher->context, src, dst, len,
326 iv ? iv : cipher->iv);
329 /* Sets the key for the cipher */
331 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
332 SilcUInt32 keylen, SilcBool encryption)
334 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
337 /* Sets the IV (initial vector) for the cipher. */
339 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
342 memmove(&cipher->iv, iv, cipher->cipher->iv_len);
343 cipher->cipher->set_iv(cipher->context, iv);
346 /* Returns the IV (initial vector) of the cipher. */
348 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
353 /* Returns the key length of the cipher. */
355 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
357 return cipher->cipher->key_len;
360 /* Returns the block size of the cipher. */
362 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
364 return cipher->cipher->block_len;
367 /* Returns the IV length of the cipher. */
369 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
371 return cipher->cipher->iv_len;
374 /* Returns the name of the cipher */
376 const char *silc_cipher_get_name(SilcCipher cipher)
378 return (const char *)cipher->cipher->name;
381 /* Returns cipher mode */
383 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
385 return cipher->cipher->mode;