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 new cipher */
71 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
74 SilcCipherObject *new;
76 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
78 /* Check if exists already */
79 if (silc_cipher_list) {
80 SilcCipherObject *entry;
81 silc_dlist_start(silc_cipher_list);
82 while ((entry = silc_dlist_get(silc_cipher_list))) {
83 if (!strcmp(entry->name, cipher->name))
88 new = silc_calloc(1, sizeof(*new));
91 new->name = strdup(cipher->name);
96 new->key_len = cipher->key_len;
97 new->block_len = cipher->block_len;
98 new->iv_len = cipher->iv_len;
99 new->set_key = cipher->set_key;
100 new->set_iv = cipher->set_iv;
101 new->encrypt = cipher->encrypt;
102 new->decrypt = cipher->decrypt;
103 new->context_len = cipher->context_len;
104 new->mode = cipher->mode;
107 if (silc_cipher_list == NULL)
108 silc_cipher_list = silc_dlist_init();
109 silc_dlist_add(silc_cipher_list, new);
111 #endif /* SILC_SYMBIAN */
115 /* Unregister a cipher */
117 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
120 SilcCipherObject *entry;
122 SILC_LOG_DEBUG(("Unregistering cipher"));
124 if (!silc_cipher_list)
127 silc_dlist_start(silc_cipher_list);
128 while ((entry = silc_dlist_get(silc_cipher_list))) {
129 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
130 silc_dlist_del(silc_cipher_list, entry);
131 silc_free(entry->name);
134 if (silc_dlist_count(silc_cipher_list) == 0) {
135 silc_dlist_uninit(silc_cipher_list);
136 silc_cipher_list = NULL;
143 #endif /* SILC_SYMBIAN */
147 /* Register default ciphers */
149 SilcBool silc_cipher_register_default(void)
151 /* We use builtin ciphers */
155 /* Unregister all ciphers */
157 SilcBool silc_cipher_unregister_all(void)
160 SilcCipherObject *entry;
162 if (!silc_cipher_list)
165 silc_dlist_start(silc_cipher_list);
166 while ((entry = silc_dlist_get(silc_cipher_list))) {
167 silc_cipher_unregister(entry);
168 if (!silc_cipher_list)
171 #endif /* SILC_SYMBIAN */
175 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
176 on error. The allocated cipher is returned in new_cipher argument. The
177 caller must set the key to the cipher after this function has returned
178 by calling the ciphers set_key function. */
180 SilcBool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
182 SilcCipherObject *entry = NULL;
185 SILC_LOG_DEBUG(("Allocating new cipher object"));
188 /* First check registered list of ciphers */
189 if (silc_cipher_list) {
190 silc_dlist_start(silc_cipher_list);
191 while ((entry = silc_dlist_get(silc_cipher_list))) {
192 if (!strcmp(entry->name, name))
196 #endif /* SILC_SYMBIAN */
199 /* Check builtin list of ciphers */
200 for (i = 0; silc_default_ciphers[i].name; i++) {
201 if (!strcmp(silc_default_ciphers[i].name, name)) {
202 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
209 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
212 (*new_cipher)->cipher = entry;
213 (*new_cipher)->context = silc_calloc(1, entry->context_len());
214 if (!(*new_cipher)->context) {
215 silc_free(*new_cipher);
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)
239 SilcCipherObject *entry;
243 /* First check registered list of ciphers */
244 if (silc_cipher_list) {
245 silc_dlist_start(silc_cipher_list);
246 while ((entry = silc_dlist_get(silc_cipher_list))) {
247 if (!strcmp(entry->name, name))
251 #endif /* SILC_SYMBIAN */
253 /* Check builtin list of ciphers */
254 for (i = 0; silc_default_ciphers[i].name; i++)
255 if (!strcmp(silc_default_ciphers[i].name, name))
261 /* Returns comma separated list of supported ciphers. */
263 char *silc_cipher_get_supported(void)
265 SilcCipherObject *entry, *entry2;
270 if (silc_cipher_list) {
271 silc_dlist_start(silc_cipher_list);
272 while ((entry = silc_dlist_get(silc_cipher_list))) {
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_SYMBIAN */
284 for (i = 0; silc_default_ciphers[i].name; i++) {
285 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
287 if (silc_cipher_list) {
288 silc_dlist_start(silc_cipher_list);
289 while ((entry2 = silc_dlist_get(silc_cipher_list))) {
290 if (!strcmp(entry2->name, entry->name))
297 len += strlen(entry->name);
298 list = silc_realloc(list, len + 1);
300 memcpy(list + (len - strlen(entry->name)),
301 entry->name, strlen(entry->name));
302 memcpy(list + len, ",", 1);
313 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
314 unsigned char *dst, SilcUInt32 len,
317 return cipher->cipher->encrypt(cipher->context, src, dst, len,
318 iv ? iv : cipher->iv);
323 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
324 unsigned char *dst, SilcUInt32 len,
327 return cipher->cipher->decrypt(cipher->context, src, dst, len,
328 iv ? iv : cipher->iv);
331 /* Sets the key for the cipher */
333 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
334 SilcUInt32 keylen, SilcBool encryption)
336 return cipher->cipher->set_key(cipher->context, key, keylen, encryption);
339 /* Sets the IV (initial vector) for the cipher. */
341 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
344 memmove(&cipher->iv, iv, cipher->cipher->iv_len);
345 cipher->cipher->set_iv(cipher->context, iv);
348 /* Returns the IV (initial vector) of the cipher. */
350 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
355 /* Returns the key length of the cipher. */
357 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
359 return cipher->cipher->key_len;
362 /* Returns the block size of the cipher. */
364 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
366 return cipher->cipher->block_len;
369 /* Returns the IV length of the cipher. */
371 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
373 return cipher->cipher->iv_len;
376 /* Returns the name of the cipher */
378 const char *silc_cipher_get_name(SilcCipher cipher)
380 return (const char *)cipher->cipher->name;
383 /* Returns cipher mode */
385 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
387 return cipher->cipher->mode;