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 /************************** 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,
256 compute_hash, hash, rng,
260 /*************************** SILC Accelerator API ***************************/
262 /* Accelerate public key */
264 SilcPublicKey silc_acc_public_key(SilcAccelerator acc,
265 SilcPublicKey public_key)
267 SilcPublicKey pubkey;
268 SilcAcceleratorPublicKey acc_pubkey;
269 const SilcPKCSAlgorithm *alg;
272 if (!acc || !public_key)
275 SILC_LOG_DEBUG(("Accelerate public key %p with accelerator %s",
276 public_key, acc->name));
279 SILC_LOG_ERROR(("Accelerator '%s' does not support public key "
280 "acceleration", acc->name));
284 if (silc_acc_get_public_key(NULL, public_key)) {
285 SILC_LOG_DEBUG(("Pubilc key %p is already accelerated", public_key));
289 /* Check that accelerator supports this public key algorithm */
290 alg = silc_pkcs_get_algorithm(public_key);
293 for (i = 0; acc->pkcs[i].name; i++) {
294 if ((!strcmp(acc->pkcs[i].name, alg->name) &&
295 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
296 !strcmp(acc->pkcs[i].name, "any")) {
302 SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
303 acc->name, alg->name, alg->scheme));
307 pubkey = silc_calloc(1, sizeof(*pubkey));
311 /* Allocate PKCS operations */
312 pubkey->pkcs = silc_calloc(1, sizeof(*pubkey->pkcs));
317 *pubkey->pkcs = silc_acc_pkcs;
318 pubkey->pkcs->type = silc_pkcs_get_type(public_key);
319 pubkey->alg = silc_pkcs_get_algorithm(public_key);
321 /* Allocate accelerator public key */
322 acc_pubkey = silc_calloc(1, sizeof(*acc_pubkey));
324 silc_free(pubkey->pkcs);
328 acc_pubkey->magic = SILC_ACC_KEY_MAGIC;
329 acc_pubkey->accelerated = public_key;
330 acc_pubkey->acc = acc;
331 acc_pubkey->pkcs_index = i;
333 /* Accelerate the public key. Returns accelerator context. */
334 if (!acc->pkcs[i].import_public_key(&acc->pkcs[i], public_key, 0,
335 &acc_pubkey->context)) {
336 SILC_LOG_DEBUG(("Error accelerating public key with accelerator '%s'",
338 silc_free(acc_pubkey);
339 silc_free(pubkey->pkcs);
343 pubkey->public_key = acc_pubkey;
345 SILC_LOG_DEBUG(("New accelerated public key %p", pubkey));
350 /* Accelerate private key */
352 SilcPrivateKey silc_acc_private_key(SilcAccelerator acc,
353 SilcPrivateKey private_key)
355 SilcPrivateKey privkey;
356 SilcAcceleratorPrivateKey acc_privkey;
357 const SilcPKCSAlgorithm *alg;
360 if (!acc || !private_key)
363 SILC_LOG_DEBUG(("Accelerate private key %p with accelerator %s",
364 private_key, acc->name));
367 SILC_LOG_ERROR(("Accelerator '%s' does not support private key "
368 "acceleration", acc->name));
372 if (silc_acc_get_private_key(NULL, private_key)) {
373 SILC_LOG_DEBUG(("Private key %p is already accelerated", private_key));
377 /* Check that accelerator supports this private key algorithm */
378 alg = silc_pkcs_get_algorithm(private_key);
381 for (i = 0; acc->pkcs[i].name; i++) {
382 if ((!strcmp(acc->pkcs[i].name, alg->name) &&
383 !strcmp(acc->pkcs[i].scheme, alg->scheme)) ||
384 !strcmp(acc->pkcs[i].name, "any")) {
390 SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
391 acc->name, alg->name, alg->scheme));
395 privkey = silc_calloc(1, sizeof(*privkey));
399 /* Allocate PKCS operations */
400 privkey->pkcs = silc_calloc(1, sizeof(*privkey->pkcs));
401 if (!privkey->pkcs) {
405 *privkey->pkcs = silc_acc_pkcs;
406 privkey->pkcs->type = silc_pkcs_get_type(private_key);
407 privkey->alg = silc_pkcs_get_algorithm(private_key);
409 /* Allocate accelerator public key */
410 acc_privkey = silc_calloc(1, sizeof(*acc_privkey));
412 silc_free(privkey->pkcs);
416 acc_privkey->magic = SILC_ACC_KEY_MAGIC;
417 acc_privkey->accelerated = private_key;
418 acc_privkey->acc = acc;
419 acc_privkey->pkcs_index = i;
421 /* Accelerate the public key. Returns accelerator context. The
422 import_public_key operation is used to accelerate the key. */
423 if (!acc->pkcs[i].import_private_key(&acc->pkcs[i], private_key, 0,
424 &acc_privkey->context)) {
425 SILC_LOG_ERROR(("Error accelerating private key with accelerator '%s'",
427 silc_free(acc_privkey);
428 silc_free(privkey->pkcs);
432 privkey->private_key = acc_privkey;
434 SILC_LOG_DEBUG(("New accelerated private key %p", privkey));
439 /* Get associated public key */
441 SilcPublicKey silc_acc_get_public_key(SilcAccelerator acc,
442 SilcPublicKey public_key)
444 SilcAcceleratorPublicKey pubkey;
449 if (public_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
452 pubkey = public_key->public_key;
454 return pubkey->accelerated;
457 /* Get associated private key */
459 SilcPrivateKey silc_acc_get_private_key(SilcAccelerator acc,
460 SilcPrivateKey private_key)
462 SilcAcceleratorPrivateKey privkey;
467 if (private_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
470 privkey = private_key->private_key;
472 return privkey->accelerated;