5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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.
23 * Revision 1.1 2000/06/27 11:36:54 priikone
29 #include "silcincludes.h"
31 #include "ciphers.h" /* Includes cipher definitions */
33 /* List of all ciphers in SILC. You can dynamically add new ciphers
34 into the list. At the initialization of SILC this list is filled with
35 the configured ciphers. */
36 struct SilcCipherListStruct {
37 SilcCipherObject *cipher;
38 struct SilcCipherListStruct *next;
41 /* Dynamically registered list of ciphers. */
42 struct SilcCipherListStruct *silc_cipher_list = NULL;
44 /* XXX: add the other good ciphers here as well */
46 /* Staticly declared list of ciphers. This is used if system doesn't
48 SilcCipherObject silc_cipher_builtin_list[] =
50 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
51 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
52 silc_none_context_len },
53 { "twofish", 16, 16, silc_twofish_set_key, silc_twofish_set_key_with_string,
54 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
55 silc_twofish_context_len },
56 { "rc6", 16, 16, 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 { "mars", 16, 16, silc_mars_set_key, silc_mars_set_key_with_string,
60 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
61 silc_mars_context_len },
63 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
66 /* Register a new cipher into SILC. This is used at the initialization of
67 the SILC. This function allocates a new object for the cipher to be
68 registered. Therefore, if memory has been allocated for the object sent
69 as argument it has to be free'd after this function returns succesfully. */
71 int silc_cipher_register(SilcCipherObject *cipher)
73 struct SilcCipherListStruct *new, *c;
75 SILC_LOG_DEBUG(("Registering new cipher"));
77 new = silc_calloc(1, sizeof(*new));
79 SILC_LOG_ERROR(("Could not allocate new cipher list object: %s",
84 new->cipher = silc_calloc(1, sizeof(*new->cipher));
86 SILC_LOG_ERROR(("Could not allocate new cipher object: %s",
91 /* Set the pointers */
92 new->cipher->name = strdup(cipher->name);
93 new->cipher->block_len = cipher->block_len;
94 new->cipher->key_len = cipher->key_len;
95 new->cipher->set_key = cipher->set_key;
96 new->cipher->set_key_with_string = cipher->set_key_with_string;
97 new->cipher->encrypt = cipher->encrypt;
98 new->cipher->decrypt = cipher->decrypt;
99 new->cipher->context_len = cipher->context_len;
102 /* Add the new cipher to the list */
103 if (!silc_cipher_list) {
104 silc_cipher_list = new;
108 c = silc_cipher_list;
120 /* Unregister a cipher from the SILC. */
122 int silc_cipher_unregister(SilcCipherObject *cipher)
124 struct SilcCipherListStruct *c, *tmp;
126 SILC_LOG_DEBUG(("Unregistering cipher"));
128 c = silc_cipher_list;
130 if (cipher == SILC_ALL_CIPHERS) {
131 /* Unregister all ciphers */
134 silc_free(c->cipher->name);
142 /* Unregister the cipher */
143 if (c->cipher == cipher) {
145 silc_free(c->cipher->name);
147 silc_cipher_list = tmp;
153 if (c->next->cipher == cipher) {
156 silc_free(c->cipher->name);
169 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
170 on error. The allocated cipher is returned in new_cipher argument. The
171 caller must set the key to the cipher after this function has returned
172 by calling the ciphers set_key function. */
174 int silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
176 struct SilcCipherListStruct *c;
179 SILC_LOG_DEBUG(("Allocating new cipher object"));
181 /* Allocate the new object */
182 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
183 if (*new_cipher == NULL) {
184 SILC_LOG_ERROR(("Could not allocate new cipher object"));
188 if (silc_cipher_list) {
190 c = silc_cipher_list;
192 if (!strcmp(c->cipher->name, name))
200 /* Set the pointers */
201 (*new_cipher)->cipher = c->cipher;
202 (*new_cipher)->context = silc_calloc(1, c->cipher->context_len());
203 (*new_cipher)->set_iv = silc_cipher_set_iv;
204 (*new_cipher)->get_iv = silc_cipher_get_iv;
205 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
206 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
213 for (i = 0; silc_cipher_builtin_list[i].name; i++)
214 if (!strcmp(silc_cipher_builtin_list[i].name, name))
217 if (silc_cipher_builtin_list[i].name == NULL) {
218 silc_free(*new_cipher);
222 /* Set the pointers */
223 (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
224 (*new_cipher)->context =
225 silc_calloc(1, (*new_cipher)->cipher->context_len());
226 (*new_cipher)->set_iv = silc_cipher_set_iv;
227 (*new_cipher)->get_iv = silc_cipher_get_iv;
228 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
229 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
230 memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
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 int silc_cipher_is_supported(const unsigned char *name)
249 struct SilcCipherListStruct *c;
252 if (silc_cipher_list) {
253 c = silc_cipher_list;
256 if (!strcmp(c->cipher->name, name))
262 for (i = 0; silc_cipher_builtin_list[i].name; i++)
263 if (!strcmp(silc_cipher_builtin_list[i].name, name))
269 /* Returns comma separated list of supported ciphers. */
271 char *silc_cipher_get_supported()
275 struct SilcCipherListStruct *c;
278 if (silc_cipher_list) {
279 c = silc_cipher_list;
282 len += strlen(c->cipher->name);
283 list = silc_realloc(list, len + 1);
285 memcpy(list + (len - strlen(c->cipher->name)),
286 c->cipher->name, strlen(c->cipher->name));
287 memcpy(list + len, ",", 1);
294 for (i = 0; silc_cipher_builtin_list[i].name; i++) {
295 len += strlen(silc_cipher_builtin_list[i].name);
296 list = silc_realloc(list, len + 1);
298 memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)),
299 silc_cipher_builtin_list[i].name,
300 strlen(silc_cipher_builtin_list[i].name));
301 memcpy(list + len, ",", 1);
310 /* Sets the IV (initial vector) for the cipher. */
312 void silc_cipher_set_iv(SilcCipher itself, const unsigned char *iv)
314 memset(&itself->iv, 0, sizeof(itself->iv));
315 memcpy(&itself->iv, iv, itself->cipher->block_len);
318 /* Returns the IV (initial vector) of the cipher. The IV is returned
321 void silc_cipher_get_iv(SilcCipher itself, unsigned char *iv)
323 memcpy(iv, &itself->iv, itself->cipher->block_len);
326 /* Returns the key length of the cipher. */
329 unsigned int silc_cipher_get_key_len(SilcCipher itself,
330 const unsigned char *name)
336 /* Returns the block size of the cipher. */
339 unsigned int silc_cipher_get_block_len(SilcCipher itself)