5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2008 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.
20 #include "silccrypto.h"
21 #include "ciphers.h" /* Includes cipher definitions */
23 /* The SilcCipher context */
24 struct SilcCipherStruct {
25 SilcCipherObject *cipher;
27 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
31 /* Dynamically registered list of ciphers. */
32 SilcDList silc_cipher_list = NULL;
33 #endif /* SILC_SYMBIAN */
35 /* Macro to define cipher to cipher list */
36 #define SILC_CDEF(name, cipher, keylen, blocklen, ivlen, mode) \
37 { name, silc_##cipher##_set_key, silc_##cipher##_set_iv, \
38 silc_##cipher##_encrypt, silc_##cipher##_decrypt, \
39 silc_##cipher##_context_len, keylen, blocklen, ivlen, mode }
41 /* Static list of ciphers for silc_cipher_register_default(). */
42 const SilcCipherObject silc_default_ciphers[] =
44 SILC_CDEF("aes-256-ctr", aes, 256, 16, 16, SILC_CIPHER_MODE_CTR),
45 SILC_CDEF("aes-192-ctr", aes, 192, 16, 16, SILC_CIPHER_MODE_CTR),
46 SILC_CDEF("aes-128-ctr", aes, 128, 16, 16, SILC_CIPHER_MODE_CTR),
47 SILC_CDEF("aes-256-cbc", aes, 256, 16, 16, SILC_CIPHER_MODE_CBC),
48 SILC_CDEF("aes-192-cbc", aes, 192, 16, 16, SILC_CIPHER_MODE_CBC),
49 SILC_CDEF("aes-128-cbc", aes, 128, 16, 16, SILC_CIPHER_MODE_CBC),
50 SILC_CDEF("aes-256-cfb", aes, 256, 16, 16, SILC_CIPHER_MODE_CFB),
51 SILC_CDEF("aes-192-cfb", aes, 192, 16, 16, SILC_CIPHER_MODE_CFB),
52 SILC_CDEF("aes-128-cfb", aes, 128, 16, 16, SILC_CIPHER_MODE_CFB),
53 SILC_CDEF("twofish-256-ctr", twofish, 256, 16, 16, SILC_CIPHER_MODE_CTR),
54 SILC_CDEF("twofish-192-ctr", twofish, 192, 16, 16, SILC_CIPHER_MODE_CTR),
55 SILC_CDEF("twofish-128-ctr", twofish, 128, 16, 16, SILC_CIPHER_MODE_CTR),
56 SILC_CDEF("twofish-256-cbc", twofish, 256, 16, 16, SILC_CIPHER_MODE_CBC),
57 SILC_CDEF("twofish-192-cbc", twofish, 192, 16, 16, SILC_CIPHER_MODE_CBC),
58 SILC_CDEF("twofish-128-cbc", twofish, 128, 16, 16, SILC_CIPHER_MODE_CBC),
59 SILC_CDEF("twofish-256-cfb", twofish, 256, 16, 16, SILC_CIPHER_MODE_CFB),
60 SILC_CDEF("twofish-192-cfb", twofish, 192, 16, 16, SILC_CIPHER_MODE_CFB),
61 SILC_CDEF("twofish-128-cfb", twofish, 128, 16, 16, SILC_CIPHER_MODE_CFB),
62 SILC_CDEF("cast5-128-ctr", cast5, 128, 8, 8, SILC_CIPHER_MODE_CTR),
63 SILC_CDEF("cast5-128-cbc", cast5, 128, 8, 8, SILC_CIPHER_MODE_CBC),
64 SILC_CDEF("cast5-128-cfb", cast5, 128, 8, 8, SILC_CIPHER_MODE_CFB),
65 SILC_CDEF("des-56-ctr", des, 56, 8, 8, SILC_CIPHER_MODE_CTR),
66 SILC_CDEF("des-56-cbc", des, 56, 8, 8, SILC_CIPHER_MODE_CBC),
67 SILC_CDEF("des-56-cfb", des, 56, 8, 8, SILC_CIPHER_MODE_CFB),
68 SILC_CDEF("3des-168-ctr", 3des, 168, 8, 8, SILC_CIPHER_MODE_CTR),
69 SILC_CDEF("3des-168-cbc", 3des, 168, 8, 8, SILC_CIPHER_MODE_CBC),
70 SILC_CDEF("3des-168-cfb", 3des, 168, 8, 8, SILC_CIPHER_MODE_CFB),
72 SILC_CDEF("none", none, 0, 0, 0, 0),
73 #endif /* SILC_DEBUG */
74 { NULL, NULL, 0, 0, 0, 0 }
77 /* Register new cipher */
79 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
82 SilcCipherObject *new;
84 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
86 /* Check if exists already */
87 if (silc_cipher_list) {
88 SilcCipherObject *entry;
89 silc_dlist_start(silc_cipher_list);
90 while ((entry = silc_dlist_get(silc_cipher_list))) {
91 if (!strcmp(entry->name, cipher->name))
96 new = silc_calloc(1, sizeof(*new));
99 new->name = strdup(cipher->name);
104 new->key_len = cipher->key_len;
105 new->block_len = cipher->block_len;
106 new->iv_len = cipher->iv_len;
107 new->set_key = cipher->set_key;
108 new->set_iv = cipher->set_iv;
109 new->encrypt = cipher->encrypt;
110 new->decrypt = cipher->decrypt;
111 new->context_len = cipher->context_len;
112 new->mode = cipher->mode;
115 if (silc_cipher_list == NULL)
116 silc_cipher_list = silc_dlist_init();
117 silc_dlist_add(silc_cipher_list, new);
119 #endif /* SILC_SYMBIAN */
123 /* Unregister a cipher */
125 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
128 SilcCipherObject *entry;
130 SILC_LOG_DEBUG(("Unregistering cipher"));
132 if (!silc_cipher_list)
135 silc_dlist_start(silc_cipher_list);
136 while ((entry = silc_dlist_get(silc_cipher_list))) {
137 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
138 silc_dlist_del(silc_cipher_list, entry);
139 silc_free(entry->name);
142 if (silc_dlist_count(silc_cipher_list) == 0) {
143 silc_dlist_uninit(silc_cipher_list);
144 silc_cipher_list = NULL;
151 #endif /* SILC_SYMBIAN */
155 /* Register default ciphers */
157 SilcBool silc_cipher_register_default(void)
159 /* We use builtin ciphers */
163 /* Unregister all ciphers */
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))) {
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 char *name, SilcCipher *new_cipher)
190 SilcCipherObject *entry = NULL;
193 SILC_LOG_DEBUG(("Allocating new cipher object"));
196 /* First check registered list of ciphers */
197 if (silc_cipher_list) {
198 silc_dlist_start(silc_cipher_list);
199 while ((entry = silc_dlist_get(silc_cipher_list))) {
200 if (!strcmp(entry->name, name))
204 #endif /* SILC_SYMBIAN */
207 /* Check builtin list of ciphers */
208 for (i = 0; silc_default_ciphers[i].name; i++) {
209 if (!strcmp(silc_default_ciphers[i].name, name)) {
210 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
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);
233 /* Free's the given cipher. */
235 void silc_cipher_free(SilcCipher cipher)
238 silc_free(cipher->context);
243 /* Returns TRUE if cipher `name' is supported. */
245 SilcBool silc_cipher_is_supported(const char *name)
247 SilcCipherObject *entry;
251 /* First check registered list of ciphers */
252 if (silc_cipher_list) {
253 silc_dlist_start(silc_cipher_list);
254 while ((entry = silc_dlist_get(silc_cipher_list))) {
255 if (!strcmp(entry->name, name))
259 #endif /* SILC_SYMBIAN */
261 /* Check builtin list of ciphers */
262 for (i = 0; silc_default_ciphers[i].name; i++)
263 if (!strcmp(silc_default_ciphers[i].name, name))
269 /* Returns comma separated list of supported ciphers. */
271 char *silc_cipher_get_supported(SilcBool only_registered)
273 SilcCipherObject *entry, *entry2;
278 if (silc_cipher_list) {
279 silc_dlist_start(silc_cipher_list);
280 while ((entry = silc_dlist_get(silc_cipher_list))) {
281 len += strlen(entry->name);
282 list = silc_realloc(list, len + 1);
284 memcpy(list + (len - strlen(entry->name)),
285 entry->name, strlen(entry->name));
286 memcpy(list + len, ",", 1);
290 #endif /* SILC_SYMBIAN */
292 if (!only_registered || !silc_cipher_list) {
293 for (i = 0; silc_default_ciphers[i].name; i++) {
294 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
296 if (silc_cipher_list) {
297 silc_dlist_start(silc_cipher_list);
298 while ((entry2 = silc_dlist_get(silc_cipher_list))) {
299 if (!strcmp(entry2->name, entry->name))
306 len += strlen(entry->name);
307 list = silc_realloc(list, len + 1);
309 memcpy(list + (len - strlen(entry->name)),
310 entry->name, strlen(entry->name));
311 memcpy(list + len, ",", 1);
323 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
324 unsigned char *dst, SilcUInt32 len,
327 return cipher->cipher->encrypt(cipher->cipher, cipher->context, src, dst, len,
328 iv ? iv : cipher->iv);
333 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
334 unsigned char *dst, SilcUInt32 len,
337 return cipher->cipher->decrypt(cipher->cipher, cipher->context, src, dst, len,
338 iv ? iv : cipher->iv);
341 /* Sets the key for the cipher */
343 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
344 SilcUInt32 keylen, SilcBool encryption)
346 return cipher->cipher->set_key(cipher->cipher, cipher->context, key, keylen,
350 /* Sets the IV (initial vector) for the cipher. */
352 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
355 memmove(&cipher->iv, iv, cipher->cipher->iv_len);
356 cipher->cipher->set_iv(cipher->cipher, cipher->context, cipher->iv);
359 /* Returns the IV (initial vector) of the cipher. */
361 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
366 /* Returns the key length of the cipher. */
368 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
370 return cipher->cipher->key_len;
373 /* Returns the block size of the cipher. */
375 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
377 return cipher->cipher->block_len;
380 /* Returns the IV length of the cipher. */
382 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
384 return cipher->cipher->iv_len;
387 /* Returns the name of the cipher */
389 const char *silc_cipher_get_name(SilcCipher cipher)
391 return (const char *)cipher->cipher->name;
394 /* Returns cipher mode */
396 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
398 return cipher->cipher->mode;