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 */
24 /* Dynamically registered list of ciphers. */
25 SilcDList silc_cipher_list = NULL;
26 #endif /* SILC_SYMBIAN */
28 /* Macro to define cipher to cipher list */
29 #define SILC_CDEF(name, alg_name, cipher, keylen, blocklen, ivlen, mode)\
30 { name, alg_name, silc_##cipher##_set_key, silc_##cipher##_set_iv, \
31 silc_##cipher##_encrypt, silc_##cipher##_decrypt, \
32 silc_##cipher##_init, silc_##cipher##_uninit, keylen, blocklen, ivlen, mode }
34 /* Static list of ciphers for silc_cipher_register_default(). */
35 const SilcCipherObject silc_default_ciphers[] =
37 SILC_CDEF("aes-256-ctr", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_CTR),
38 SILC_CDEF("aes-192-ctr", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_CTR),
39 SILC_CDEF("aes-128-ctr", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_CTR),
40 SILC_CDEF("aes-256-cbc", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_CBC),
41 SILC_CDEF("aes-192-cbc", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_CBC),
42 SILC_CDEF("aes-128-cbc", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_CBC),
43 SILC_CDEF("aes-256-cfb", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_CFB),
44 SILC_CDEF("aes-192-cfb", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_CFB),
45 SILC_CDEF("aes-128-cfb", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_CFB),
46 SILC_CDEF("aes-256-ecb", "aes", aes, 256, 16, 16, SILC_CIPHER_MODE_ECB),
47 SILC_CDEF("aes-192-ecb", "aes", aes, 192, 16, 16, SILC_CIPHER_MODE_ECB),
48 SILC_CDEF("aes-128-ecb", "aes", aes, 128, 16, 16, SILC_CIPHER_MODE_ECB),
49 SILC_CDEF("twofish-256-ctr", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_CTR),
50 SILC_CDEF("twofish-192-ctr", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_CTR),
51 SILC_CDEF("twofish-128-ctr", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_CTR),
52 SILC_CDEF("twofish-256-cbc", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_CBC),
53 SILC_CDEF("twofish-192-cbc", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_CBC),
54 SILC_CDEF("twofish-128-cbc", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_CBC),
55 SILC_CDEF("twofish-256-cfb", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_CFB),
56 SILC_CDEF("twofish-192-cfb", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_CFB),
57 SILC_CDEF("twofish-128-cfb", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_CFB),
58 SILC_CDEF("twofish-256-ecb", "twofish", twofish, 256, 16, 16, SILC_CIPHER_MODE_ECB),
59 SILC_CDEF("twofish-192-ecb", "twofish", twofish, 192, 16, 16, SILC_CIPHER_MODE_ECB),
60 SILC_CDEF("twofish-128-ecb", "twofish", twofish, 128, 16, 16, SILC_CIPHER_MODE_ECB),
61 SILC_CDEF("cast5-128-ctr", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_CTR),
62 SILC_CDEF("cast5-128-cbc", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_CBC),
63 SILC_CDEF("cast5-128-cfb", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_CFB),
64 SILC_CDEF("cast5-128-ecb", "cast5", cast5, 128, 8, 8, SILC_CIPHER_MODE_ECB),
65 SILC_CDEF("des-56-ctr", "des", des, 56, 8, 8, SILC_CIPHER_MODE_CTR),
66 SILC_CDEF("des-56-cbc", "des", des, 56, 8, 8, SILC_CIPHER_MODE_CBC),
67 SILC_CDEF("des-56-cfb", "des", des, 56, 8, 8, SILC_CIPHER_MODE_CFB),
68 SILC_CDEF("des-56-ecb", "des", des, 56, 8, 8, SILC_CIPHER_MODE_ECB),
69 SILC_CDEF("3des-168-ctr", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_CTR),
70 SILC_CDEF("3des-168-cbc", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_CBC),
71 SILC_CDEF("3des-168-cfb", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_CFB),
72 SILC_CDEF("3des-168-ecb", "3des", 3des, 168, 8, 8, SILC_CIPHER_MODE_ECB),
74 SILC_CDEF("none", "none", none, 0, 0, 0, 0),
75 #endif /* SILC_DEBUG */
76 { NULL, NULL, NULL, 0, 0, 0, 0 }
79 /* Register new cipher */
81 SilcBool silc_cipher_register(const SilcCipherObject *cipher)
84 SilcCipherObject *new;
86 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
88 /* Check if exists already */
89 if (silc_cipher_list) {
90 SilcCipherObject *entry;
91 silc_dlist_start(silc_cipher_list);
92 while ((entry = silc_dlist_get(silc_cipher_list))) {
93 if (!strcmp(entry->name, cipher->name))
98 new = silc_calloc(1, sizeof(*new));
101 new->name = strdup(cipher->name);
106 new->key_len = cipher->key_len;
107 new->block_len = cipher->block_len;
108 new->iv_len = cipher->iv_len;
109 new->set_key = cipher->set_key;
110 new->set_iv = cipher->set_iv;
111 new->encrypt = cipher->encrypt;
112 new->decrypt = cipher->decrypt;
113 new->init = cipher->init;
114 new->uninit = cipher->uninit;
115 new->mode = cipher->mode;
118 if (silc_cipher_list == NULL)
119 silc_cipher_list = silc_dlist_init();
120 silc_dlist_add(silc_cipher_list, new);
122 #endif /* SILC_SYMBIAN */
126 /* Unregister a cipher */
128 SilcBool silc_cipher_unregister(SilcCipherObject *cipher)
131 SilcCipherObject *entry;
133 SILC_LOG_DEBUG(("Unregistering cipher"));
135 if (!silc_cipher_list)
138 silc_dlist_start(silc_cipher_list);
139 while ((entry = silc_dlist_get(silc_cipher_list))) {
140 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
141 silc_dlist_del(silc_cipher_list, entry);
142 silc_free(entry->name);
145 if (silc_dlist_count(silc_cipher_list) == 0) {
146 silc_dlist_uninit(silc_cipher_list);
147 silc_cipher_list = NULL;
154 #endif /* SILC_SYMBIAN */
158 /* Register default ciphers */
160 SilcBool silc_cipher_register_default(void)
162 /* We use builtin ciphers */
166 /* Unregister all ciphers */
168 SilcBool silc_cipher_unregister_all(void)
171 SilcCipherObject *entry;
173 if (!silc_cipher_list)
176 silc_dlist_start(silc_cipher_list);
177 while ((entry = silc_dlist_get(silc_cipher_list))) {
178 silc_cipher_unregister(entry);
179 if (!silc_cipher_list)
182 #endif /* SILC_SYMBIAN */
186 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
187 on error. The allocated cipher is returned in new_cipher argument. The
188 caller must set the key to the cipher after this function has returned
189 by calling the ciphers set_key function. */
191 SilcBool silc_cipher_alloc(const char *name, SilcCipher *new_cipher)
193 SilcCipherObject *entry = NULL;
196 SILC_LOG_DEBUG(("Allocating new cipher object"));
199 /* First check registered list of ciphers */
200 if (silc_cipher_list) {
201 silc_dlist_start(silc_cipher_list);
202 while ((entry = silc_dlist_get(silc_cipher_list))) {
203 if (!strcmp(entry->name, name))
207 #endif /* SILC_SYMBIAN */
210 /* Check builtin list of ciphers */
211 for (i = 0; silc_default_ciphers[i].name; i++) {
212 if (!strcmp(silc_default_ciphers[i].name, name)) {
213 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
220 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
223 (*new_cipher)->cipher = entry;
224 (*new_cipher)->context = entry->init(entry);
225 if (!(*new_cipher)->context) {
226 silc_free(*new_cipher);
236 /* Allocate cipher */
238 SilcBool silc_cipher_alloc_full(const char *alg_name, SilcUInt32 key_len,
239 SilcCipherMode mode, SilcCipher *new_cipher)
242 const char *mode_name;
245 case SILC_CIPHER_MODE_ECB:
248 case SILC_CIPHER_MODE_CBC:
251 case SILC_CIPHER_MODE_CTR:
254 case SILC_CIPHER_MODE_CFB:
257 case SILC_CIPHER_MODE_OFB:
265 silc_snprintf(name, sizeof(name), "%s-%d-%s", alg_name, key_len, mode_name);
267 return silc_cipher_alloc(name, new_cipher);
270 /* Free's the given cipher. */
272 void silc_cipher_free(SilcCipher cipher)
275 cipher->cipher->uninit(cipher->cipher, cipher->context);
276 memset(cipher, 0, sizeof(*cipher));
281 /* Returns TRUE if cipher `name' is supported. */
283 SilcBool silc_cipher_is_supported(const char *name)
285 SilcCipherObject *entry;
289 /* First check registered list of ciphers */
290 if (silc_cipher_list) {
291 silc_dlist_start(silc_cipher_list);
292 while ((entry = silc_dlist_get(silc_cipher_list))) {
293 if (!strcmp(entry->name, name))
297 #endif /* SILC_SYMBIAN */
299 /* Check builtin list of ciphers */
300 for (i = 0; silc_default_ciphers[i].name; i++)
301 if (!strcmp(silc_default_ciphers[i].name, name))
307 /* Returns comma separated list of supported ciphers. */
309 char *silc_cipher_get_supported(SilcBool only_registered)
311 SilcCipherObject *entry, *entry2;
316 if (silc_cipher_list) {
317 silc_dlist_start(silc_cipher_list);
318 while ((entry = silc_dlist_get(silc_cipher_list))) {
319 len += strlen(entry->name);
320 list = silc_realloc(list, len + 1);
322 memcpy(list + (len - strlen(entry->name)),
323 entry->name, strlen(entry->name));
324 memcpy(list + len, ",", 1);
328 #endif /* SILC_SYMBIAN */
330 if (!only_registered || !silc_cipher_list) {
331 for (i = 0; silc_default_ciphers[i].name; i++) {
332 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
334 if (silc_cipher_list) {
335 silc_dlist_start(silc_cipher_list);
336 while ((entry2 = silc_dlist_get(silc_cipher_list))) {
337 if (!strcmp(entry2->name, entry->name))
344 len += strlen(entry->name);
345 list = silc_realloc(list, len + 1);
347 memcpy(list + (len - strlen(entry->name)),
348 entry->name, strlen(entry->name));
349 memcpy(list + len, ",", 1);
361 SilcBool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
362 unsigned char *dst, SilcUInt32 len,
365 return cipher->cipher->encrypt(cipher, cipher->cipher,
366 cipher->context, src, dst, len,
367 iv ? iv : cipher->iv);
372 SilcBool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
373 unsigned char *dst, SilcUInt32 len,
376 return cipher->cipher->decrypt(cipher, cipher->cipher,
377 cipher->context, src, dst, len,
378 iv ? iv : cipher->iv);
381 /* Sets the key for the cipher */
383 SilcBool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
384 SilcUInt32 keylen, SilcBool encryption)
386 return cipher->cipher->set_key(cipher, cipher->cipher, cipher->context,
387 (void *)key, keylen, encryption);
390 /* Sets the IV (initial vector) for the cipher. */
392 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
395 memmove(cipher->iv, iv, cipher->cipher->iv_len);
396 cipher->cipher->set_iv(cipher, cipher->cipher, cipher->context, cipher->iv);
399 /* Returns the IV (initial vector) of the cipher. */
401 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
406 /* Returns the key length of the cipher. */
408 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
410 return cipher->cipher->key_len;
413 /* Returns the block size of the cipher. */
415 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
417 return cipher->cipher->block_len;
420 /* Returns the IV length of the cipher. */
422 SilcUInt32 silc_cipher_get_iv_len(SilcCipher cipher)
424 return cipher->cipher->iv_len;
427 /* Returns the name of the cipher */
429 const char *silc_cipher_get_name(SilcCipher cipher)
431 return (const char *)cipher->cipher->name;
434 /* Returns the algorithm name of the cipher */
436 const char *silc_cipher_get_alg_name(SilcCipher cipher)
438 return (const char *)cipher->cipher->alg_name;
441 /* Returns cipher mode */
443 SilcCipherMode silc_cipher_get_mode(SilcCipher cipher)
445 return cipher->cipher->mode;