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 { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
71 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
72 silc_cast_context_len },
73 { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
74 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
75 silc_cast_context_len },
76 { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
77 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
78 silc_cast_context_len },
79 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
80 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
81 silc_none_context_len },
83 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
86 /* Register a new cipher into SILC. This is used at the initialization of
87 the SILC. This function allocates a new object for the cipher to be
88 registered. Therefore, if memory has been allocated for the object sent
89 as argument it has to be free'd after this function returns succesfully. */
91 bool silc_cipher_register(const SilcCipherObject *cipher)
94 SilcCipherObject *new;
96 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
98 /* Check if exists already */
99 if (silc_cipher_list) {
100 SilcCipherObject *entry;
101 silc_dlist_start(silc_cipher_list);
102 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
103 if (!strcmp(entry->name, cipher->name))
108 new = silc_calloc(1, sizeof(*new));
109 new->name = strdup(cipher->name);
110 new->block_len = cipher->block_len;
111 new->key_len = cipher->key_len;
112 new->set_key = cipher->set_key;
113 new->set_key_with_string = cipher->set_key_with_string;
114 new->encrypt = cipher->encrypt;
115 new->decrypt = cipher->decrypt;
116 new->context_len = cipher->context_len;
119 if (silc_cipher_list == NULL)
120 silc_cipher_list = silc_dlist_init();
121 silc_dlist_add(silc_cipher_list, new);
123 #endif /* SILC_EPOC */
127 /* Unregister a cipher from the SILC. */
129 bool silc_cipher_unregister(SilcCipherObject *cipher)
132 SilcCipherObject *entry;
134 SILC_LOG_DEBUG(("Unregistering cipher"));
136 if (!silc_cipher_list)
139 silc_dlist_start(silc_cipher_list);
140 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
141 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
142 silc_dlist_del(silc_cipher_list, entry);
143 silc_free(entry->name);
146 if (silc_dlist_count(silc_cipher_list) == 0) {
147 silc_dlist_uninit(silc_cipher_list);
148 silc_cipher_list = NULL;
155 #endif /* SILC_EPOC */
159 /* Function that registers all the default ciphers (all builtin ciphers).
160 The application may use this to register the default ciphers if specific
161 ciphers in any specific order is not wanted. */
163 bool silc_cipher_register_default(void)
168 for (i = 0; silc_default_ciphers[i].name; i++)
169 silc_cipher_register(&(silc_default_ciphers[i]));
171 #endif /* SILC_EPOC */
175 bool silc_cipher_unregister_all(void)
178 SilcCipherObject *entry;
180 if (!silc_cipher_list)
183 silc_dlist_start(silc_cipher_list);
184 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
185 silc_cipher_unregister(entry);
186 if (!silc_cipher_list)
189 #endif /* SILC_EPOC */
193 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
194 on error. The allocated cipher is returned in new_cipher argument. The
195 caller must set the key to the cipher after this function has returned
196 by calling the ciphers set_key function. */
198 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
200 SilcCipherObject *entry = NULL;
202 SILC_LOG_DEBUG(("Allocating new cipher object"));
205 if (silc_cipher_list) {
206 silc_dlist_start(silc_cipher_list);
207 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
208 if (!strcmp(entry->name, name))
214 /* On EPOC which don't have globals we check our constant cipher list. */
216 for (i = 0; silc_default_ciphers[i].name; i++) {
217 if (!strcmp(silc_default_ciphers[i].name, name)) {
218 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
223 #endif /* SILC_EPOC */
226 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
227 (*new_cipher)->cipher = entry;
228 (*new_cipher)->context = silc_calloc(1, entry->context_len());
235 /* Free's the given cipher. */
237 void silc_cipher_free(SilcCipher cipher)
240 silc_free(cipher->context);
245 /* Returns TRUE if cipher `name' is supported. */
247 bool silc_cipher_is_supported(const unsigned char *name)
250 SilcCipherObject *entry;
252 if (silc_cipher_list) {
253 silc_dlist_start(silc_cipher_list);
254 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
255 if (!strcmp(entry->name, name))
262 for (i = 0; silc_default_ciphers[i].name; i++)
263 if (!strcmp(silc_default_ciphers[i].name, name))
266 #endif /* SILC_EPOC */
270 /* Returns comma separated list of supported ciphers. */
272 char *silc_cipher_get_supported(void)
274 SilcCipherObject *entry;
279 if (silc_cipher_list) {
280 silc_dlist_start(silc_cipher_list);
281 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
282 len += strlen(entry->name);
283 list = silc_realloc(list, len + 1);
285 memcpy(list + (len - strlen(entry->name)),
286 entry->name, strlen(entry->name));
287 memcpy(list + len, ",", 1);
294 for (i = 0; silc_default_ciphers[i].name; i++) {
295 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
296 len += strlen(entry->name);
297 list = silc_realloc(list, len + 1);
299 memcpy(list + (len - strlen(entry->name)),
300 entry->name, strlen(entry->name));
301 memcpy(list + len, ",", 1);
305 #endif /* SILC_EPOC */
314 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
315 unsigned char *dst, SilcUInt32 len,
319 assert((len & (cipher->cipher->block_len - 1)) == 0);
321 if (len & (cipher->cipher->block_len - 1))
323 return cipher->cipher->encrypt(cipher->context, src, dst, len,
324 iv ? iv : cipher->iv);
329 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
330 unsigned char *dst, SilcUInt32 len,
334 assert((len & (cipher->cipher->block_len - 1)) == 0);
336 if (len & (cipher->cipher->block_len - 1))
338 return cipher->cipher->decrypt(cipher->context, src, dst, len,
339 iv ? iv : cipher->iv);
342 /* Sets the key for the cipher */
344 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
347 return cipher->cipher->set_key(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)
354 memset(&cipher->iv, 0, sizeof(cipher->iv));
355 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
358 /* Returns the IV (initial vector) of the cipher. */
360 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
365 /* Returns the key length of the cipher. */
367 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
369 return cipher->cipher->key_len;
372 /* Returns the block size of the cipher. */
374 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
376 return cipher->cipher->block_len;
379 /* Returns the name of the cipher */
381 const char *silc_cipher_get_name(SilcCipher cipher)
383 return (const char *)cipher->cipher->name;