Fixed debug messages. Fixed softacc uninit.
[silc.git] / lib / silcacc / silcacc_pkcs.c
1 /*
2
3   silcacc_pkcs.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2007 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 #include "silc.h"
21
22 /************************** Types and definitions ***************************/
23
24 #define SILC_ACC_KEY_MAGIC 0xfde09137
25
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);
45
46 /* Accelerator public key */
47 typedef struct {
48   SilcUInt32 magic;
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;
54
55 /* Accelerator private key */
56 typedef struct {
57   SilcUInt32 magic;
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;
63
64 /*************************** Accelerator PKCS API ***************************/
65
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. */
69
70 const SilcPKCSObject silc_acc_pkcs =
71 {
72   SILC_PKCS_SILC,
73
74   /* Wrappers */
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,
90
91   /* Accelerated */
92   silc_acc_pkcs_encrypt,
93   silc_acc_pkcs_decrypt,
94   silc_acc_pkcs_sign,
95   silc_acc_pkcs_verify
96 };
97
98 SILC_PKCS_GET_ALGORITHM(silc_acc_pkcs_get_algorithm)
99 {
100   SilcAcceleratorPublicKey pub = public_key;
101   return pub->accelerated->pkcs->get_algorithm(pub->accelerated->pkcs,
102                                                pub->accelerated->public_key);
103 }
104
105 SILC_PKCS_IMPORT_PUBLIC_KEY_FILE(silc_acc_pkcs_import_public_key_file)
106 {
107   /* Not implemented */
108   return FALSE;
109 }
110
111 SILC_PKCS_IMPORT_PUBLIC_KEY(silc_acc_pkcs_import_public_key)
112 {
113   /* Not implemented */
114   return FALSE;
115 }
116
117 SILC_PKCS_EXPORT_PUBLIC_KEY_FILE(silc_acc_pkcs_export_public_key_file)
118 {
119   SilcAcceleratorPublicKey pub = public_key;
120   return pub->accelerated->pkcs->
121     export_public_key_file(pub->accelerated->pkcs, NULL,
122                            pub->accelerated->public_key,
123                            encoding, ret_len);
124 }
125
126 SILC_PKCS_EXPORT_PUBLIC_KEY(silc_acc_pkcs_export_public_key)
127 {
128   SilcAcceleratorPublicKey pub = public_key;
129   return pub->accelerated->pkcs->export_public_key(pub->accelerated->pkcs,
130                                                    NULL,
131                                                    pub->accelerated->public_key,
132                                                    ret_len);
133 }
134
135 SILC_PKCS_PUBLIC_KEY_BITLEN(silc_acc_pkcs_public_key_bitlen)
136 {
137   SilcAcceleratorPublicKey pub = public_key;
138   return pub->accelerated->pkcs->
139     public_key_bitlen(pub->accelerated->pkcs,
140                       pub->accelerated->public_key);
141 }
142
143 SILC_PKCS_PUBLIC_KEY_COPY(silc_acc_pkcs_public_key_copy)
144 {
145   SilcAcceleratorPublicKey pub = public_key;
146   return pub->accelerated->pkcs->public_key_copy(pub->accelerated->pkcs,
147                                                  pub->accelerated->public_key);
148 }
149
150 SILC_PKCS_PUBLIC_KEY_COMPARE(silc_acc_pkcs_public_key_compare)
151 {
152   SilcAcceleratorPublicKey pub;
153
154   pub = key2;
155   if (pub->magic == SILC_ACC_KEY_MAGIC)
156     key2 = pub->accelerated->public_key;
157
158   pub = key1;
159
160   return pub->accelerated->pkcs->
161     public_key_compare(pub->accelerated->pkcs,
162                        pub->accelerated->public_key, key2);
163 }
164
165 SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_acc_pkcs_import_private_key_file)
166 {
167   /* Not implemented */
168   return FALSE;
169 }
170
171 SILC_PKCS_IMPORT_PRIVATE_KEY(silc_acc_pkcs_import_private_key)
172 {
173   /* Not implemented */
174   return FALSE;
175 }
176
177 SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_acc_pkcs_export_private_key_file)
178 {
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);
184 }
185
186 SILC_PKCS_EXPORT_PRIVATE_KEY(silc_acc_pkcs_export_private_key)
187 {
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);
192 }
193
194 SILC_PKCS_PRIVATE_KEY_BITLEN(silc_acc_pkcs_private_key_bitlen)
195 {
196   SilcAcceleratorPrivateKey prv = private_key;
197   return prv->accelerated->pkcs->
198     private_key_bitlen(prv->accelerated->pkcs,
199                        prv->accelerated->private_key);
200 }
201
202 /* Accelerator routines follow */
203
204 SILC_PKCS_PUBLIC_KEY_FREE(silc_acc_pkcs_public_key_free)
205 {
206   SilcAcceleratorPublicKey pub = public_key;
207   pub->acc->pkcs[pub->pkcs_index].
208     public_key_free(&pub->acc->pkcs[pub->pkcs_index], pub->context);
209 }
210
211 SILC_PKCS_PRIVATE_KEY_FREE(silc_acc_pkcs_private_key_free)
212 {
213   SilcAcceleratorPrivateKey prv = private_key;
214   prv->acc->pkcs[prv->pkcs_index].
215     private_key_free(&prv->acc->pkcs[prv->pkcs_index], prv->context);
216 }
217
218 SILC_PKCS_ENCRYPT(silc_acc_pkcs_encrypt)
219 {
220   SilcAcceleratorPublicKey pub = public_key;
221
222   /* Accelerate */
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);
226 }
227
228 SILC_PKCS_DECRYPT(silc_acc_pkcs_decrypt)
229 {
230   SilcAcceleratorPrivateKey prv = private_key;
231
232   /* Accelerate */
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);
236 }
237
238 SILC_PKCS_SIGN(silc_acc_pkcs_sign)
239 {
240   SilcAcceleratorPrivateKey prv = private_key;
241
242   /* Accelerate */
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);
246 }
247
248 SILC_PKCS_VERIFY(silc_acc_pkcs_verify)
249 {
250   SilcAcceleratorPublicKey pub = public_key;
251
252   /* Accelerate */
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,
256                        verify_cb, context);
257 }
258
259 /*************************** SILC Accelerator API ***************************/
260
261 /* Accelerate public key */
262
263 SilcPublicKey silc_acc_public_key(SilcAccelerator acc,
264                                   SilcPublicKey public_key)
265 {
266   SilcPublicKey pubkey;
267   SilcAcceleratorPublicKey acc_pubkey;
268   const SilcPKCSAlgorithm *alg;
269   int i;
270
271   if (!acc || !public_key)
272     return NULL;
273
274   SILC_LOG_DEBUG(("Accelerate public key %p with accelerator %s",
275                   public_key, acc->name));
276
277   if (!acc->pkcs) {
278     SILC_LOG_ERROR(("Accelerator '%s' does not support public key "
279                     "acceleration", acc->name));
280     return NULL;
281   }
282
283   /* Check that accelerator supports this public key algorithm */
284   alg = silc_pkcs_get_algorithm(public_key);
285   if (!alg)
286     return NULL;
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")) {
291       alg = NULL;
292       break;
293     }
294   }
295   if (alg) {
296     SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
297                     acc->name, alg->name, alg->scheme));
298     return NULL;
299   }
300
301   pubkey = silc_calloc(1, sizeof(*pubkey));
302   if (!pubkey)
303     return NULL;
304
305   /* Allocate PKCS operations */
306   pubkey->pkcs = silc_calloc(1, sizeof(*pubkey->pkcs));
307   if (!pubkey->pkcs) {
308     silc_free(pubkey);
309     return NULL;
310   }
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);
314
315   /* Allocate accelerator public key */
316   acc_pubkey = silc_calloc(1, sizeof(*acc_pubkey));
317   if (!acc_pubkey) {
318     silc_free(pubkey->pkcs);
319     silc_free(pubkey);
320     return NULL;
321   }
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;
326
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'",
331                     acc->name));
332     silc_free(acc_pubkey);
333     silc_free(pubkey->pkcs);
334     silc_free(pubkey);
335     return NULL;
336   }
337   pubkey->public_key = acc_pubkey;
338
339   SILC_LOG_DEBUG(("New accelerated public key %p", pubkey));
340
341   return pubkey;
342 }
343
344 /* Accelerate private key */
345
346 SilcPrivateKey silc_acc_private_key(SilcAccelerator acc,
347                                     SilcPrivateKey private_key)
348 {
349   SilcPrivateKey privkey;
350   SilcAcceleratorPrivateKey acc_privkey;
351   const SilcPKCSAlgorithm *alg;
352   int i;
353
354   if (!acc || !private_key)
355     return NULL;
356
357   SILC_LOG_DEBUG(("Accelerate private key %p with accelerator %s",
358                   private_key, acc->name));
359
360   if (!acc->pkcs) {
361     SILC_LOG_ERROR(("Accelerator '%s' does not support private key "
362                     "acceleration", acc->name));
363     return NULL;
364   }
365
366   /* Check that accelerator supports this private key algorithm */
367   alg = silc_pkcs_get_algorithm(private_key);
368   if (!alg)
369     return NULL;
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")) {
374       alg = NULL;
375       break;
376     }
377   }
378   if (alg) {
379     SILC_LOG_DEBUG(("Accelerator %s does not support %s/%s acceleration",
380                     acc->name, alg->name, alg->scheme));
381     return NULL;
382   }
383
384   privkey = silc_calloc(1, sizeof(*privkey));
385   if (!privkey)
386     return NULL;
387
388   /* Allocate PKCS operations */
389   privkey->pkcs = silc_calloc(1, sizeof(*privkey->pkcs));
390   if (!privkey->pkcs) {
391     silc_free(privkey);
392     return NULL;
393   }
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);
397
398   /* Allocate accelerator public key */
399   acc_privkey = silc_calloc(1, sizeof(*acc_privkey));
400   if (!acc_privkey) {
401     silc_free(privkey->pkcs);
402     silc_free(privkey);
403     return NULL;
404   }
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;
409
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'",
414                     acc->name));
415     silc_free(acc_privkey);
416     silc_free(privkey->pkcs);
417     silc_free(privkey);
418     return NULL;
419   }
420   privkey->private_key = acc_privkey;
421
422   SILC_LOG_DEBUG(("New accelerated private key %p", privkey));
423
424   return privkey;
425 }
426
427 /* Get associated public key */
428
429 SilcPublicKey silc_acc_get_public_key(SilcAccelerator acc,
430                                       SilcPublicKey public_key)
431 {
432   SilcAcceleratorPublicKey pubkey;
433
434   if (!public_key)
435     return NULL;
436
437   if (public_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
438     return NULL;
439
440   pubkey = public_key->public_key;
441
442   return pubkey->accelerated;
443 }
444
445 /* Get associated private key */
446
447 SilcPrivateKey silc_acc_get_private_key(SilcAccelerator acc,
448                                         SilcPrivateKey private_key)
449 {
450   SilcAcceleratorPrivateKey privkey;
451
452   if (!private_key)
453     return NULL;
454
455   if (private_key->pkcs->get_algorithm != silc_acc_pkcs_get_algorithm)
456     return NULL;
457
458   privkey = private_key->private_key;
459
460   return privkey->accelerated;
461 }