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"
23 #include "ciphers.h" /* Includes cipher definitions */
25 /* The SilcCipher context */
26 struct SilcCipherStruct {
27 SilcCipherObject *cipher;
29 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
33 /* Dynamically registered list of ciphers. */
34 SilcDList silc_cipher_list = NULL;
35 #endif /* SILC_EPOC */
37 /* Static list of ciphers for silc_cipher_register_default(). */
38 const SilcCipherObject silc_default_ciphers[] =
40 { "aes-256-cbc", 16, 256, silc_aes_set_key,
41 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
42 silc_aes_decrypt_cbc, silc_aes_context_len },
43 { "aes-192-cbc", 16, 192, silc_aes_set_key,
44 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
45 silc_aes_decrypt_cbc, silc_aes_context_len },
46 { "aes-128-cbc", 16, 128, silc_aes_set_key,
47 silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
48 silc_aes_decrypt_cbc, silc_aes_context_len },
49 { "twofish-256-cbc", 16, 256, 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 { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
54 silc_twofish_set_key_with_string,
55 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
56 silc_twofish_context_len },
57 { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
58 silc_twofish_set_key_with_string,
59 silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
60 silc_twofish_context_len },
61 { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
62 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
63 silc_cast_context_len },
64 { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
65 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
66 silc_cast_context_len },
67 { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
68 silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
69 silc_cast_context_len },
70 { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
71 silc_none_encrypt_cbc, silc_none_decrypt_cbc,
72 silc_none_context_len },
74 { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
77 /* Register a new cipher into SILC. This is used at the initialization of
78 the SILC. This function allocates a new object for the cipher to be
79 registered. Therefore, if memory has been allocated for the object sent
80 as argument it has to be free'd after this function returns succesfully. */
82 bool silc_cipher_register(const SilcCipherObject *cipher)
85 SilcCipherObject *new;
87 SILC_LOG_DEBUG(("Registering new cipher `%s'", cipher->name));
89 /* Check if exists already */
90 if (silc_cipher_list) {
91 SilcCipherObject *entry;
92 silc_dlist_start(silc_cipher_list);
93 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
94 if (!strcmp(entry->name, cipher->name))
99 new = silc_calloc(1, sizeof(*new));
100 new->name = strdup(cipher->name);
101 new->block_len = cipher->block_len;
102 new->key_len = cipher->key_len;
103 new->set_key = cipher->set_key;
104 new->set_key_with_string = cipher->set_key_with_string;
105 new->encrypt = cipher->encrypt;
106 new->decrypt = cipher->decrypt;
107 new->context_len = cipher->context_len;
110 if (silc_cipher_list == NULL)
111 silc_cipher_list = silc_dlist_init();
112 silc_dlist_add(silc_cipher_list, new);
114 #endif /* SILC_EPOC */
118 /* Unregister a cipher from the SILC. */
120 bool silc_cipher_unregister(SilcCipherObject *cipher)
123 SilcCipherObject *entry;
125 SILC_LOG_DEBUG(("Unregistering cipher"));
127 if (!silc_cipher_list)
130 silc_dlist_start(silc_cipher_list);
131 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
132 if (cipher == SILC_ALL_CIPHERS || entry == cipher) {
133 silc_dlist_del(silc_cipher_list, entry);
134 silc_free(entry->name);
137 if (silc_dlist_count(silc_cipher_list) == 0) {
138 silc_dlist_uninit(silc_cipher_list);
139 silc_cipher_list = NULL;
146 #endif /* SILC_EPOC */
150 /* Function that registers all the default ciphers (all builtin ciphers).
151 The application may use this to register the default ciphers if specific
152 ciphers in any specific order is not wanted. */
154 bool silc_cipher_register_default(void)
159 for (i = 0; silc_default_ciphers[i].name; i++)
160 silc_cipher_register(&(silc_default_ciphers[i]));
162 #endif /* SILC_EPOC */
166 bool silc_cipher_unregister_all(void)
169 SilcCipherObject *entry;
171 if (!silc_cipher_list)
174 silc_dlist_start(silc_cipher_list);
175 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
176 silc_cipher_unregister(entry);
177 if (!silc_cipher_list)
180 #endif /* SILC_EPOC */
184 /* Allocates a new SILC cipher object. Function returns 1 on succes and 0
185 on error. The allocated cipher is returned in new_cipher argument. The
186 caller must set the key to the cipher after this function has returned
187 by calling the ciphers set_key function. */
189 bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
191 SilcCipherObject *entry = NULL;
193 SILC_LOG_DEBUG(("Allocating new cipher object"));
196 if (silc_cipher_list) {
197 silc_dlist_start(silc_cipher_list);
198 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
199 if (!strcmp(entry->name, name))
205 /* On EPOC which don't have globals we check our constant cipher list. */
207 for (i = 0; silc_default_ciphers[i].name; i++) {
208 if (!strcmp(silc_default_ciphers[i].name, name)) {
209 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
214 #endif /* SILC_EPOC */
217 *new_cipher = silc_calloc(1, sizeof(**new_cipher));
218 (*new_cipher)->cipher = entry;
219 (*new_cipher)->context = silc_calloc(1, entry->context_len());
226 /* Free's the given cipher. */
228 void silc_cipher_free(SilcCipher cipher)
231 silc_free(cipher->context);
236 /* Returns TRUE if cipher `name' is supported. */
238 bool silc_cipher_is_supported(const unsigned char *name)
241 SilcCipherObject *entry;
243 if (silc_cipher_list) {
244 silc_dlist_start(silc_cipher_list);
245 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
246 if (!strcmp(entry->name, name))
253 for (i = 0; silc_default_ciphers[i].name; i++)
254 if (!strcmp(silc_default_ciphers[i].name, name))
257 #endif /* SILC_EPOC */
261 /* Returns comma separated list of supported ciphers. */
263 char *silc_cipher_get_supported(void)
265 SilcCipherObject *entry;
270 if (silc_cipher_list) {
271 silc_dlist_start(silc_cipher_list);
272 while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
273 len += strlen(entry->name);
274 list = silc_realloc(list, len + 1);
276 memcpy(list + (len - strlen(entry->name)),
277 entry->name, strlen(entry->name));
278 memcpy(list + len, ",", 1);
285 for (i = 0; silc_default_ciphers[i].name; i++) {
286 entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
287 len += strlen(entry->name);
288 list = silc_realloc(list, len + 1);
290 memcpy(list + (len - strlen(entry->name)),
291 entry->name, strlen(entry->name));
292 memcpy(list + len, ",", 1);
296 #endif /* SILC_EPOC */
305 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
306 unsigned char *dst, SilcUInt32 len,
310 assert((len & (cipher->cipher->block_len - 1)) == 0);
312 if (len & (cipher->cipher->block_len - 1))
314 return cipher->cipher->encrypt(cipher->context, src, dst, len,
315 iv ? iv : cipher->iv);
320 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
321 unsigned char *dst, SilcUInt32 len,
325 assert((len & (cipher->cipher->block_len - 1)) == 0);
327 if (len & (cipher->cipher->block_len - 1))
329 return cipher->cipher->decrypt(cipher->context, src, dst, len,
330 iv ? iv : cipher->iv);
333 /* Sets the key for the cipher */
335 bool silc_cipher_set_key(SilcCipher cipher, const unsigned char *key,
338 return cipher->cipher->set_key(cipher->context, key, keylen);
341 /* Sets the IV (initial vector) for the cipher. */
343 void silc_cipher_set_iv(SilcCipher cipher, const unsigned char *iv)
345 memset(&cipher->iv, 0, sizeof(cipher->iv));
346 memcpy(&cipher->iv, iv, cipher->cipher->block_len);
349 /* Returns the IV (initial vector) of the cipher. */
351 unsigned char *silc_cipher_get_iv(SilcCipher cipher)
356 /* Returns the key length of the cipher. */
358 SilcUInt32 silc_cipher_get_key_len(SilcCipher cipher)
360 return cipher->cipher->key_len;
363 /* Returns the block size of the cipher. */
365 SilcUInt32 silc_cipher_get_block_len(SilcCipher cipher)
367 return cipher->cipher->block_len;
370 /* Returns the name of the cipher */
372 const char *silc_cipher_get_name(SilcCipher cipher)
374 return (const char *)cipher->cipher->name;