5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
23 #include "ciphers.h" /* Includes cipher definitions */
26 /* Dynamically registered list of ciphers. */
27 SilcDList silc_cipher_list = NULL;
28 #endif /* SILC_EPOC */
30 /* Static list of ciphers for silc_cipher_register_default(). */
31 const SilcCipherObject silc_default_ciphers[] =
33 { "aes-256-cbc", 16, 256, silc_aes_set_key,
34 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
35 silc_aes_decrypt_cbc, silc_aes_context_len },
36 { "aes-192-cbc", 16, 192, silc_aes_set_key,
37 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
38 silc_aes_decrypt_cbc, silc_aes_context_len },
39 { "aes-128-cbc", 16, 128, silc_aes_set_key,
40 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
41 silc_aes_decrypt_cbc, silc_aes_context_len },
42 { "twofish-256-cbc", 16, 256, silc_twofish_set_key,
43 silc_twofish_set_key_with_string,
44 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
45 silc_twofish_context_len },
46 { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
47 silc_twofish_set_key_with_string,
48 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
49 silc_twofish_context_len },
50 { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
51 silc_twofish_set_key_with_string,
52 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
53 silc_twofish_context_len },
54 { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
55 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
56 silc_rc6_context_len },
57 { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
58 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
59 silc_rc6_context_len },
60 { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
61 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
62 silc_rc6_context_len },
63 { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
64 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
65 silc_mars_context_len },
66 { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
67 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
68 silc_mars_context_len },
69 { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
70 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
71 silc_mars_context_len },
72 { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
73 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
74 silc_cast_context_len },
75 { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
76 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
77 silc_cast_context_len },
78 { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
79 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
80 silc_cast_context_len },
81 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
82 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
83 silc_none_context_len },
85 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
88 /* Register a new cipher into SILC. This is used at the initialization of
89 the SILC. This function allocates a new object for the cipher to be
90 registered. Therefore, if memory has been allocated for the object sent
91 as argument it has to be free'd after this function returns succesfully. */
93 bool silc_cipher_register(const SilcCipherObject *cipher)
96 SilcCipherObject *new;
98 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
100 /* Check if exists already */
101 if (silc_cipher_list) {
102 SilcCipherObject *entry;
103 silc_dlist_start(silc_cipher_list);
104 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
105 if (!strcmp(entry->name, cipher->name))
110 new = silc_calloc(1, sizeof(*new));
111 new->name = strdup(cipher->name);
112 new->block_len = cipher->block_len;
113 new->key_len = cipher->key_len;
114 new->set_key = cipher->set_key;
115 new->set_key_with_string = cipher->set_key_with_string;
116 new->encrypt = cipher->encrypt;
117 new->decrypt = cipher->decrypt;
118 new->context_len = cipher->context_len;
121 if (silc_cipher_list == NULL)
122 silc_cipher_list = silc_dlist_init();
123 silc_dlist_add(silc_cipher_list, new);
125 #endif /* SILC_EPOC */
129 /* Unregister a cipher from the SILC. */
131 bool silc_cipher_unregister(SilcCipherObject *cipher)
134 SilcCipherObject *entry;
136 SILC_LOG_DEBUG(("Unregistering cipher"));
138 if (!silc_cipher_list)
141 silc_dlist_start(silc_cipher_list);
142 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
143 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
144 silc_dlist_del(silc_cipher_list, entry);
145 silc_free(entry->name);
148 if (silc_dlist_count(silc_cipher_list) == 0) {
149 silc_dlist_uninit(silc_cipher_list);
150 silc_cipher_list = NULL;
157 #endif /* SILC_EPOC */
161 /* Function that registers all the default ciphers (all builtin ciphers).
162 The application may use this to register the default ciphers if specific
163 ciphers in any specific order is not wanted. */
165 bool silc_cipher_register_default(void)
170 for (i = 0; silc_default_ciphers[i].name; i++)
171 silc_cipher_register(&(silc_default_ciphers[i]));
173 #endif /* SILC_EPOC */
177 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
178 on error. The allocated cipher is returned in new_cipher argument. The
179 caller must set the key to the cipher after this function has returned
180 by calling the ciphers set_key function. */
182 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
184 SilcCipherObject *entry = NULL;
186 SILC_LOG_DEBUG(("Allocating new cipher object"));
189 if (silc_cipher_list) {
190 silc_dlist_start(silc_cipher_list);
191 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
192 if (!strcmp(entry->name, name))
198 /* On EPOC which don't have globals we check our constant cipher list. */
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]);
207 #endif /* SILC_EPOC */
210 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
211 (*new_cipher)->cipher = entry;
212 (*new_cipher)->context = silc_calloc(1, entry->context_len());
213 (*new_cipher)->set_iv = silc_cipher_set_iv;
214 (*new_cipher)->get_iv = silc_cipher_get_iv;
215 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
216 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
223 /* Free's the given cipher. */
225 void silc_cipher_free(SilcCipher cipher)
228 silc_free(cipher->context);
233 /* Returns TRUE if cipher `name' is supported. */
235 bool silc_cipher_is_supported(const unsigned char *name)
238 SilcCipherObject *entry;
240 if (silc_cipher_list) {
241 silc_dlist_start(silc_cipher_list);
242 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
243 if (!strcmp(entry->name, name))
250 for (i = 0; silc_default_ciphers[i].name; i++)
251 if (!strcmp(silc_default_ciphers[i].name, name))
254 #endif /* SILC_EPOC */
258 /* Returns comma separated list of supported ciphers. */
260 char *silc_cipher_get_supported(void)
262 SilcCipherObject *entry;
267 if (silc_cipher_list) {
268 silc_dlist_start(silc_cipher_list);
269 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
270 len += strlen(entry->name);
271 list = silc_realloc(list, len + 1);
273 memcpy(list + (len - strlen(entry->name)),
274 entry->name, strlen(entry->name));
275 memcpy(list + len, ",", 1);
282 for (i = 0; silc_default_ciphers[i].name; i++) {
283 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
284 len += strlen(entry->name);
285 list = silc_realloc(list, len + 1);
287 memcpy(list + (len - strlen(entry->name)),
288 entry->name, strlen(entry->name));
289 memcpy(list + len, ",", 1);
293 #endif /* SILC_EPOC */
302 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
303 unsigned char *dst, SilcUInt32 len,
306 return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
311 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
312 unsigned char *dst, SilcUInt32 len,
315 return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
318 /* Sets the key for the cipher */
320 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
323 return cipher->cipher->set_key(cipher->context, key, keylen);
326 /* Sets the IV (initial vector) for the cipher. */
328 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
330 memset(&cipher->iv, 0, sizeof(cipher->iv));
331 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
334 /* Returns the IV (initial vector) of the cipher. The IV is returned
337 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
339 memcpy(iv, &cipher->iv, cipher->cipher->block_len);
342 /* Returns the key length of the cipher. */
344 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
346 return cipher->cipher->key_len;
349 /* Returns the block size of the cipher. */
351 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
353 return cipher->cipher->block_len;