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 `%s'", cipher->name));
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))
203 if (!c || !c->cipher->context_len)
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);
229 /* Set the pointers */
230 (*new_cipher)->cipher = &silc_cipher_builtin_list[i];
231 (*new_cipher)->context =
232 silc_calloc(1, (*new_cipher)->cipher->context_len());
233 (*new_cipher)->set_iv = silc_cipher_set_iv;
234 (*new_cipher)->get_iv = silc_cipher_get_iv;
235 (*new_cipher)->get_key_len = silc_cipher_get_key_len;
236 (*new_cipher)->get_block_len = silc_cipher_get_block_len;
237 memset(&(*new_cipher)->iv, 0, sizeof((*new_cipher)->iv));
242 /* Free's the given cipher. */
244 void silc_cipher_free(SilcCipher cipher)
247 silc_free(cipher->context);
252 /* Returns TRUE if cipher `name' is supported. */
254 int silc_cipher_is_supported(const unsigned char *name)
256 struct SilcCipherListStruct *c;
259 if (silc_cipher_list) {
260 c = silc_cipher_list;
263 if (!strcmp(c->cipher->name, name))
269 for (i = 0; silc_cipher_builtin_list[i].name; i++)
270 if (!strcmp(silc_cipher_builtin_list[i].name, name))
276 /* Returns comma separated list of supported ciphers. */
278 char *silc_cipher_get_supported()
282 struct SilcCipherListStruct *c;
285 if (silc_cipher_list) {
286 c = silc_cipher_list;
289 len += strlen(c->cipher->name);
290 list = silc_realloc(list, len + 1);
292 memcpy(list + (len - strlen(c->cipher->name)),
293 c->cipher->name, strlen(c->cipher->name));
294 memcpy(list + len, ",", 1);
301 for (i = 0; silc_cipher_builtin_list[i].name; i++) {
302 len += strlen(silc_cipher_builtin_list[i].name);
303 list = silc_realloc(list, len + 1);
305 memcpy(list + (len - strlen(silc_cipher_builtin_list[i].name)),
306 silc_cipher_builtin_list[i].name,
307 strlen(silc_cipher_builtin_list[i].name));
308 memcpy(list + len, ",", 1);
319 int silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
320 unsigned char *dst, uint32 len,
323 return cipher->cipher->encrypt(cipher->context, src, dst, len, iv);
328 int silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
329 unsigned char *dst, uint32 len,
332 return cipher->cipher->decrypt(cipher->context, src, dst, len, iv);
335 /* Sets the key for the cipher */
337 int silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
340 return cipher->cipher->set_key(cipher->context, key, keylen);
343 /* Sets the IV (initial vector) for the cipher. */
345 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
347 memset(&cipher->iv, 0, sizeof(cipher->iv));
348 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
351 /* Returns the IV (initial vector) of the cipher. The IV is returned
354 void silc_cipher_get_iv(SilcCipher cipher, unsigned char *iv)
356 memcpy(iv, &cipher->iv, cipher->cipher->block_len);
359 /* Returns the key length of the cipher. */
361 uint32 silc_cipher_get_key_len(SilcCipher cipher)
363 return cipher->cipher->key_len;
366 /* Returns the block size of the cipher. */
368 uint32 silc_cipher_get_block_len(SilcCipher cipher)
370 return cipher->cipher->block_len;