Rewrote crypto library init/uninit. Added silc_crypto_init
[silc.git] / lib / silccrypt / silcpkcs1.c
1 /*
2
3   silcpkcs1.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 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 /* $Id$ */
20
21 #include "silc.h"
22 #include "rsa.h"
23 #include "silcpkcs1_i.h"
24
25 /************************** PKCS #1 message format ***************************/
26
27 /* Minimum padding in block */
28 #define SILC_PKCS1_MIN_PADDING 8
29
30 /* Encodes PKCS#1 data block from the `data' according to the block type
31    indicated by `bt'.  When encoding signatures the `bt' must be
32    SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
33    be SILC_PKCS1_BT_PUB.  The encoded data is copied into the `dest_data'
34    buffer which is size of `dest_data_size'.  If the `dest_data' is not
35    able to hold the encoded block this returns FALSE.  The `rng' must be
36    set when `bt' is SILC_PKCS1_BT_PUB.  This function returns TRUE on
37    success. */
38
39 SilcBool silc_pkcs1_encode(SilcPkcs1BlockType bt,
40                            const unsigned char *data,
41                            SilcUInt32 data_len,
42                            unsigned char *dest_data,
43                            SilcUInt32 dest_data_size,
44                            SilcRng rng)
45 {
46   SilcInt32 padlen;
47   int i;
48
49   SILC_LOG_DEBUG(("PKCS#1 encoding, bt %d", bt));
50
51   if (!data || !dest_data ||
52       dest_data_size < SILC_PKCS1_MIN_PADDING + 3 ||
53       dest_data_size < data_len) {
54     SILC_LOG_DEBUG(("Data to be encoded is too long"));
55     return FALSE;
56   }
57
58   /* Start of block */
59   dest_data[0] = 0x00;
60   dest_data[1] = (unsigned char)bt;
61
62   padlen = (SilcInt32)dest_data_size - (SilcInt32)data_len - 3;
63   if (padlen < SILC_PKCS1_MIN_PADDING) {
64     SILC_LOG_DEBUG(("Data to be encoded is too long"));
65     return FALSE;
66   }
67
68   /* Encode according to block type */
69   switch (bt) {
70   case SILC_PKCS1_BT_PRV0:
71   case SILC_PKCS1_BT_PRV1:
72     /* Signature */
73     memset(dest_data + 2, bt == SILC_PKCS1_BT_PRV1 ? 0xff : 0x00, padlen);
74     break;
75
76   case SILC_PKCS1_BT_PUB:
77     /* Encryption */
78     if (!rng) {
79       SILC_LOG_ERROR(("Cannot encrypt: random number generator not provided"));
80       return FALSE;
81     }
82
83     /* It is guaranteed this routine does not return zero byte. */
84     for (i = 2; i < padlen; i++)
85       dest_data[i] = silc_rng_get_byte_fast(rng);
86
87     break;
88   }
89
90   /* Copy the data */
91   dest_data[padlen + 2] = 0x00;
92   memcpy(dest_data + padlen + 3, data, data_len);
93
94   return TRUE;
95 }
96
97 /* Decodes the PKCS#1 encoded block according to the block type `bt'.
98    When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
99    when decrypting it must be SILC_PKCS1_BT_PUB.  This copies the
100    decoded data into `dest_data' which is size of `dest_data_size'.  If
101    the deocded block does not fit to `dest_data' this returns FALSE.
102    Returns TRUE on success. */
103
104 SilcBool silc_pkcs1_decode(SilcPkcs1BlockType bt,
105                            const unsigned char *data,
106                            SilcUInt32 data_len,
107                            unsigned char *dest_data,
108                            SilcUInt32 dest_data_size,
109                            SilcUInt32 *dest_len)
110 {
111   int i = 0;
112
113   SILC_LOG_DEBUG(("PKCS#1 decoding, bt %d", bt));
114
115   /* Sanity checks */
116   if (!data || !dest_data || dest_data_size < 3 ||
117       data[0] != 0x00 || data[1] != (unsigned char)bt) {
118     SILC_LOG_DEBUG(("Malformed block"));
119     return FALSE;
120   }
121
122   /* Decode according to block type */
123   switch (bt) {
124   case SILC_PKCS1_BT_PRV0:
125     /* Do nothing */
126     break;
127
128   case SILC_PKCS1_BT_PRV1:
129     /* Verification */
130     for (i = 2; i < data_len; i++)
131       if (data[i] != 0xff)
132         break;
133     break;
134
135   case SILC_PKCS1_BT_PUB:
136     /* Decryption */
137     for (i = 2; i < data_len; i++)
138       if (data[i] == 0x00)
139         break;
140     break;
141   }
142
143   /* Sanity checks */
144   if (data[i++] != 0x00) {
145     SILC_LOG_DEBUG(("Malformed block"));
146     return FALSE;
147   }
148   if (i - 1 < SILC_PKCS1_MIN_PADDING) {
149     SILC_LOG_DEBUG(("Malformed block"));
150     return FALSE;
151   }
152   if (dest_data_size < data_len - i) {
153     SILC_LOG_DEBUG(("Destination buffer too small"));
154     return FALSE;
155   }
156
157   /* Copy the data */
158   memcpy(dest_data, data + i, data_len - i);
159
160   /* Return data length */
161   if (dest_len)
162     *dest_len = data_len - i;
163
164   return TRUE;
165 }
166
167
168 /***************************** PKCS #1 PKCS API ******************************/
169
170 /* Generates RSA key pair. */
171
172 SilcBool silc_pkcs1_generate_key(const struct SilcPKCSAlgorithmStruct *pkcs,
173                                  SilcUInt32 keylen,
174                                  SilcRng rng,
175                                  void **ret_public_key,
176                                  void **ret_private_key)
177 {
178   SilcUInt32 prime_bits = keylen / 2;
179   SilcMPInt p, q;
180   SilcBool found = FALSE;
181
182   if (keylen < 768 || keylen > 16384)
183     return FALSE;
184
185   silc_mp_init(&p);
186   silc_mp_init(&q);
187
188   /* Find p and q */
189   while (!found) {
190     silc_math_gen_prime(&p, prime_bits, FALSE, rng);
191     silc_math_gen_prime(&q, prime_bits, FALSE, rng);
192     if ((silc_mp_cmp(&p, &q)) != 0)
193       found = TRUE;
194   }
195
196   /* If p is smaller than q, switch them */
197   if ((silc_mp_cmp(&p, &q)) > 0) {
198     SilcMPInt hlp;
199     silc_mp_init(&hlp);
200
201     silc_mp_set(&hlp, &p);
202     silc_mp_set(&p, &q);
203     silc_mp_set(&q, &hlp);
204
205     silc_mp_uninit(&hlp);
206   }
207
208   /* Generate the actual keys */
209   if (!silc_rsa_generate_keys(keylen, &p, &q, ret_public_key, ret_private_key))
210     return FALSE;
211
212   silc_mp_uninit(&p);
213   silc_mp_uninit(&q);
214
215   return TRUE;
216 }
217
218 /* Import PKCS #1 compliant public key */
219
220 int silc_pkcs1_import_public_key(const struct SilcPKCSAlgorithmStruct *pkcs,
221                                  void *key,
222                                  SilcUInt32 key_len,
223                                  void **ret_public_key)
224 {
225   SilcAsn1 asn1 = NULL;
226   SilcBufferStruct alg_key;
227   RsaPublicKey *pubkey;
228
229   if (!ret_public_key)
230     return 0;
231
232   asn1 = silc_asn1_alloc(NULL);
233   if (!asn1)
234     return 0;
235
236   /* Allocate RSA public key */
237   *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
238   if (!pubkey)
239     goto err;
240
241   /* Parse the PKCS #1 public key */
242   silc_buffer_set(&alg_key, key, key_len);
243   if (!silc_asn1_decode(asn1, &alg_key,
244                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
245                         SILC_ASN1_SEQUENCE,
246                           SILC_ASN1_INT(&pubkey->n),
247                           SILC_ASN1_INT(&pubkey->e),
248                         SILC_ASN1_END, SILC_ASN1_END))
249     goto err;
250
251   /* Set key length */
252   pubkey->bits = ((silc_mp_sizeinbase(&pubkey->n, 2) + 7) / 8) * 8;
253
254   silc_asn1_free(asn1);
255
256   return key_len;
257
258  err:
259   silc_free(pubkey);
260   silc_asn1_free(asn1);
261   return 0;
262 }
263
264 /* Export PKCS #1 compliant public key */
265
266 unsigned char *
267 silc_pkcs1_export_public_key(const struct SilcPKCSAlgorithmStruct *pkcs,
268                              SilcStack stack,
269                              void *public_key,
270                              SilcUInt32 *ret_len)
271 {
272   RsaPublicKey *key = public_key;
273   SilcAsn1 asn1 = NULL;
274   SilcBufferStruct alg_key;
275   unsigned char *ret;
276
277   asn1 = silc_asn1_alloc(stack);
278   if (!asn1)
279     goto err;
280
281   /* Encode to PKCS #1 public key */
282   memset(&alg_key, 0, sizeof(alg_key));
283   if (!silc_asn1_encode(asn1, &alg_key,
284                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
285                         SILC_ASN1_SEQUENCE,
286                           SILC_ASN1_INT(&key->n),
287                           SILC_ASN1_INT(&key->e),
288                         SILC_ASN1_END, SILC_ASN1_END))
289     goto err;
290
291   ret = silc_buffer_steal(&alg_key, ret_len);
292   silc_asn1_free(asn1);
293
294   return ret;
295
296  err:
297   if (asn1)
298     silc_asn1_free(asn1);
299   return NULL;
300 }
301
302 /* Returns key length */
303
304 SilcUInt32
305 silc_pkcs1_public_key_bitlen(const struct SilcPKCSAlgorithmStruct *pkcs,
306                              void *public_key)
307 {
308   RsaPublicKey *key = public_key;
309   return key->bits;
310 }
311
312 /* Copy public key */
313
314 void *silc_pkcs1_public_key_copy(const struct SilcPKCSAlgorithmStruct *pkcs,
315                                  void *public_key)
316 {
317   RsaPublicKey *key = public_key, *new_key;
318
319   new_key = silc_calloc(1, sizeof(*new_key));
320   if (!new_key)
321     return NULL;
322
323   silc_mp_init(&new_key->n);
324   silc_mp_init(&new_key->e);
325   silc_mp_set(&new_key->n, &key->n);
326   silc_mp_set(&new_key->e, &key->e);
327   new_key->bits = key->bits;
328
329   return new_key;
330 }
331
332 /* Compare public keys */
333
334 SilcBool
335 silc_pkcs1_public_key_compare(const struct SilcPKCSAlgorithmStruct *pkcs,
336                               void *key1, void *key2)
337 {
338   RsaPublicKey *k1 = key1, *k2 = key2;
339
340   if (k1->bits != k2->bits)
341     return FALSE;
342   if (silc_mp_cmp(&k1->e, &k2->e) != 0)
343     return FALSE;
344   if (silc_mp_cmp(&k1->n, &k2->n) != 0)
345     return FALSE;
346
347   return TRUE;
348 }
349
350 /* Frees public key */
351
352 void silc_pkcs1_public_key_free(const struct SilcPKCSAlgorithmStruct *pkcs,
353                                 void *public_key)
354 {
355   RsaPublicKey *key = public_key;
356
357   silc_mp_uninit(&key->n);
358   silc_mp_uninit(&key->e);
359   silc_free(key);
360 }
361
362 /* Import PKCS #1 compliant private key */
363
364 int silc_pkcs1_import_private_key(const struct SilcPKCSAlgorithmStruct *pkcs,
365                                   void *key,
366                                   SilcUInt32 key_len,
367                                   void **ret_private_key)
368 {
369   SilcAsn1 asn1;
370   SilcBufferStruct alg_key;
371   RsaPrivateKey *privkey;
372   SilcUInt32 ver;
373
374   if (!ret_private_key)
375     return 0;
376
377   asn1 = silc_asn1_alloc(NULL);
378   if (!asn1)
379     return 0;
380
381   /* Allocate RSA private key */
382   *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
383   if (!privkey)
384     goto err;
385
386   /* Parse the PKCS #1 private key */
387   silc_buffer_set(&alg_key, key, key_len);
388   if (!silc_asn1_decode(asn1, &alg_key,
389                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
390                         SILC_ASN1_SEQUENCE,
391                           SILC_ASN1_SHORT_INT(&ver),
392                           SILC_ASN1_INT(&privkey->n),
393                           SILC_ASN1_INT(&privkey->e),
394                           SILC_ASN1_INT(&privkey->d),
395                           SILC_ASN1_INT(&privkey->p),
396                           SILC_ASN1_INT(&privkey->q),
397                           SILC_ASN1_INT(&privkey->dP),
398                           SILC_ASN1_INT(&privkey->dQ),
399                           SILC_ASN1_INT(&privkey->qP),
400                         SILC_ASN1_END, SILC_ASN1_END))
401     goto err;
402
403   if (ver != 0)
404     goto err;
405
406   /* Set key length */
407   privkey->bits = ((silc_mp_sizeinbase(&privkey->n, 2) + 7) / 8) * 8;
408
409   silc_asn1_free(asn1);
410
411   return key_len;
412
413  err:
414   silc_free(privkey);
415   silc_asn1_free(asn1);
416   return 0;
417 }
418
419 /* Export PKCS #1 compliant private key */
420
421 unsigned char *
422 silc_pkcs1_export_private_key(const struct SilcPKCSAlgorithmStruct *pkcs,
423                               SilcStack stack,
424                               void *private_key,
425                               SilcUInt32 *ret_len)
426 {
427   RsaPrivateKey *key = private_key;
428   SilcAsn1 asn1;
429   SilcBufferStruct alg_key;
430   unsigned char *ret;
431
432   asn1 = silc_asn1_alloc(stack);
433   if (!asn1)
434     return FALSE;
435
436   /* Encode to PKCS #1 private key */
437   memset(&alg_key, 0, sizeof(alg_key));
438   if (!silc_asn1_encode(asn1, &alg_key,
439                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
440                         SILC_ASN1_SEQUENCE,
441                           SILC_ASN1_SHORT_INT(0),
442                           SILC_ASN1_INT(&key->n),
443                           SILC_ASN1_INT(&key->e),
444                           SILC_ASN1_INT(&key->d),
445                           SILC_ASN1_INT(&key->p),
446                           SILC_ASN1_INT(&key->q),
447                           SILC_ASN1_INT(&key->dP),
448                           SILC_ASN1_INT(&key->dQ),
449                           SILC_ASN1_INT(&key->qP),
450                         SILC_ASN1_END, SILC_ASN1_END))
451     goto err;
452
453   ret = silc_buffer_steal(&alg_key, ret_len);
454   silc_asn1_free(asn1);
455
456   return ret;
457
458  err:
459   silc_asn1_free(asn1);
460   return NULL;
461 }
462
463 /* Returns key length */
464
465 SilcUInt32
466 silc_pkcs1_private_key_bitlen(const struct SilcPKCSAlgorithmStruct *pkcs,
467                               void *private_key)
468 {
469   RsaPrivateKey *key = private_key;
470   return key->bits;
471 }
472
473 /* Frees private key */
474
475 void silc_pkcs1_private_key_free(const struct SilcPKCSAlgorithmStruct *pkcs,
476                                  void *private_key)
477 {
478   RsaPrivateKey *key = private_key;
479
480   silc_mp_uninit(&key->n);
481   silc_mp_uninit(&key->e);
482   silc_mp_uninit(&key->d);
483   silc_mp_uninit(&key->dP);
484   silc_mp_uninit(&key->dQ);
485   silc_mp_uninit(&key->qP);
486   silc_mp_uninit(&key->p);
487   silc_mp_uninit(&key->q);
488   silc_free(key);
489 }
490
491 /* PKCS #1 RSA routines */
492
493 SilcAsyncOperation
494 silc_pkcs1_encrypt(const struct SilcPKCSAlgorithmStruct *pkcs,
495                    void *public_key,
496                    unsigned char *src,
497                    SilcUInt32 src_len,
498                    SilcRng rng,
499                    SilcPKCSEncryptCb encrypt_cb,
500                    void *context)
501 {
502   RsaPublicKey *key = public_key;
503   SilcMPInt mp_tmp;
504   SilcMPInt mp_dst;
505   unsigned char padded[2048 + 1];
506   SilcUInt32 len = (key->bits + 7) / 8;
507   SilcStack stack;
508
509   if (sizeof(padded) < len) {
510     encrypt_cb(FALSE, NULL, 0, context);
511     return NULL;
512   }
513
514   /* Pad data */
515   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len,
516                          padded, len, rng)) {
517     encrypt_cb(FALSE, NULL, 0, context);
518     return NULL;
519   }
520
521   stack = silc_stack_alloc(2048, silc_crypto_stack());
522
523   silc_mp_sinit(stack, &mp_tmp);
524   silc_mp_sinit(stack, &mp_dst);
525
526   /* Data to MP */
527   silc_mp_bin2mp(padded, len, &mp_tmp);
528
529   /* Encrypt */
530   silc_rsa_public_operation(key, &mp_tmp, &mp_dst);
531
532   /* MP to data */
533   silc_mp_mp2bin_noalloc(&mp_dst, padded, len);
534
535   /* Deliver result */
536   encrypt_cb(TRUE, padded, len, context);
537
538   memset(padded, 0, sizeof(padded));
539   silc_mp_suninit(stack, &mp_tmp);
540   silc_mp_suninit(stack, &mp_dst);
541   silc_stack_free(stack);
542
543   return NULL;
544 }
545
546 SilcAsyncOperation
547 silc_pkcs1_decrypt(const struct SilcPKCSAlgorithmStruct *pkcs,
548                    void *private_key,
549                    unsigned char *src,
550                    SilcUInt32 src_len,
551                    SilcPKCSDecryptCb decrypt_cb,
552                    void *context)
553 {
554   RsaPrivateKey *key = private_key;
555   SilcMPInt mp_tmp;
556   SilcMPInt mp_dst;
557   unsigned char *padded, unpadded[2048 + 1];
558   SilcUInt32 padded_len, dst_len;
559   SilcStack stack;
560
561   if (sizeof(unpadded) < (key->bits + 7) / 8) {
562     decrypt_cb(FALSE, NULL, 0, context);
563     return NULL;
564   }
565
566   stack = silc_stack_alloc(2048, silc_crypto_stack());
567
568   silc_mp_sinit(stack, &mp_tmp);
569   silc_mp_sinit(stack, &mp_dst);
570
571   /* Data to MP */
572   silc_mp_bin2mp(src, src_len, &mp_tmp);
573
574   /* Decrypt */
575   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
576
577   /* MP to data */
578   padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
579
580   /* Unpad data */
581   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len,
582                          unpadded, sizeof(unpadded), &dst_len)) {
583     memset(padded, 0, padded_len);
584     silc_free(padded);
585     silc_mp_suninit(stack, &mp_tmp);
586     silc_mp_suninit(stack, &mp_dst);
587     decrypt_cb(FALSE, NULL, 0, context);
588     return NULL;
589   }
590
591   /* Deliver result */
592   decrypt_cb(TRUE, unpadded, dst_len, context);
593
594   memset(padded, 0, padded_len);
595   memset(unpadded, 0, sizeof(unpadded));
596   silc_free(padded);
597   silc_mp_suninit(stack, &mp_tmp);
598   silc_mp_suninit(stack, &mp_dst);
599   silc_stack_free(stack);
600
601   return NULL;
602 }
603
604 /* PKCS #1 sign with appendix, hash OID included in the signature */
605
606 SilcAsyncOperation
607 silc_pkcs1_sign(const struct SilcPKCSAlgorithmStruct *pkcs,
608                 void *private_key,
609                 unsigned char *src,
610                 SilcUInt32 src_len,
611                 SilcBool compute_hash,
612                 SilcHash hash,
613                 SilcPKCSSignCb sign_cb,
614                 void *context)
615 {
616   RsaPrivateKey *key = private_key;
617   unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
618   SilcMPInt mp_tmp;
619   SilcMPInt mp_dst;
620   SilcBufferStruct di;
621   SilcUInt32 len = (key->bits + 7) / 8;
622   const char *oid;
623   SilcStack stack;
624   SilcAsn1 asn1;
625
626   SILC_LOG_DEBUG(("Sign"));
627
628   if (sizeof(padded) < len) {
629     sign_cb(FALSE, NULL, 0, context);
630     return NULL;
631   }
632
633   oid = silc_hash_get_oid(hash);
634   if (!oid) {
635     sign_cb(FALSE, NULL, 0, context);
636     return NULL;
637   }
638
639   stack = silc_stack_alloc(2048, silc_crypto_stack());
640
641   asn1 = silc_asn1_alloc(stack);
642   if (!asn1) {
643     silc_stack_free(stack);
644     sign_cb(FALSE, NULL, 0, context);
645     return NULL;
646   }
647
648   /* Compute hash */
649   if (compute_hash) {
650     silc_hash_make(hash, src, src_len, hashr);
651     src = hashr;
652     src_len = silc_hash_len(hash);
653   }
654
655   /* Encode digest info */
656   memset(&di, 0, sizeof(di));
657   if (!silc_asn1_encode(asn1, &di,
658                         SILC_ASN1_SEQUENCE,
659                           SILC_ASN1_SEQUENCE,
660                             SILC_ASN1_OID(oid),
661                             SILC_ASN1_NULL(TRUE),
662                           SILC_ASN1_END,
663                           SILC_ASN1_OCTET_STRING(src, src_len),
664                         SILC_ASN1_END, SILC_ASN1_END)) {
665     silc_asn1_free(asn1);
666     silc_stack_free(stack);
667     sign_cb(FALSE, NULL, 0, context);
668     return NULL;
669   }
670   SILC_LOG_HEXDUMP(("DigestInfo"), silc_buffer_data(&di),
671                    silc_buffer_len(&di));
672
673   /* Pad data */
674   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, silc_buffer_data(&di),
675                          silc_buffer_len(&di), padded, len, NULL)) {
676     silc_asn1_free(asn1);
677     silc_stack_free(stack);
678     sign_cb(FALSE, NULL, 0, context);
679     return NULL;
680   }
681
682   silc_mp_sinit(stack, &mp_tmp);
683   silc_mp_sinit(stack, &mp_dst);
684
685   /* Data to MP */
686   silc_mp_bin2mp(padded, len, &mp_tmp);
687
688   /* Sign */
689   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
690
691   /* MP to data */
692   silc_mp_mp2bin_noalloc(&mp_dst, padded, len);
693
694   /* Deliver result */
695   sign_cb(TRUE, padded, len, context);
696
697   memset(padded, 0, sizeof(padded));
698   if (compute_hash)
699     memset(hashr, 0, sizeof(hashr));
700   silc_mp_suninit(stack, &mp_tmp);
701   silc_mp_suninit(stack, &mp_dst);
702   silc_asn1_free(asn1);
703   silc_stack_free(stack);
704
705   return NULL;
706 }
707
708 /* PKCS #1 verification with appendix. */
709
710 SilcAsyncOperation
711 silc_pkcs1_verify(const struct SilcPKCSAlgorithmStruct *pkcs,
712                   void *public_key,
713                   unsigned char *signature,
714                   SilcUInt32 signature_len,
715                   unsigned char *data,
716                   SilcUInt32 data_len,
717                   SilcHash hash,
718                   SilcPKCSVerifyCb verify_cb,
719                   void *context)
720 {
721   RsaPublicKey *key = public_key;
722   SilcBool ret = FALSE;
723   SilcMPInt mp_tmp2;
724   SilcMPInt mp_dst;
725   unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
726   SilcUInt32 verify_len, len = (key->bits + 7) / 8;
727   SilcBufferStruct di, ldi;
728   SilcBool has_null = TRUE;
729   SilcHash ihash = NULL;
730   SilcStack stack;
731   SilcAsn1 asn1;
732   char *oid;
733
734   SILC_LOG_DEBUG(("Verify signature"));
735
736   stack = silc_stack_alloc(2048, silc_crypto_stack());
737
738   asn1 = silc_asn1_alloc(stack);
739   if (!asn1) {
740     verify_cb(FALSE, context);
741     return NULL;
742   }
743
744   silc_mp_sinit(stack, &mp_tmp2);
745   silc_mp_sinit(stack, &mp_dst);
746
747   /* Format the signature into MP int */
748   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
749
750   /* Verify */
751   silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);
752
753   /* MP to data */
754   verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
755
756   /* Unpad data */
757   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
758                          unpadded, sizeof(unpadded), &len))
759     goto err;
760   silc_buffer_set(&di, unpadded, len);
761
762   /* If hash isn't given, allocate the one given in digest info */
763   if (!hash) {
764     has_null = FALSE;
765
766     /* Decode digest info */
767     if (!silc_asn1_decode(asn1, &di,
768                           SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
769                           SILC_ASN1_SEQUENCE,
770                             SILC_ASN1_SEQUENCE,
771                               SILC_ASN1_OID(&oid),
772                               SILC_ASN1_NULL_T(SILC_ASN1_OPTIONAL,
773                                                SILC_ASN1_TAG_NULL, &has_null),
774                             SILC_ASN1_END,
775                           SILC_ASN1_END, SILC_ASN1_END))
776       goto err;
777
778     if (!silc_hash_alloc_by_oid(oid, &ihash)) {
779       SILC_LOG_DEBUG(("Unknown OID %s", oid));
780       goto err;
781     }
782     hash = ihash;
783   }
784
785   /* Hash the data */
786   silc_hash_make(hash, data, data_len, hashr);
787   data = hashr;
788   data_len = silc_hash_len(hash);
789   oid = (char *)silc_hash_get_oid(hash);
790
791   /* Encode digest info for comparison */
792   memset(&ldi, 0, sizeof(ldi));
793   if (!silc_asn1_encode(asn1, &ldi,
794                         SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
795                         SILC_ASN1_SEQUENCE,
796                           SILC_ASN1_SEQUENCE,
797                             SILC_ASN1_OID(oid),
798                             SILC_ASN1_NULL(has_null),
799                           SILC_ASN1_END,
800                           SILC_ASN1_OCTET_STRING(data, data_len),
801                         SILC_ASN1_END, SILC_ASN1_END))
802     goto err;
803
804   SILC_LOG_HEXDUMP(("DigestInfo remote"), silc_buffer_data(&di),
805                    silc_buffer_len(&di));
806   SILC_LOG_HEXDUMP(("DigestInfo local"), silc_buffer_data(&ldi),
807                    silc_buffer_len(&ldi));
808
809   /* Compare */
810   if (silc_buffer_len(&di) == silc_buffer_len(&ldi) &&
811       !memcmp(silc_buffer_data(&di), silc_buffer_data(&ldi),
812               silc_buffer_len(&ldi)))
813     ret = TRUE;
814
815   /* Deliver result */
816   verify_cb(ret, context);
817
818   memset(verify, 0, verify_len);
819   memset(unpadded, 0, sizeof(unpadded));
820   silc_free(verify);
821   silc_mp_suninit(stack, &mp_tmp2);
822   silc_mp_suninit(stack, &mp_dst);
823   if (hash)
824     memset(hashr, 0, sizeof(hashr));
825   if (ihash)
826     silc_hash_free(ihash);
827   silc_asn1_free(asn1);
828   silc_stack_free(stack);
829
830   return NULL;
831
832  err:
833   memset(verify, 0, verify_len);
834   silc_free(verify);
835   silc_mp_suninit(stack, &mp_tmp2);
836   silc_mp_suninit(stack, &mp_dst);
837   if (ihash)
838     silc_hash_free(ihash);
839   silc_asn1_free(asn1);
840   silc_stack_free(stack);
841
842   verify_cb(FALSE, context);
843   return NULL;
844 }
845
846 /* PKCS #1 sign without hash oid */
847
848 SilcAsyncOperation
849 silc_pkcs1_sign_no_oid(const struct SilcPKCSAlgorithmStruct *pkcs,
850                        void *private_key,
851                        unsigned char *src,
852                        SilcUInt32 src_len,
853                        SilcBool compute_hash,
854                        SilcHash hash,
855                        SilcPKCSSignCb sign_cb,
856                        void *context)
857 {
858   RsaPrivateKey *key = private_key;
859   SilcMPInt mp_tmp;
860   SilcMPInt mp_dst;
861   unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
862   SilcUInt32 len = (key->bits + 7) / 8;
863   SilcStack stack;
864
865   SILC_LOG_DEBUG(("Sign"));
866
867   if (sizeof(padded) < len) {
868     sign_cb(FALSE, NULL, 0, context);
869     return NULL;
870   }
871
872   /* Compute hash if requested */
873   if (compute_hash) {
874     silc_hash_make(hash, src, src_len, hashr);
875     src = hashr;
876     src_len = silc_hash_len(hash);
877   }
878
879   /* Pad data */
880   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
881                          padded, len, NULL)) {
882     sign_cb(FALSE, NULL, 0, context);
883     return NULL;
884   }
885
886   stack = silc_stack_alloc(2048, silc_crypto_stack());
887
888   silc_mp_sinit(stack, &mp_tmp);
889   silc_mp_sinit(stack, &mp_dst);
890
891   /* Data to MP */
892   silc_mp_bin2mp(padded, len, &mp_tmp);
893
894   /* Sign */
895   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
896
897   /* MP to data */
898   silc_mp_mp2bin_noalloc(&mp_dst, padded, len);
899
900   /* Deliver result */
901   sign_cb(TRUE, padded, len, context);
902
903   memset(padded, 0, sizeof(padded));
904   if (compute_hash)
905     memset(hashr, 0, sizeof(hashr));
906   silc_mp_suninit(stack, &mp_tmp);
907   silc_mp_suninit(stack, &mp_dst);
908   silc_stack_free(stack);
909
910   return NULL;
911 }
912
913 /* PKCS #1 verify without hash oid */
914
915 SilcAsyncOperation
916 silc_pkcs1_verify_no_oid(const struct SilcPKCSAlgorithmStruct *pkcs,
917                          void *public_key,
918                          unsigned char *signature,
919                          SilcUInt32 signature_len,
920                          unsigned char *data,
921                          SilcUInt32 data_len,
922                          SilcHash hash,
923                          SilcPKCSVerifyCb verify_cb,
924                          void *context)
925 {
926   RsaPublicKey *key = public_key;
927   SilcBool ret = FALSE;
928   SilcMPInt mp_tmp2;
929   SilcMPInt mp_dst;
930   unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
931   SilcUInt32 verify_len, len = (key->bits + 7) / 8;
932   SilcStack stack;
933
934   SILC_LOG_DEBUG(("Verify signature"));
935
936   stack = silc_stack_alloc(2048, silc_crypto_stack());
937
938   silc_mp_sinit(stack, &mp_tmp2);
939   silc_mp_sinit(stack, &mp_dst);
940
941   /* Format the signature into MP int */
942   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
943
944   /* Verify */
945   silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);
946
947   /* MP to data */
948   verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
949
950   /* Unpad data */
951   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
952                          unpadded, sizeof(unpadded), &len)) {
953     memset(verify, 0, verify_len);
954     silc_free(verify);
955     silc_mp_suninit(stack, &mp_tmp2);
956     silc_mp_suninit(stack, &mp_dst);
957     silc_stack_free(stack);
958     verify_cb(FALSE, context);
959     return NULL;
960   }
961
962   /* Hash data if requested */
963   if (hash) {
964     silc_hash_make(hash, data, data_len, hashr);
965     data = hashr;
966     data_len = silc_hash_len(hash);
967   }
968
969   /* Compare */
970   if (len == data_len && !memcmp(data, unpadded, len))
971     ret = TRUE;
972
973   /* Deliver result */
974   verify_cb(ret, context);
975
976   memset(verify, 0, verify_len);
977   memset(unpadded, 0, sizeof(unpadded));
978   if (hash)
979     memset(hashr, 0, sizeof(hashr));
980   silc_free(verify);
981   silc_mp_suninit(stack, &mp_tmp2);
982   silc_mp_suninit(stack, &mp_dst);
983   silc_stack_free(stack);
984
985   return NULL;
986 }