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"
24 #include "ciphers.h" /* Includes cipher definitions */
26 /* Dynamically registered list of ciphers. */
27 SilcDList silc_cipher_list = NULL;
29 /* Static list of ciphers for silc_cipher_register_default(). */
30 SilcCipherObject silc_default_ciphers[] =
32 { "aes-256-cbc", 16, 256, silc_aes_set_key,
33 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
34 silc_aes_decrypt_cbc, silc_aes_context_len },
35 { "aes-192-cbc", 16, 192, silc_aes_set_key,
36 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
37 silc_aes_decrypt_cbc, silc_aes_context_len },
38 { "aes-128-cbc", 16, 128, silc_aes_set_key,
39 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
40 silc_aes_decrypt_cbc, silc_aes_context_len },
41 { "twofish-256-cbc", 16, 256, silc_twofish_set_key,
42 silc_twofish_set_key_with_string,
43 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
44 silc_twofish_context_len },
45 { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
46 silc_twofish_set_key_with_string,
47 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
48 silc_twofish_context_len },
49 { "twofish-128-cbc", 16, 128, 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 { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
54 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
55 silc_rc6_context_len },
56 { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
57 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
58 silc_rc6_context_len },
59 { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
60 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
61 silc_rc6_context_len },
62 { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
63 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
64 silc_mars_context_len },
65 { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
66 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
67 silc_mars_context_len },
68 { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
69 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
70 silc_mars_context_len },
71 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
72 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
73 silc_none_context_len },
75 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
78 /* Register a new cipher into SILC. This is used at the initialization of
79 the SILC. This function allocates a new object for the cipher to be
80 registered. Therefore, if memory has been allocated for the object sent
81 as argument it has to be free'd after this function returns succesfully. */
83 bool silc_cipher_register(SilcCipherObject *cipher)
85 SilcCipherObject *new;
87 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
89 new = silc_calloc(1, sizeof(*new));
90 new->name = strdup(cipher->name);
91 new->block_len = cipher->block_len;
92 new->key_len = cipher->key_len;
93 new->set_key = cipher->set_key;
94 new->set_key_with_string = cipher->set_key_with_string;
95 new->encrypt = cipher->encrypt;
96 new->decrypt = cipher->decrypt;
97 new->context_len = cipher->context_len;
100 if (silc_cipher_list == NULL)
101 silc_cipher_list = silc_dlist_init();
102 silc_dlist_add(silc_cipher_list, new);
107 /* Unregister a cipher from the SILC. */
109 bool silc_cipher_unregister(SilcCipherObject *cipher)
111 SilcCipherObject *entry;
113 SILC_LOG_DEBUG(("Unregistering cipher"));
115 if (!silc_cipher_list)
118 silc_dlist_start(silc_cipher_list);
119 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
120 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
121 silc_dlist_del(silc_cipher_list, entry);
123 if (silc_dlist_count(silc_cipher_list) == 0) {
124 silc_dlist_uninit(silc_cipher_list);
125 silc_cipher_list = NULL;
135 /* Function that registers all the default ciphers (all builtin ciphers).
136 The application may use this to register the default ciphers if specific
137 ciphers in any specific order is not wanted. */
139 bool silc_cipher_register_default(void)
143 for (i = 0; silc_default_ciphers[i].name; i++)
144 silc_cipher_register(&(silc_default_ciphers[i]));
149 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
150 on error. The allocated cipher is returned in new_cipher argument. The
151 caller must set the key to the cipher after this function has returned
152 by calling the ciphers set_key function. */
154 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
156 SilcCipherObject *entry;
158 SILC_LOG_DEBUG(("Allocating new cipher object"));
160 if (silc_cipher_list) {
161 silc_dlist_start(silc_cipher_list);
162 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
163 if (!strcmp(entry->name, name)) {
164 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
165 (*new_cipher)->cipher = entry;
166 (*new_cipher)->context = silc_calloc(1, entry->context_len());
167 (*new_cipher)->set_iv = silc_cipher_set_iv;
168 (*new_cipher)->get_iv = silc_cipher_get_iv;
169 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
170 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
179 /* Free's the given cipher. */
181 void silc_cipher_free(SilcCipher cipher)
184 silc_free(cipher->context);
189 /* Returns TRUE if cipher `name' is supported. */
191 bool silc_cipher_is_supported(const unsigned char *name)
193 SilcCipherObject *entry;
195 if (silc_cipher_list) {
196 silc_dlist_start(silc_cipher_list);
197 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
198 if (!strcmp(entry->name, name))
206 /* Returns comma separated list of supported ciphers. */
208 char *silc_cipher_get_supported(void)
210 SilcCipherObject *entry;
215 if (silc_cipher_list) {
216 silc_dlist_start(silc_cipher_list);
217 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
218 len += strlen(entry->name);
219 list = silc_realloc(list, len + 1);
221 memcpy(list + (len - strlen(entry->name)),
222 entry->name, strlen(entry->name));
223 memcpy(list + len, ",", 1);
235 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
236 unsigned char *dst, uint32 len,
239 return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
244 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
245 unsigned char *dst, uint32 len,
248 return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
251 /* Sets the key for the cipher */
253 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
256 return cipher->cipher->set_key(cipher->context, key, keylen);
259 /* Sets the IV (initial vector) for the cipher. */
261 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
263 memset(&cipher->iv, 0, sizeof(cipher->iv));
264 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
267 /* Returns the IV (initial vector) of the cipher. The IV is returned
270 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
272 memcpy(iv, &cipher->iv, cipher->cipher->block_len);
275 /* Returns the key length of the cipher. */
277 uint32 silc_cipher_get_key_len(SilcCipher cipher)
279 return cipher->cipher->key_len;
282 /* Returns the block size of the cipher. */
284 uint32 silc_cipher_get_block_len(SilcCipher cipher)
286 return cipher->cipher->block_len;