5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2007 - 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 #include "softacc_i.h"
24 /* The public and private key accelerator. We perform the public key and
25 private key operations in threads. Threads are run in the thread pool. */
27 /************************** Types and definitions ***************************/
29 /* Software accelerator PKCS algorithm operations */
30 const SilcPKCSAlgorithm softacc_pkcs[] =
33 "any", "any", NULL, NULL,
34 silc_softacc_acc_public_key,
35 NULL, NULL, NULL, NULL,
36 silc_softacc_free_public_key,
37 silc_softacc_acc_private_key,
39 silc_softacc_free_private_key,
47 NULL, NULL, NULL, NULL,
48 NULL, NULL, NULL, NULL,
49 NULL, NULL, NULL, NULL,
54 /* Software accelerator public key */
56 SilcPublicKey key; /* Accelerated public key */
57 } *SilcSoftaccPublicKey;
59 /* Software accelerator private key */
61 SilcPrivateKey key; /* Accelerated private key */
62 } *SilcSoftaccPrivateKey;
72 /* Executor context */
74 SilcStack stack; /* Executor stack */
75 void *context; /* Callback context */
76 SilcSoftaccType type; /* Execution type */
77 SilcAsyncOperationStruct op; /* Operation for aborting */
79 unsigned char *src; /* Source data */
80 unsigned char *data; /* More source data */
83 SilcHash hash; /* Hash function to use */
84 SilcRng rng; /* RNG, may be NULL */
87 SilcPublicKey public_key;
88 SilcPrivateKey private_key;
92 SilcPKCSEncryptCb encrypt_cb;
93 SilcPKCSDecryptCb decrypt_cb;
94 SilcPKCSSignCb sign_cb;
95 SilcPKCSVerifyCb verify_cb;
98 unsigned char *result_data;
99 SilcUInt32 result_len;
101 unsigned int result : 1;
102 unsigned int compute_hash : 1;
103 unsigned int aborted : 1;
106 /****************************** PKCS ALG API ********************************/
108 /* Abort operation */
110 void silc_softacc_pkcs_abort(SilcAsyncOperation op, void *context)
112 SilcSoftaccExec e = context;
116 /* Accelerator completion, executed in main thread. */
118 SILC_TASK_CALLBACK(silc_softacc_pkcs_completion)
120 SilcSoftaccExec e = context;
121 SilcStack stack = e->stack;
123 /* At the latest, abort is catched here in the main thread. Don't
124 deliver callback if we were aborted */
128 SILC_LOG_DEBUG(("Call completion, result=%s", e->result ? "Ok" : "failed"));
130 /* Call completion callback */
132 case SILC_SOFTACC_ENCRYPT:
133 e->cb.encrypt_cb(e->result, e->result_data, e->result_len, e->context);
136 case SILC_SOFTACC_DECRYPT:
137 e->cb.decrypt_cb(e->result, e->result_data, e->result_len, e->context);
140 case SILC_SOFTACC_SIGN:
141 e->cb.sign_cb(e->result, e->result_data, e->result_len, e->context);
144 case SILC_SOFTACC_VERIFY:
145 e->cb.verify_cb(e->result, e->context);
150 silc_sfree(stack, e->src);
151 silc_sfree(stack, e->data);
152 silc_sfree(stack, e->result_data);
153 silc_sfree(stack, e);
154 silc_stack_free(stack);
157 /* Callback for encrypt, decrypt and signature */
159 void silc_softacc_pkcs_data_cb(SilcBool success, const unsigned char *data,
160 SilcUInt32 data_len, void *context)
162 SilcSoftaccExec e = context;
163 SilcStack stack = e->stack;
166 silc_stack_pop(stack);
169 e->result_data = silc_smemdup(stack, data, data_len);
170 e->result_len = data_len;
174 /* Verification callback */
176 void silc_softacc_pkcs_verify_cb(SilcBool success, void *context)
178 SilcSoftaccExec e = context;
179 SilcStack stack = e->stack;
181 /* Pop e->src and e->data from memory */
182 silc_stack_pop(stack);
187 /* Accelerator thread */
189 void silc_softacc_pkcs_thread(SilcSchedule schedule, void *context)
191 SilcSoftaccExec e = context;
196 SILC_LOG_DEBUG(("Execute type %d", e->type));
198 /* Call the operation */
200 case SILC_SOFTACC_ENCRYPT:
201 silc_pkcs_encrypt_async(e->key.public_key, e->src, e->src_len, e->rng,
202 silc_softacc_pkcs_data_cb, e);
205 case SILC_SOFTACC_DECRYPT:
206 silc_pkcs_decrypt_async(e->key.private_key, e->src, e->src_len,
207 silc_softacc_pkcs_data_cb, e);
210 case SILC_SOFTACC_SIGN:
211 silc_pkcs_sign_async(e->key.private_key, e->src, e->src_len,
212 e->compute_hash, e->hash, e->rng,
213 silc_softacc_pkcs_data_cb, e);
216 case SILC_SOFTACC_VERIFY:
217 silc_pkcs_verify_async(e->key.public_key, e->src, e->src_len, e->data,
218 e->data_len, e->compute_hash, e->hash,
219 silc_softacc_pkcs_verify_cb, e);
224 /* Accelerate public key */
226 SILC_PKCS_ALG_IMPORT_PUBLIC_KEY(silc_softacc_acc_public_key)
228 SilcSoftaccPublicKey pubkey;
231 sa = silc_global_get_var("softacc", FALSE);
232 if (!sa || !sa->schedule) {
233 SILC_LOG_ERROR(("Software accelerator not initialized"));
237 pubkey = silc_calloc(1, sizeof(*pubkey));
242 *ret_public_key = pubkey;
247 /* Accelerate private key */
249 SILC_PKCS_ALG_IMPORT_PRIVATE_KEY(silc_softacc_acc_private_key)
251 SilcSoftaccPrivateKey privkey;
254 sa = silc_global_get_var("softacc", FALSE);
255 if (!sa || !sa->schedule) {
256 SILC_LOG_ERROR(("Software accelerator not initialized"));
260 privkey = silc_calloc(1, sizeof(*privkey));
265 *ret_private_key = privkey;
270 /* Free public key */
272 SILC_PKCS_ALG_PUBLIC_KEY_FREE(silc_softacc_free_public_key)
274 silc_free(public_key);
277 /* Free private key */
279 SILC_PKCS_ALG_PRIVATE_KEY_FREE(silc_softacc_free_private_key)
281 silc_free(private_key);
284 /* Accelerated encrypt */
286 SILC_PKCS_ALG_ENCRYPT(silc_softacc_encrypt)
288 SilcSoftaccPublicKey pubkey = public_key;
293 SILC_LOG_DEBUG(("Encrypt"));
295 sa = silc_global_get_var("softacc", FALSE);
296 if (!sa || !sa->schedule) {
297 SILC_LOG_ERROR(("Software accelerator not initialized"));
298 encrypt_cb(FALSE, NULL, 0, context);
302 stack = silc_stack_alloc(2048, silc_crypto_stack());
304 e = silc_scalloc(stack, 1, sizeof(*e));
306 silc_stack_free(stack);
307 encrypt_cb(FALSE, NULL, 0, context);
311 silc_stack_push(stack, NULL);
314 e->type = SILC_SOFTACC_ENCRYPT;
315 e->src = silc_smemdup(stack, src, src_len);
316 e->src_len = src_len;
318 e->key.public_key = pubkey->key;
319 e->cb.encrypt_cb = encrypt_cb;
320 e->context = context;
321 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
324 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
325 silc_softacc_pkcs_completion, e);
330 /* Acceleted decrypt */
332 SILC_PKCS_ALG_DECRYPT(silc_softacc_decrypt)
334 SilcSoftaccPrivateKey privkey = private_key;
339 SILC_LOG_DEBUG(("Decrypt"));
341 sa = silc_global_get_var("softacc", FALSE);
342 if (!sa || !sa->schedule) {
343 SILC_LOG_ERROR(("Software accelerator not initialized"));
344 decrypt_cb(FALSE, NULL, 0, context);
348 stack = silc_stack_alloc(2048, silc_crypto_stack());
350 e = silc_scalloc(stack, 1, sizeof(*e));
352 silc_stack_free(stack);
353 decrypt_cb(FALSE, NULL, 0, context);
357 silc_stack_push(stack, NULL);
360 e->type = SILC_SOFTACC_DECRYPT;
361 e->src = silc_smemdup(stack, src, src_len);
362 e->src_len = src_len;
363 e->key.private_key = privkey->key;
364 e->cb.decrypt_cb = decrypt_cb;
365 e->context = context;
366 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
369 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
370 silc_softacc_pkcs_completion, e);
375 /* Accelerated signature */
377 SILC_PKCS_ALG_SIGN(silc_softacc_sign)
379 SilcSoftaccPrivateKey privkey = private_key;
384 SILC_LOG_DEBUG(("Sign"));
386 sa = silc_global_get_var("softacc", FALSE);
387 if (!sa || !sa->schedule) {
388 SILC_LOG_ERROR(("Software accelerator not initialized"));
389 sign_cb(FALSE, NULL, 0, context);
393 stack = silc_stack_alloc(2048, silc_crypto_stack());
395 e = silc_scalloc(stack, 1, sizeof(*e));
397 silc_stack_free(stack);
398 sign_cb(FALSE, NULL, 0, context);
402 silc_stack_push(stack, NULL);
405 e->type = SILC_SOFTACC_SIGN;
407 e->src = silc_smemdup(stack, src, src_len);
408 e->src_len = src_len;
409 e->compute_hash = compute_hash;
411 e->key.private_key = privkey->key;
412 e->cb.sign_cb = sign_cb;
413 e->context = context;
414 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
417 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
418 silc_softacc_pkcs_completion, e);
423 /* Accelerated verification */
425 SILC_PKCS_ALG_VERIFY(silc_softacc_verify)
427 SilcSoftaccPublicKey pubkey = public_key;
432 SILC_LOG_DEBUG(("Verify"));
434 sa = silc_global_get_var("softacc", FALSE);
435 if (!sa || !sa->schedule) {
436 SILC_LOG_ERROR(("Software accelerator not initialized"));
437 verify_cb(FALSE, context);
441 stack = silc_stack_alloc(2048, silc_crypto_stack());
443 e = silc_scalloc(stack, 1, sizeof(*e));
445 silc_stack_free(stack);
446 verify_cb(FALSE, context);
450 silc_stack_push(stack, NULL);
453 e->type = SILC_SOFTACC_VERIFY;
454 e->src = silc_smemdup(stack, signature, signature_len);
455 e->src_len = signature_len;
456 e->data = silc_smemdup(stack, data, data_len);
457 e->data_len = data_len;
458 e->compute_hash = compute_hash;
460 e->key.public_key = pubkey->key;
461 e->cb.verify_cb = verify_cb;
462 e->context = context;
463 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
466 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
467 silc_softacc_pkcs_completion, e);