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 /* XXX: add the other good ciphers here as well */
39 /* Staticly declared list of ciphers. This is used if system doesn't
41 SilcCipherObject silc_cipher_builtin_list[] =
43 { "twofish", 16, 16, silc_twofish_set_key, silc_twofish_set_key_with_string,
44 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
45 silc_twofish_context_len },
46 { "aes", 16, 16, silc_rijndael_set_key,
47 silc_rijndael_set_key_with_string, silc_rijndael_encrypt_cbc,
48 silc_rijndael_decrypt_cbc, silc_rijndael_context_len },
49 { "rc6", 16, 16, silc_rc6_set_key, silc_rc6_set_key_with_string,
50 silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc,
51 silc_rc6_context_len },
52 { "mars", 16, 16, silc_mars_set_key, silc_mars_set_key_with_string,
53 silc_mars_encrypt_cbc, silc_mars_decrypt_cbc,
54 silc_mars_context_len },
55 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
56 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
57 silc_none_context_len },
59 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
62 /* Register a new cipher into SILC. This is used at the initialization of
63 the SILC. This function allocates a new object for the cipher to be
64 registered. Therefore, if memory has been allocated for the object sent
65 as argument it has to be free'd after this function returns succesfully. */
67 int silc_cipher_register(SilcCipherObject *cipher)
69 struct SilcCipherListStruct *new, *c;
71 SILC_LOG_DEBUG(("Registering new cipher"));
73 new = silc_calloc(1, sizeof(*new));
74 new->cipher = silc_calloc(1, sizeof(*new->cipher));
76 /* Set the pointers */
77 new->cipher->name = strdup(cipher->name);
78 new->cipher->block_len = cipher->block_len;
79 new->cipher->key_len = cipher->key_len;
80 new->cipher->set_key = cipher->set_key;
81 new->cipher->set_key_with_string = cipher->set_key_with_string;
82 new->cipher->encrypt = cipher->encrypt;
83 new->cipher->decrypt = cipher->decrypt;
84 new->cipher->context_len = cipher->context_len;
87 /* Add the new cipher to the list */
88 if (!silc_cipher_list) {
89 silc_cipher_list = new;
105 /* Unregister a cipher from the SILC. */
107 int silc_cipher_unregister(SilcCipherObject *cipher)
109 struct SilcCipherListStruct *c, *tmp;
111 SILC_LOG_DEBUG(("Unregistering cipher"));
113 c = silc_cipher_list;
115 if (cipher == SILC_ALL_CIPHERS) {
116 /* Unregister all ciphers */
119 silc_free(c->cipher->name);
127 /* Unregister the cipher */
128 if (c->cipher == cipher) {
130 silc_free(c->cipher->name);
132 silc_cipher_list = tmp;
138 if (c->next->cipher == cipher) {
141 silc_free(c->cipher->name);
154 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
155 on error. The allocated cipher is returned in new_cipher argument. The
156 caller must set the key to the cipher after this function has returned
157 by calling the ciphers set_key function. */
159 int silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
161 struct SilcCipherListStruct *c;
164 SILC_LOG_DEBUG(("Allocating new cipher object"));
166 /* Allocate the new object */
167 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
169 if (silc_cipher_list) {
171 c = silc_cipher_list;
173 if (!strcmp(c->cipher->name, name))
181 /* Set the pointers */
182 (*new_cipher)->cipher = c->cipher;
183 (*new_cipher)->context = silc_calloc(1, c->cipher->context_len());
184 (*new_cipher)->set_iv = silc_cipher_set_iv;
185 (*new_cipher)->get_iv = silc_cipher_get_iv;
186 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
187 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
194 for (i = 0; silc_cipher_builtin_list[i].name; i++)
195 if (!strcmp(silc_cipher_builtin_list[i].name, name))
198 if (silc_cipher_builtin_list[i].name == NULL) {
199 silc_free(*new_cipher);
203 /* Set the pointers */
204 (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
205 (*new_cipher)->context =
206 silc_calloc(1, (*new_cipher)->cipher->context_len());
207 (*new_cipher)->set_iv = silc_cipher_set_iv;
208 (*new_cipher)->get_iv = silc_cipher_get_iv;
209 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
210 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
211 memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
216 /* Free's the given cipher. */
218 void silc_cipher_free(SilcCipher cipher)
221 silc_free(cipher->context);
226 /* Returns TRUE if cipher `name' is supported. */
228 int silc_cipher_is_supported(const unsigned char *name)
230 struct SilcCipherListStruct *c;
233 if (silc_cipher_list) {
234 c = silc_cipher_list;
237 if (!strcmp(c->cipher->name, name))
243 for (i = 0; silc_cipher_builtin_list[i].name; i++)
244 if (!strcmp(silc_cipher_builtin_list[i].name, name))
250 /* Returns comma separated list of supported ciphers. */
252 char *silc_cipher_get_supported()
256 struct SilcCipherListStruct *c;
259 if (silc_cipher_list) {
260 c = silc_cipher_list;
263 len += strlen(c->cipher->name);
264 list = silc_realloc(list, len + 1);
266 memcpy(list + (len - strlen(c->cipher->name)),
267 c->cipher->name, strlen(c->cipher->name));
268 memcpy(list + len, ",", 1);
275 for (i = 0; silc_cipher_builtin_list[i].name; i++) {
276 len += strlen(silc_cipher_builtin_list[i].name);
277 list = silc_realloc(list, len + 1);
279 memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)),
280 silc_cipher_builtin_list[i].name,
281 strlen(silc_cipher_builtin_list[i].name));
282 memcpy(list + len, ",", 1);
291 /* Sets the IV (initial vector) for the cipher. */
293 void silc_cipher_set_iv(SilcCipher itself, const unsigned char *iv)
295 memset(&itself->iv, 0, sizeof(itself->iv));
296 memcpy(&itself->iv, iv, itself->cipher->block_len);
299 /* Returns the IV (initial vector) of the cipher. The IV is returned
302 void silc_cipher_get_iv(SilcCipher itself, unsigned char *iv)
304 memcpy(iv, &itself->iv, itself->cipher->block_len);
307 /* Returns the key length of the cipher. */
310 unsigned int silc_cipher_get_key_len(SilcCipher itself,
311 const unsigned char *name)
317 /* Returns the block size of the cipher. */
320 unsigned int silc_cipher_get_block_len(SilcCipher itself)