5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2008 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include "silccrypto.h"
22 /************************** Types and definitions ***************************/
24 SILC_CIPHER_API_SET_KEY(acc_cipher);
25 SILC_CIPHER_API_SET_IV(acc_cipher);
26 SILC_CIPHER_API_ENCRYPT(acc_cipher);
27 SILC_CIPHER_API_DECRYPT(acc_cipher);
28 SILC_CIPHER_API_INIT(acc_cipher);
29 SILC_CIPHER_API_UNINIT(acc_cipher);
31 /* Accelerated cipher */
32 typedef struct SilcAcceleratorCipherStruct {
33 SilcCipher cipher; /* Associated cipher */
34 SilcCipher acc_cipher; /* Accelerator cipher */
35 } *SilcAcceleratorCipher;
37 /************************** Accelerator Cipher API **************************/
39 /* The Cipher API for the accelerated cipher is simply a wrapper. It
40 calls the SILC Cipher API for the accelerator cipher. */
42 const SilcCipherObject silc_acc_ciph =
47 silc_acc_cipher_set_key,
48 silc_acc_cipher_set_iv,
49 silc_acc_cipher_encrypt,
50 silc_acc_cipher_decrypt,
52 silc_acc_cipher_uninit,
57 SILC_CIPHER_API_SET_KEY(acc_cipher)
59 SilcAcceleratorCipher c = context;
61 /* Set key for the associated cipher too */
62 silc_cipher_set_key(c->cipher, key, keylen, encryption);
64 /* Set key for accelerator */
65 return silc_cipher_set_key(c->acc_cipher, key, keylen, encryption);
68 SILC_CIPHER_API_SET_IV(acc_cipher)
70 SilcAcceleratorCipher c = context;
72 /* Set IV for the associated cipher too */
73 silc_cipher_set_iv(c->cipher, iv);
75 /* Set IV for accelerator */
76 silc_cipher_set_iv(c->acc_cipher, iv);
79 SILC_CIPHER_API_ENCRYPT(acc_cipher)
81 SilcAcceleratorCipher c = context;
82 return silc_cipher_encrypt(c->acc_cipher, src, dst, len, iv);
85 SILC_CIPHER_API_DECRYPT(acc_cipher)
87 SilcAcceleratorCipher c = context;
88 return silc_cipher_decrypt(c->acc_cipher, src, dst, len, iv);
91 SILC_CIPHER_API_INIT(acc_cipher)
93 /* This operation is never called */
97 SILC_CIPHER_API_UNINIT(acc_cipher)
99 SilcAcceleratorCipher c = context;
100 SilcCipherObject *acc_ops = c->acc_cipher->cipher;
102 /* Free the accelerator cipher and its operations we allocated earlier. */
103 silc_cipher_free(c->acc_cipher);
106 /* Free our operations too */
110 /*************************** SILC Accelerator API ***************************/
112 /* Accelerate cipher */
114 SilcCipher silc_acc_cipher(SilcAccelerator acc, SilcCipher cipher)
117 SilcAcceleratorCipher acc_cipher;
118 const SilcCipherObject *alg;
124 SILC_LOG_DEBUG(("Accelerate cipher %p with accelerator %s",
128 SILC_LOG_ERROR(("Accelerator '%s' does not support cipher acceleration ",
133 if (silc_acc_get_cipher(NULL, cipher)) {
134 SILC_LOG_DEBUG(("Cipher %p is already accelerated", cipher));
138 /* Check that accelerator supports this cipher algorithm */
139 alg = cipher->cipher;
140 for (i = 0; acc->cipher[i].alg_name; i++) {
141 if ((!strcmp(acc->cipher[i].alg_name, alg->alg_name) ||
142 !strcmp(acc->cipher[i].alg_name, "any")) &&
143 (acc->cipher[i].mode == alg->mode ||
144 acc->cipher[i].mode == 0) &&
145 (acc->cipher[i].key_len == alg->key_len ||
146 acc->cipher[i].key_len == 0)) {
152 SILC_LOG_DEBUG(("Accelerator %s does not support %s (mode %d) "
153 "acceleration", acc->name, alg->name, alg->mode));
157 /* Allocate cipher context for the SILC Cipher API */
158 c = silc_calloc(1, sizeof(*c));
162 /* Allocate cipher operations */
163 c->cipher = silc_calloc(1, sizeof(SilcCipherObject));
168 *c->cipher = silc_acc_ciph;
170 /* Allocate cipher context */
171 c->context = acc_cipher = silc_calloc(1, sizeof(*acc_cipher));
173 silc_free(c->cipher);
177 acc_cipher->cipher = cipher;
179 /* Allocate the actual algorithm accelerator. */
180 acc_cipher->acc_cipher = silc_calloc(1, sizeof(*acc_cipher->acc_cipher));
181 if (!acc_cipher->acc_cipher) {
182 silc_free(c->cipher);
184 silc_free(acc_cipher);
187 /* Initialize the algorithm accelerator */
188 acc_cipher->acc_cipher->context =
189 acc->cipher[i].init((struct SilcCipherObjectStruct *)&acc->cipher[i]);
190 if (!acc_cipher->acc_cipher->context) {
191 silc_free(c->cipher);
193 silc_free(acc_cipher->acc_cipher);
194 silc_free(acc_cipher);
198 /* Allocate algorithm accelerator operations */
199 acc_cipher->acc_cipher->cipher = silc_calloc(1, sizeof(SilcCipherObject));
200 if (!acc_cipher->acc_cipher->cipher) {
201 silc_free(c->cipher);
203 silc_free(acc_cipher->acc_cipher->context);
204 silc_free(acc_cipher->acc_cipher);
205 silc_free(acc_cipher);
209 /* Set algorithm accelerator operations. They are copied from the
210 accelerator, but algorithm specific things come from associated
211 cipher. This way accelerators get the associated cipher details. */
212 *acc_cipher->acc_cipher->cipher = acc->cipher[i];
213 acc_cipher->acc_cipher->cipher->alg_name =
214 (char *)silc_cipher_get_alg_name(cipher);
215 acc_cipher->acc_cipher->cipher->key_len = silc_cipher_get_key_len(cipher);
216 acc_cipher->acc_cipher->cipher->block_len =
217 silc_cipher_get_block_len(cipher);
218 acc_cipher->acc_cipher->cipher->iv_len = silc_cipher_get_iv_len(cipher);
220 /* Set for the accelerator cipher too */
221 c->cipher->key_len = silc_cipher_get_key_len(cipher);
222 c->cipher->block_len = silc_cipher_get_block_len(cipher);
223 c->cipher->iv_len = silc_cipher_get_iv_len(cipher);
225 /* Start the accelerator. The accelerator is started by setting key
227 if (!silc_cipher_set_key(acc_cipher->acc_cipher, NULL, 0, FALSE)) {
228 SilcCipherObject *ops = acc_cipher->acc_cipher->cipher;
229 silc_cipher_free(acc_cipher->acc_cipher);
231 silc_free(c->cipher);
236 SILC_LOG_DEBUG(("New accelerated cipher %p", c));
241 /* Return underlaying cipher from accelerated cipher. */
243 SilcCipher silc_acc_get_cipher(SilcAccelerator acc, SilcCipher cipher)
245 SilcAcceleratorCipher acc_cipher;
247 if (!cipher || cipher->cipher != &silc_acc_ciph)
250 acc_cipher = cipher->context;
252 return acc_cipher->cipher;