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, 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,
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 /* Check that accelerator supports this public key algorithm */
284 alg = silc_pkcs_get_algorithm(public_key);
287 for (i = 0; acc->pkcs[i].name; i++) {
288 if ((!strcmp(acc->pkcs[i].name, alg->name) &&
289 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
290 !strcmp(acc->pkcs[i].name, "any")) {
296 SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
297 acc->name, alg->name, alg->scheme));
301 pubkey = silc_calloc(1, sizeof(*pubkey));
305 /* Allocate PKCS operations */
306 pubkey->pkcs = silc_calloc(1, sizeof(*pubkey->pkcs));
311 *pubkey->pkcs = silc_acc_pkcs;
312 pubkey->pkcs->type = silc_pkcs_get_type(public_key);
313 pubkey->alg = silc_pkcs_get_algorithm(public_key);
315 /* Allocate accelerator public key */
316 acc_pubkey = silc_calloc(1, sizeof(*acc_pubkey));
318 silc_free(pubkey->pkcs);
322 acc_pubkey->magic = SILC_ACC_KEY_MAGIC;
323 acc_pubkey->accelerated = public_key;
324 acc_pubkey->acc = acc;
325 acc_pubkey->pkcs_index = i;
327 /* Accelerate the public key. Returns accelerator context. */
328 if (!acc->pkcs->import_public_key(&acc->pkcs[i], public_key, 0,
329 &acc_pubkey->context)) {
330 SILC_LOG_ERROR(("Error accelerating public key with accelerator '%s'",
332 silc_free(acc_pubkey);
333 silc_free(pubkey->pkcs);
337 pubkey->public_key = acc_pubkey;
339 SILC_LOG_DEBUG(("New accelerated public key %p", pubkey));
344 /* Accelerate private key */
346 SilcPrivateKey silc_acc_private_key(SilcAccelerator acc,
347 SilcPrivateKey private_key)
349 SilcPrivateKey privkey;
350 SilcAcceleratorPrivateKey acc_privkey;
351 const SilcPKCSAlgorithm *alg;
354 if (!acc || !private_key)
357 SILC_LOG_DEBUG(("Accelerate private key %p with accelerator %s",
358 private_key, acc->name));
361 SILC_LOG_ERROR(("Accelerator '%s' does not support private key "
362 "acceleration", acc->name));
366 /* Check that accelerator supports this private key algorithm */
367 alg = silc_pkcs_get_algorithm(private_key);
370 for (i = 0; acc->pkcs[i].name; i++) {
371 if ((!strcmp(acc->pkcs[i].name, alg->name) &&
372 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
373 !strcmp(acc->pkcs[i].name, "any")) {
379 SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
380 acc->name, alg->name, alg->scheme));
384 privkey = silc_calloc(1, sizeof(*privkey));
388 /* Allocate PKCS operations */
389 privkey->pkcs = silc_calloc(1, sizeof(*privkey->pkcs));
390 if (!privkey->pkcs) {
394 *privkey->pkcs = silc_acc_pkcs;
395 privkey->pkcs->type = silc_pkcs_get_type(private_key);
396 privkey->alg = silc_pkcs_get_algorithm(private_key);
398 /* Allocate accelerator public key */
399 acc_privkey = silc_calloc(1, sizeof(*acc_privkey));
401 silc_free(privkey->pkcs);
405 acc_privkey->magic = SILC_ACC_KEY_MAGIC;
406 acc_privkey->accelerated = private_key;
407 acc_privkey->acc = acc;
408 acc_privkey->pkcs_index = i;
410 /* Accelerate the public key. Returns accelerator context. */
411 if (!acc->pkcs->import_private_key(&acc->pkcs[i], private_key, 0,
412 &acc_privkey->context)) {
413 SILC_LOG_ERROR(("Error accelerating private key with accelerator '%s'",
415 silc_free(acc_privkey);
416 silc_free(privkey->pkcs);
420 privkey->private_key = acc_privkey;
422 SILC_LOG_DEBUG(("New accelerated private key %p", privkey));
427 /* Get associated public key */
429 SilcPublicKey silc_acc_get_public_key(SilcAccelerator acc,
430 SilcPublicKey public_key)
432 SilcAcceleratorPublicKey pubkey;
437 if (public_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
440 pubkey = public_key->public_key;
442 return pubkey->accelerated;
445 /* Get associated private key */
447 SilcPrivateKey silc_acc_get_private_key(SilcAccelerator acc,
448 SilcPrivateKey private_key)
450 SilcAcceleratorPrivateKey privkey;
455 if (private_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
458 privkey = private_key->private_key;
460 return privkey->accelerated;