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 /* List of all ciphers in SILC. You can dynamically add new ciphers
27 into the list. At the initialization of SILC this list is filled with
28 the configured ciphers. */
29 struct SilcCipherListStruct {
30 SilcCipherObject *cipher;
31 struct SilcCipherListStruct *next;
34 /* Dynamically registered list of ciphers. */
35 struct SilcCipherListStruct *silc_cipher_list = NULL;
37 /* Staticly declared list of ciphers. This is used if system doesn't
39 SilcCipherObject silc_cipher_builtin_list[] =
41 { "aes-256-cbc", 16, 256, silc_aes_set_key,
42 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
43 silc_aes_decrypt_cbc, silc_aes_context_len },
44 { "aes-192-cbc", 16, 192, silc_aes_set_key,
45 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
46 silc_aes_decrypt_cbc, silc_aes_context_len },
47 { "aes-128-cbc", 16, 128, silc_aes_set_key,
48 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
49 silc_aes_decrypt_cbc, silc_aes_context_len },
50 { "twofish-256-cbc", 16, 256, 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 { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
55 silc_twofish_set_key_with_string,
56 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
57 silc_twofish_context_len },
58 { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
59 silc_twofish_set_key_with_string,
60 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
61 silc_twofish_context_len },
62 { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
63 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
64 silc_rc6_context_len },
65 { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
66 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
67 silc_rc6_context_len },
68 { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
69 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
70 silc_rc6_context_len },
71 { "mars-256-cbc", 16, 256, silc_mars_set_key, silc_mars_set_key_with_string,
72 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
73 silc_mars_context_len },
74 { "mars-192-cbc", 16, 192, silc_mars_set_key, silc_mars_set_key_with_string,
75 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
76 silc_mars_context_len },
77 { "mars-128-cbc", 16, 128, silc_mars_set_key, silc_mars_set_key_with_string,
78 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
79 silc_mars_context_len },
80 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
81 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
82 silc_none_context_len },
84 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
87 /* Register a new cipher into SILC. This is used at the initialization of
88 the SILC. This function allocates a new object for the cipher to be
89 registered. Therefore, if memory has been allocated for the object sent
90 as argument it has to be free'd after this function returns succesfully. */
92 int silc_cipher_register(SilcCipherObject *cipher)
94 struct SilcCipherListStruct *new, *c;
96 SILC_LOG_DEBUG(("Registering new cipher"));
98 new = silc_calloc(1, sizeof(*new));
99 new->cipher = silc_calloc(1, sizeof(*new->cipher));
101 /* Set the pointers */
102 new->cipher->name = strdup(cipher->name);
103 new->cipher->block_len = cipher->block_len;
104 new->cipher->key_len = cipher->key_len;
105 new->cipher->set_key = cipher->set_key;
106 new->cipher->set_key_with_string = cipher->set_key_with_string;
107 new->cipher->encrypt = cipher->encrypt;
108 new->cipher->decrypt = cipher->decrypt;
109 new->cipher->context_len = cipher->context_len;
112 /* Add the new cipher to the list */
113 if (!silc_cipher_list) {
114 silc_cipher_list = new;
118 c = silc_cipher_list;
130 /* Unregister a cipher from the SILC. */
132 int silc_cipher_unregister(SilcCipherObject *cipher)
134 struct SilcCipherListStruct *c, *tmp;
136 SILC_LOG_DEBUG(("Unregistering cipher"));
138 c = silc_cipher_list;
140 if (cipher == SILC_ALL_CIPHERS) {
141 /* Unregister all ciphers */
144 silc_free(c->cipher->name);
152 /* Unregister the cipher */
153 if (c->cipher == cipher) {
155 silc_free(c->cipher->name);
157 silc_cipher_list = tmp;
163 if (c->next->cipher == cipher) {
166 silc_free(c->cipher->name);
179 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
180 on error. The allocated cipher is returned in new_cipher argument. The
181 caller must set the key to the cipher after this function has returned
182 by calling the ciphers set_key function. */
184 int silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
186 struct SilcCipherListStruct *c;
189 SILC_LOG_DEBUG(("Allocating new cipher object"));
191 /* Allocate the new object */
192 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
194 if (silc_cipher_list) {
196 c = silc_cipher_list;
198 if (!strcmp(c->cipher->name, name))
206 /* Set the pointers */
207 (*new_cipher)->cipher = c->cipher;
208 (*new_cipher)->context = silc_calloc(1, c->cipher->context_len());
209 (*new_cipher)->set_iv = silc_cipher_set_iv;
210 (*new_cipher)->get_iv = silc_cipher_get_iv;
211 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
212 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
219 for (i = 0; silc_cipher_builtin_list[i].name; i++)
220 if (!strcmp(silc_cipher_builtin_list[i].name, name))
223 if (silc_cipher_builtin_list[i].name == NULL) {
224 silc_free(*new_cipher);
228 /* Set the pointers */
229 (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
230 (*new_cipher)->context =
231 silc_calloc(1, (*new_cipher)->cipher->context_len());
232 (*new_cipher)->set_iv = silc_cipher_set_iv;
233 (*new_cipher)->get_iv = silc_cipher_get_iv;
234 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
235 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
236 memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
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 int silc_cipher_is_supported(const unsigned char *name)
255 struct SilcCipherListStruct *c;
258 if (silc_cipher_list) {
259 c = silc_cipher_list;
262 if (!strcmp(c->cipher->name, name))
268 for (i = 0; silc_cipher_builtin_list[i].name; i++)
269 if (!strcmp(silc_cipher_builtin_list[i].name, name))
275 /* Returns comma separated list of supported ciphers. */
277 char *silc_cipher_get_supported()
281 struct SilcCipherListStruct *c;
284 if (silc_cipher_list) {
285 c = silc_cipher_list;
288 len += strlen(c->cipher->name);
289 list = silc_realloc(list, len + 1);
291 memcpy(list + (len - strlen(c->cipher->name)),
292 c->cipher->name, strlen(c->cipher->name));
293 memcpy(list + len, ",", 1);
300 for (i = 0; silc_cipher_builtin_list[i].name; i++) {
301 len += strlen(silc_cipher_builtin_list[i].name);
302 list = silc_realloc(list, len + 1);
304 memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)),
305 silc_cipher_builtin_list[i].name,
306 strlen(silc_cipher_builtin_list[i].name));
307 memcpy(list + len, ",", 1);
316 /* Sets the IV (initial vector) for the cipher. */
318 void silc_cipher_set_iv(SilcCipher itself, const unsigned char *iv)
320 memset(&itself->iv, 0, sizeof(itself->iv));
321 memcpy(&itself->iv, iv, itself->cipher->block_len);
324 /* Returns the IV (initial vector) of the cipher. The IV is returned
327 void silc_cipher_get_iv(SilcCipher itself, unsigned char *iv)
329 memcpy(iv, &itself->iv, itself->cipher->block_len);
332 /* Returns the key length of the cipher. */
334 unsigned int silc_cipher_get_key_len(SilcCipher itself,
335 const unsigned char *name)
337 return itself->cipher->key_len;
340 /* Returns the block size of the cipher. */
342 unsigned int silc_cipher_get_block_len(SilcCipher itself)
344 return itself->cipher->block_len;