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 bool silc_cipher_unregister_all(void)
180 SilcCipherObject *entry;
182 if (!silc_cipher_list)
185 silc_dlist_start(silc_cipher_list);
186 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
187 silc_cipher_unregister(entry);
188 if (!silc_cipher_list)
191 #endif /* SILC_EPOC */
195 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
196 on error. The allocated cipher is returned in new_cipher argument. The
197 caller must set the key to the cipher after this function has returned
198 by calling the ciphers set_key function. */
200 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
202 SilcCipherObject *entry = NULL;
204 SILC_LOG_DEBUG(("Allocating new cipher object"));
207 if (silc_cipher_list) {
208 silc_dlist_start(silc_cipher_list);
209 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
210 if (!strcmp(entry->name, name))
216 /* On EPOC which don't have globals we check our constant cipher list. */
218 for (i = 0; silc_default_ciphers[i].name; i++) {
219 if (!strcmp(silc_default_ciphers[i].name, name)) {
220 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
225 #endif /* SILC_EPOC */
228 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
229 (*new_cipher)->cipher = entry;
230 (*new_cipher)->context = silc_calloc(1, entry->context_len());
231 (*new_cipher)->set_iv = silc_cipher_set_iv;
232 (*new_cipher)->get_iv = silc_cipher_get_iv;
233 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
234 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
241 /* Free's the given cipher. */
243 void silc_cipher_free(SilcCipher cipher)
246 silc_free(cipher->context);
251 /* Returns TRUE if cipher `name' is supported. */
253 bool silc_cipher_is_supported(const unsigned char *name)
256 SilcCipherObject *entry;
258 if (silc_cipher_list) {
259 silc_dlist_start(silc_cipher_list);
260 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
261 if (!strcmp(entry->name, name))
268 for (i = 0; silc_default_ciphers[i].name; i++)
269 if (!strcmp(silc_default_ciphers[i].name, name))
272 #endif /* SILC_EPOC */
276 /* Returns comma separated list of supported ciphers. */
278 char *silc_cipher_get_supported(void)
280 SilcCipherObject *entry;
285 if (silc_cipher_list) {
286 silc_dlist_start(silc_cipher_list);
287 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
288 len += strlen(entry->name);
289 list = silc_realloc(list, len + 1);
291 memcpy(list + (len - strlen(entry->name)),
292 entry->name, strlen(entry->name));
293 memcpy(list + len, ",", 1);
300 for (i = 0; silc_default_ciphers[i].name; i++) {
301 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
302 len += strlen(entry->name);
303 list = silc_realloc(list, len + 1);
305 memcpy(list + (len - strlen(entry->name)),
306 entry->name, strlen(entry->name));
307 memcpy(list + len, ",", 1);
311 #endif /* SILC_EPOC */
320 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
321 unsigned char *dst, SilcUInt32 len,
324 return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
329 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
330 unsigned char *dst, SilcUInt32 len,
333 return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
336 /* Sets the key for the cipher */
338 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
341 return cipher->cipher->set_key(cipher->context, key, keylen);
344 /* Sets the IV (initial vector) for the cipher. */
346 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
348 memset(&cipher->iv, 0, sizeof(cipher->iv));
349 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
352 /* Returns the IV (initial vector) of the cipher. The IV is returned
355 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
357 memcpy(iv, &cipher->iv, cipher->cipher->block_len);
360 /* Returns the key length of the cipher. */
362 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
364 return cipher->cipher->key_len;
367 /* Returns the block size of the cipher. */
369 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
371 return cipher->cipher->block_len;