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(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(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(e->key.private_key, e->src, e->src_len, e->compute_hash,
212 e->hash, e->rng, silc_softacc_pkcs_data_cb, e);
215 case SILC_SOFTACC_VERIFY:
216 silc_pkcs_verify(e->key.public_key, e->src, e->src_len, e->data,
217 e->data_len, e->hash, silc_softacc_pkcs_verify_cb, e);
222 /* Accelerate public key */
224 SILC_PKCS_ALG_IMPORT_PUBLIC_KEY(silc_softacc_acc_public_key)
226 SilcSoftaccPublicKey pubkey;
229 sa = silc_global_get_var("softacc", FALSE);
230 if (!sa || !sa->schedule) {
231 SILC_LOG_ERROR(("Software accelerator not initialized"));
235 pubkey = silc_calloc(1, sizeof(*pubkey));
240 *ret_public_key = pubkey;
245 /* Accelerate private key */
247 SILC_PKCS_ALG_IMPORT_PRIVATE_KEY(silc_softacc_acc_private_key)
249 SilcSoftaccPrivateKey privkey;
252 sa = silc_global_get_var("softacc", FALSE);
253 if (!sa || !sa->schedule) {
254 SILC_LOG_ERROR(("Software accelerator not initialized"));
258 privkey = silc_calloc(1, sizeof(*privkey));
263 *ret_private_key = privkey;
268 /* Free public key */
270 SILC_PKCS_ALG_PUBLIC_KEY_FREE(silc_softacc_free_public_key)
272 silc_free(public_key);
275 /* Free private key */
277 SILC_PKCS_ALG_PRIVATE_KEY_FREE(silc_softacc_free_private_key)
279 silc_free(private_key);
282 /* Accelerated encrypt */
284 SILC_PKCS_ALG_ENCRYPT(silc_softacc_encrypt)
286 SilcSoftaccPublicKey pubkey = public_key;
291 SILC_LOG_DEBUG(("Encrypt"));
293 sa = silc_global_get_var("softacc", FALSE);
294 if (!sa || !sa->schedule) {
295 SILC_LOG_ERROR(("Software accelerator not initialized"));
296 encrypt_cb(FALSE, NULL, 0, context);
300 stack = silc_stack_alloc(2048, silc_crypto_stack());
302 e = silc_scalloc(stack, 1, sizeof(*e));
304 silc_stack_free(stack);
305 encrypt_cb(FALSE, NULL, 0, context);
309 silc_stack_push(stack, NULL);
312 e->type = SILC_SOFTACC_ENCRYPT;
313 e->src = silc_smemdup(stack, src, src_len);
314 e->src_len = src_len;
316 e->key.public_key = pubkey->key;
317 e->cb.encrypt_cb = encrypt_cb;
318 e->context = context;
319 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
322 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
323 silc_softacc_pkcs_completion, e);
328 /* Acceleted decrypt */
330 SILC_PKCS_ALG_DECRYPT(silc_softacc_decrypt)
332 SilcSoftaccPrivateKey privkey = private_key;
337 SILC_LOG_DEBUG(("Decrypt"));
339 sa = silc_global_get_var("softacc", FALSE);
340 if (!sa || !sa->schedule) {
341 SILC_LOG_ERROR(("Software accelerator not initialized"));
342 decrypt_cb(FALSE, NULL, 0, context);
346 stack = silc_stack_alloc(2048, silc_crypto_stack());
348 e = silc_scalloc(stack, 1, sizeof(*e));
350 silc_stack_free(stack);
351 decrypt_cb(FALSE, NULL, 0, context);
355 silc_stack_push(stack, NULL);
358 e->type = SILC_SOFTACC_DECRYPT;
359 e->src = silc_smemdup(stack, src, src_len);
360 e->src_len = src_len;
361 e->key.private_key = privkey->key;
362 e->cb.decrypt_cb = decrypt_cb;
363 e->context = context;
364 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
367 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
368 silc_softacc_pkcs_completion, e);
373 /* Accelerated signature */
375 SILC_PKCS_ALG_SIGN(silc_softacc_sign)
377 SilcSoftaccPrivateKey privkey = private_key;
382 SILC_LOG_DEBUG(("Sign"));
384 sa = silc_global_get_var("softacc", FALSE);
385 if (!sa || !sa->schedule) {
386 SILC_LOG_ERROR(("Software accelerator not initialized"));
387 sign_cb(FALSE, NULL, 0, context);
391 stack = silc_stack_alloc(2048, silc_crypto_stack());
393 e = silc_scalloc(stack, 1, sizeof(*e));
395 silc_stack_free(stack);
396 sign_cb(FALSE, NULL, 0, context);
400 silc_stack_push(stack, NULL);
403 e->type = SILC_SOFTACC_SIGN;
405 e->src = silc_smemdup(stack, src, src_len);
406 e->src_len = src_len;
407 e->compute_hash = compute_hash;
409 e->key.private_key = privkey->key;
410 e->cb.sign_cb = sign_cb;
411 e->context = context;
412 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
415 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
416 silc_softacc_pkcs_completion, e);
421 /* Accelerated verification */
423 SILC_PKCS_ALG_VERIFY(silc_softacc_verify)
425 SilcSoftaccPublicKey pubkey = public_key;
430 SILC_LOG_DEBUG(("Verify"));
432 sa = silc_global_get_var("softacc", FALSE);
433 if (!sa || !sa->schedule) {
434 SILC_LOG_ERROR(("Software accelerator not initialized"));
435 verify_cb(FALSE, context);
439 stack = silc_stack_alloc(2048, silc_crypto_stack());
441 e = silc_scalloc(stack, 1, sizeof(*e));
443 silc_stack_free(stack);
444 verify_cb(FALSE, context);
448 silc_stack_push(stack, NULL);
451 e->type = SILC_SOFTACC_VERIFY;
452 e->src = silc_smemdup(stack, signature, signature_len);
453 e->src_len = signature_len;
454 e->data = silc_smemdup(stack, data, data_len);
455 e->data_len = data_len;
457 e->key.public_key = pubkey->key;
458 e->cb.verify_cb = verify_cb;
459 e->context = context;
460 silc_async_init(&e->op, silc_softacc_pkcs_abort, NULL, e);
463 silc_thread_pool_run(sa->tp, TRUE, sa->schedule, silc_softacc_pkcs_thread, e,
464 silc_softacc_pkcs_completion, e);