5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2007 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.
22 /************************** Types and definitions ***************************/
24 #define SILC_ACC_KEY_MAGIC 0xfde09137
26 SILC_PKCS_GET_ALGORITHM(silc_acc_pkcs_get_algorithm);
27 SILC_PKCS_IMPORT_PUBLIC_KEY_FILE(silc_acc_pkcs_import_public_key_file);
28 SILC_PKCS_IMPORT_PUBLIC_KEY(silc_acc_pkcs_import_public_key);
29 SILC_PKCS_EXPORT_PUBLIC_KEY_FILE(silc_acc_pkcs_export_public_key_file);
30 SILC_PKCS_EXPORT_PUBLIC_KEY(silc_acc_pkcs_export_public_key);
31 SILC_PKCS_PUBLIC_KEY_BITLEN(silc_acc_pkcs_public_key_bitlen);
32 SILC_PKCS_PUBLIC_KEY_COPY(silc_acc_pkcs_public_key_copy);
33 SILC_PKCS_PUBLIC_KEY_COMPARE(silc_acc_pkcs_public_key_compare);
34 SILC_PKCS_PUBLIC_KEY_FREE(silc_acc_pkcs_public_key_free);
35 SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_acc_pkcs_import_private_key_file);
36 SILC_PKCS_IMPORT_PRIVATE_KEY(silc_acc_pkcs_import_private_key);
37 SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_acc_pkcs_export_private_key_file);
38 SILC_PKCS_EXPORT_PRIVATE_KEY(silc_acc_pkcs_export_private_key);
39 SILC_PKCS_PRIVATE_KEY_BITLEN(silc_acc_pkcs_private_key_bitlen);
40 SILC_PKCS_PRIVATE_KEY_FREE(silc_acc_pkcs_private_key_free);
41 SILC_PKCS_ENCRYPT(silc_acc_pkcs_encrypt);
42 SILC_PKCS_DECRYPT(silc_acc_pkcs_decrypt);
43 SILC_PKCS_SIGN(silc_acc_pkcs_sign);
44 SILC_PKCS_VERIFY(silc_acc_pkcs_verify);
46 /* Accelerator public key */
49 int pkcs_index; /* Accelerator PKCS index */
50 SilcAccelerator acc; /* The accelerator */
51 void *context; /* Accelerator context */
52 SilcPublicKey accelerated; /* Associated public key */
53 } *SilcAcceleratorPublicKey;
55 /* Accelerator private key */
58 int pkcs_index; /* Accelerator PKCS index */
59 SilcAccelerator acc; /* The accelerator */
60 void *context; /* Accelerator context */
61 SilcPrivateKey accelerated; /* Associated private key */
62 } *SilcAcceleratorPrivateKey;
64 /*************************** Accelerator PKCS API ***************************/
66 /* The PKCS API for the accelerated public key and private key is simply
67 a wrapper for the underlaying key. Encrypt, decrypt, sign and verify
68 operations are accelerated by calling the accelerator operations. */
70 const SilcPKCSObject silc_acc_pkcs =
75 silc_acc_pkcs_get_algorithm,
76 silc_acc_pkcs_import_public_key_file,
77 silc_acc_pkcs_import_public_key,
78 silc_acc_pkcs_export_public_key_file,
79 silc_acc_pkcs_export_public_key,
80 silc_acc_pkcs_public_key_bitlen,
81 silc_acc_pkcs_public_key_copy,
82 silc_acc_pkcs_public_key_compare,
83 silc_acc_pkcs_public_key_free,
84 silc_acc_pkcs_import_private_key_file,
85 silc_acc_pkcs_import_private_key,
86 silc_acc_pkcs_export_private_key_file,
87 silc_acc_pkcs_export_private_key,
88 silc_acc_pkcs_private_key_bitlen,
89 silc_acc_pkcs_private_key_free,
92 silc_acc_pkcs_encrypt,
93 silc_acc_pkcs_decrypt,
98 SILC_PKCS_GET_ALGORITHM(silc_acc_pkcs_get_algorithm)
100 SilcAcceleratorPublicKey pub = public_key;
101 return pub->accelerated->pkcs->get_algorithm(pub->accelerated->pkcs,
102 pub->accelerated->public_key);
105 SILC_PKCS_IMPORT_PUBLIC_KEY_FILE(silc_acc_pkcs_import_public_key_file)
107 /* Not implemented */
111 SILC_PKCS_IMPORT_PUBLIC_KEY(silc_acc_pkcs_import_public_key)
113 /* Not implemented */
117 SILC_PKCS_EXPORT_PUBLIC_KEY_FILE(silc_acc_pkcs_export_public_key_file)
119 SilcAcceleratorPublicKey pub = public_key;
120 return pub->accelerated->pkcs->
121 export_public_key_file(pub->accelerated->pkcs, NULL,
122 pub->accelerated->public_key,
126 SILC_PKCS_EXPORT_PUBLIC_KEY(silc_acc_pkcs_export_public_key)
128 SilcAcceleratorPublicKey pub = public_key;
129 return pub->accelerated->pkcs->export_public_key(pub->accelerated->pkcs,
131 pub->accelerated->public_key,
135 SILC_PKCS_PUBLIC_KEY_BITLEN(silc_acc_pkcs_public_key_bitlen)
137 SilcAcceleratorPublicKey pub = public_key;
138 return pub->accelerated->pkcs->
139 public_key_bitlen(pub->accelerated->pkcs,
140 pub->accelerated->public_key);
143 SILC_PKCS_PUBLIC_KEY_COPY(silc_acc_pkcs_public_key_copy)
145 SilcAcceleratorPublicKey pub = public_key;
146 return pub->accelerated->pkcs->public_key_copy(pub->accelerated->pkcs,
147 pub->accelerated->public_key);
150 SILC_PKCS_PUBLIC_KEY_COMPARE(silc_acc_pkcs_public_key_compare)
152 SilcAcceleratorPublicKey pub;
155 if (pub->magic == SILC_ACC_KEY_MAGIC)
156 key2 = pub->accelerated->public_key;
160 return pub->accelerated->pkcs->
161 public_key_compare(pub->accelerated->pkcs,
162 pub->accelerated->public_key, key2);
165 SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_acc_pkcs_import_private_key_file)
167 /* Not implemented */
171 SILC_PKCS_IMPORT_PRIVATE_KEY(silc_acc_pkcs_import_private_key)
173 /* Not implemented */
177 SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_acc_pkcs_export_private_key_file)
179 SilcAcceleratorPrivateKey prv = private_key;
180 return prv->accelerated->pkcs->
181 export_private_key_file(prv->accelerated->pkcs, stack,
182 prv->accelerated->private_key, passphrase,
183 passphrase_len, encoding, rng, ret_len);
186 SILC_PKCS_EXPORT_PRIVATE_KEY(silc_acc_pkcs_export_private_key)
188 SilcAcceleratorPrivateKey prv = private_key;
189 return prv->accelerated->pkcs->
190 export_private_key(prv->accelerated->pkcs, stack,
191 prv->accelerated->private_key, ret_len);
194 SILC_PKCS_PRIVATE_KEY_BITLEN(silc_acc_pkcs_private_key_bitlen)
196 SilcAcceleratorPrivateKey prv = private_key;
197 return prv->accelerated->pkcs->
198 private_key_bitlen(prv->accelerated->pkcs,
199 prv->accelerated->private_key);
202 /* Accelerator routines follow */
204 SILC_PKCS_PUBLIC_KEY_FREE(silc_acc_pkcs_public_key_free)
206 SilcAcceleratorPublicKey pub = public_key;
207 pub->acc->pkcs[pub->pkcs_index].
208 public_key_free(&pub->acc->pkcs[pub->pkcs_index], pub->context);
211 SILC_PKCS_PRIVATE_KEY_FREE(silc_acc_pkcs_private_key_free)
213 SilcAcceleratorPrivateKey prv = private_key;
214 prv->acc->pkcs[prv->pkcs_index].
215 private_key_free(&prv->acc->pkcs[prv->pkcs_index], prv->context);
218 SILC_PKCS_ENCRYPT(silc_acc_pkcs_encrypt)
220 SilcAcceleratorPublicKey pub = public_key;
223 return pub->acc->pkcs[pub->pkcs_index].encrypt(
224 &pub->acc->pkcs[pub->pkcs_index], pub->context, src,
225 src_len, rng, encrypt_cb, context);
228 SILC_PKCS_DECRYPT(silc_acc_pkcs_decrypt)
230 SilcAcceleratorPrivateKey prv = private_key;
233 return prv->acc->pkcs[prv->pkcs_index].decrypt(
234 &prv->acc->pkcs[prv->pkcs_index], prv->context, src,
235 src_len, decrypt_cb, context);
238 SILC_PKCS_SIGN(silc_acc_pkcs_sign)
240 SilcAcceleratorPrivateKey prv = private_key;
243 return prv->acc->pkcs[prv->pkcs_index].sign(
244 &prv->acc->pkcs[prv->pkcs_index], prv->context, src,
245 src_len, compute_hash, hash, rng, sign_cb, context);
248 SILC_PKCS_VERIFY(silc_acc_pkcs_verify)
250 SilcAcceleratorPublicKey pub = public_key;
253 return pub->acc->pkcs[pub->pkcs_index].verify(
254 &pub->acc->pkcs[pub->pkcs_index], pub->context,
255 signature, signature_len, data, data_len, hash, rng,
259 /*************************** SILC Accelerator API ***************************/
261 /* Accelerate public key */
263 SilcPublicKey silc_acc_public_key(SilcAccelerator acc,
264 SilcPublicKey public_key)
266 SilcPublicKey pubkey;
267 SilcAcceleratorPublicKey acc_pubkey;
268 const SilcPKCSAlgorithm *alg;
271 if (!acc || !public_key)
274 SILC_LOG_DEBUG(("Accelerate public key %p with accelerator %s",
275 public_key, acc->name));
278 SILC_LOG_ERROR(("Accelerator '%s' does not support public key "
279 "acceleration", acc->name));
283 if (silc_acc_get_public_key(NULL, public_key)) {
284 SILC_LOG_DEBUG(("Pubilc key %p is already accelerated", public_key));
288 /* Check that accelerator supports this public key algorithm */
289 alg = silc_pkcs_get_algorithm(public_key);
292 for (i = 0; acc->pkcs[i].name; i++) {
293 if ((!strcmp(acc->pkcs[i].name, alg->name) &&
294 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
295 !strcmp(acc->pkcs[i].name, "any")) {
301 SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
302 acc->name, alg->name, alg->scheme));
306 pubkey = silc_calloc(1, sizeof(*pubkey));
310 /* Allocate PKCS operations */
311 pubkey->pkcs = silc_calloc(1, sizeof(*pubkey->pkcs));
316 *pubkey->pkcs = silc_acc_pkcs;
317 pubkey->pkcs->type = silc_pkcs_get_type(public_key);
318 pubkey->alg = silc_pkcs_get_algorithm(public_key);
320 /* Allocate accelerator public key */
321 acc_pubkey = silc_calloc(1, sizeof(*acc_pubkey));
323 silc_free(pubkey->pkcs);
327 acc_pubkey->magic = SILC_ACC_KEY_MAGIC;
328 acc_pubkey->accelerated = public_key;
329 acc_pubkey->acc = acc;
330 acc_pubkey->pkcs_index = i;
332 /* Accelerate the public key. Returns accelerator context. */
333 if (!acc->pkcs[i].import_public_key(&acc->pkcs[i], public_key, 0,
334 &acc_pubkey->context)) {
335 SILC_LOG_ERROR(("Error accelerating public key with accelerator '%s'",
337 silc_free(acc_pubkey);
338 silc_free(pubkey->pkcs);
342 pubkey->public_key = acc_pubkey;
344 SILC_LOG_DEBUG(("New accelerated public key %p", pubkey));
349 /* Accelerate private key */
351 SilcPrivateKey silc_acc_private_key(SilcAccelerator acc,
352 SilcPrivateKey private_key)
354 SilcPrivateKey privkey;
355 SilcAcceleratorPrivateKey acc_privkey;
356 const SilcPKCSAlgorithm *alg;
359 if (!acc || !private_key)
362 SILC_LOG_DEBUG(("Accelerate private key %p with accelerator %s",
363 private_key, acc->name));
366 SILC_LOG_ERROR(("Accelerator '%s' does not support private key "
367 "acceleration", acc->name));
371 if (silc_acc_get_private_key(NULL, private_key)) {
372 SILC_LOG_DEBUG(("Private key %p is already accelerated", private_key));
376 /* Check that accelerator supports this private key algorithm */
377 alg = silc_pkcs_get_algorithm(private_key);
380 for (i = 0; acc->pkcs[i].name; i++) {
381 if ((!strcmp(acc->pkcs[i].name, alg->name) &&
382 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
383 !strcmp(acc->pkcs[i].name, "any")) {
389 SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
390 acc->name, alg->name, alg->scheme));
394 privkey = silc_calloc(1, sizeof(*privkey));
398 /* Allocate PKCS operations */
399 privkey->pkcs = silc_calloc(1, sizeof(*privkey->pkcs));
400 if (!privkey->pkcs) {
404 *privkey->pkcs = silc_acc_pkcs;
405 privkey->pkcs->type = silc_pkcs_get_type(private_key);
406 privkey->alg = silc_pkcs_get_algorithm(private_key);
408 /* Allocate accelerator public key */
409 acc_privkey = silc_calloc(1, sizeof(*acc_privkey));
411 silc_free(privkey->pkcs);
415 acc_privkey->magic = SILC_ACC_KEY_MAGIC;
416 acc_privkey->accelerated = private_key;
417 acc_privkey->acc = acc;
418 acc_privkey->pkcs_index = i;
420 /* Accelerate the public key. Returns accelerator context. */
421 if (!acc->pkcs[i].import_private_key(&acc->pkcs[i], private_key, 0,
422 &acc_privkey->context)) {
423 SILC_LOG_ERROR(("Error accelerating private key with accelerator '%s'",
425 silc_free(acc_privkey);
426 silc_free(privkey->pkcs);
430 privkey->private_key = acc_privkey;
432 SILC_LOG_DEBUG(("New accelerated private key %p", privkey));
437 /* Get associated public key */
439 SilcPublicKey silc_acc_get_public_key(SilcAccelerator acc,
440 SilcPublicKey public_key)
442 SilcAcceleratorPublicKey pubkey;
447 if (public_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
450 pubkey = public_key->public_key;
452 return pubkey->accelerated;
455 /* Get associated private key */
457 SilcPrivateKey silc_acc_get_private_key(SilcAccelerator acc,
458 SilcPrivateKey private_key)
460 SilcAcceleratorPrivateKey privkey;
465 if (private_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
468 privkey = private_key->private_key;
470 return privkey->accelerated;