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 */
25 /* The SilcCipher context */
26 struct SilcCipherStruct {
27 SilcCipherObject *cipher;
29 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
33 /* Dynamically registered list of ciphers. */
34 SilcDList silc_cipher_list = NULL;
35 #endif /* SILC_EPOC */
37 /* Static list of ciphers for silc_cipher_register_default(). */
38 const SilcCipherObject silc_default_ciphers[] =
40 { "aes-256-cbc", 16, 256, silc_aes_set_key,
41 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
42 silc_aes_decrypt_cbc, silc_aes_context_len },
43 { "aes-192-cbc", 16, 192, silc_aes_set_key,
44 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
45 silc_aes_decrypt_cbc, silc_aes_context_len },
46 { "aes-128-cbc", 16, 128, silc_aes_set_key,
47 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
48 silc_aes_decrypt_cbc, silc_aes_context_len },
49 { "twofish-256-cbc", 16, 256, silc_twofish_set_key,
50 silc_twofish_set_key_with_string,
51 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
52 silc_twofish_context_len },
53 { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
54 silc_twofish_set_key_with_string,
55 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
56 silc_twofish_context_len },
57 { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
58 silc_twofish_set_key_with_string,
59 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
60 silc_twofish_context_len },
61 { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
62 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
63 silc_rc6_context_len },
64 { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
65 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
66 silc_rc6_context_len },
67 { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
68 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
69 silc_rc6_context_len },
70 { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
71 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
72 silc_mars_context_len },
73 { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
74 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
75 silc_mars_context_len },
76 { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
77 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
78 silc_mars_context_len },
79 { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
80 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
81 silc_cast_context_len },
82 { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
83 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
84 silc_cast_context_len },
85 { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
86 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
87 silc_cast_context_len },
88 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
89 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
90 silc_none_context_len },
92 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
95 /* Register a new cipher into SILC. This is used at the initialization of
96 the SILC. This function allocates a new object for the cipher to be
97 registered. Therefore, if memory has been allocated for the object sent
98 as argument it has to be free'd after this function returns succesfully. */
100 bool silc_cipher_register(const SilcCipherObject *cipher)
103 SilcCipherObject *new;
105 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
107 /* Check if exists already */
108 if (silc_cipher_list) {
109 SilcCipherObject *entry;
110 silc_dlist_start(silc_cipher_list);
111 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
112 if (!strcmp(entry->name, cipher->name))
117 new = silc_calloc(1, sizeof(*new));
118 new->name = strdup(cipher->name);
119 new->block_len = cipher->block_len;
120 new->key_len = cipher->key_len;
121 new->set_key = cipher->set_key;
122 new->set_key_with_string = cipher->set_key_with_string;
123 new->encrypt = cipher->encrypt;
124 new->decrypt = cipher->decrypt;
125 new->context_len = cipher->context_len;
128 if (silc_cipher_list == NULL)
129 silc_cipher_list = silc_dlist_init();
130 silc_dlist_add(silc_cipher_list, new);
132 #endif /* SILC_EPOC */
136 /* Unregister a cipher from the SILC. */
138 bool silc_cipher_unregister(SilcCipherObject *cipher)
141 SilcCipherObject *entry;
143 SILC_LOG_DEBUG(("Unregistering cipher"));
145 if (!silc_cipher_list)
148 silc_dlist_start(silc_cipher_list);
149 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
150 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
151 silc_dlist_del(silc_cipher_list, entry);
152 silc_free(entry->name);
155 if (silc_dlist_count(silc_cipher_list) == 0) {
156 silc_dlist_uninit(silc_cipher_list);
157 silc_cipher_list = NULL;
164 #endif /* SILC_EPOC */
168 /* Function that registers all the default ciphers (all builtin ciphers).
169 The application may use this to register the default ciphers if specific
170 ciphers in any specific order is not wanted. */
172 bool silc_cipher_register_default(void)
177 for (i = 0; silc_default_ciphers[i].name; i++)
178 silc_cipher_register(&(silc_default_ciphers[i]));
180 #endif /* SILC_EPOC */
184 bool silc_cipher_unregister_all(void)
187 SilcCipherObject *entry;
189 if (!silc_cipher_list)
192 silc_dlist_start(silc_cipher_list);
193 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
194 silc_cipher_unregister(entry);
195 if (!silc_cipher_list)
198 #endif /* SILC_EPOC */
202 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
203 on error. The allocated cipher is returned in new_cipher argument. The
204 caller must set the key to the cipher after this function has returned
205 by calling the ciphers set_key function. */
207 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
209 SilcCipherObject *entry = NULL;
211 SILC_LOG_DEBUG(("Allocating new cipher object"));
214 if (silc_cipher_list) {
215 silc_dlist_start(silc_cipher_list);
216 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
217 if (!strcmp(entry->name, name))
223 /* On EPOC which don't have globals we check our constant cipher list. */
225 for (i = 0; silc_default_ciphers[i].name; i++) {
226 if (!strcmp(silc_default_ciphers[i].name, name)) {
227 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
232 #endif /* SILC_EPOC */
235 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
236 (*new_cipher)->cipher = entry;
237 (*new_cipher)->context = silc_calloc(1, entry->context_len());
244 /* Free's the given cipher. */
246 void silc_cipher_free(SilcCipher cipher)
249 silc_free(cipher->context);
254 /* Returns TRUE if cipher `name' is supported. */
256 bool silc_cipher_is_supported(const unsigned char *name)
259 SilcCipherObject *entry;
261 if (silc_cipher_list) {
262 silc_dlist_start(silc_cipher_list);
263 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
264 if (!strcmp(entry->name, name))
271 for (i = 0; silc_default_ciphers[i].name; i++)
272 if (!strcmp(silc_default_ciphers[i].name, name))
275 #endif /* SILC_EPOC */
279 /* Returns comma separated list of supported ciphers. */
281 char *silc_cipher_get_supported(void)
283 SilcCipherObject *entry;
288 if (silc_cipher_list) {
289 silc_dlist_start(silc_cipher_list);
290 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
291 len += strlen(entry->name);
292 list = silc_realloc(list, len + 1);
294 memcpy(list + (len - strlen(entry->name)),
295 entry->name, strlen(entry->name));
296 memcpy(list + len, ",", 1);
303 for (i = 0; silc_default_ciphers[i].name; i++) {
304 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
305 len += strlen(entry->name);
306 list = silc_realloc(list, len + 1);
308 memcpy(list + (len - strlen(entry->name)),
309 entry->name, strlen(entry->name));
310 memcpy(list + len, ",", 1);
314 #endif /* SILC_EPOC */
323 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
324 unsigned char *dst, SilcUInt32 len,
327 return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
332 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
333 unsigned char *dst, SilcUInt32 len,
336 return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
339 /* Sets the key for the cipher */
341 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
344 return cipher->cipher->set_key(cipher->context, key, keylen);
347 /* Sets the IV (initial vector) for the cipher. */
349 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
351 memset(&cipher->iv, 0, sizeof(cipher->iv));
352 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
355 /* Returns the IV (initial vector) of the cipher. */
357 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
362 /* Returns the key length of the cipher. */
364 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
366 return cipher->cipher->key_len;
369 /* Returns the block size of the cipher. */
371 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
373 return cipher->cipher->block_len;
376 /* Returns the name of the cipher */
378 const char *silc_cipher_get_name(SilcCipher cipher)
380 return (const char *)cipher->cipher->name;