Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[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   SilcUInt32 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 (i >= data_len) {
145     SILC_LOG_DEBUG(("Malformed block"));
146     return FALSE;
147   }
148   if (i < SILC_PKCS1_MIN_PADDING) {
149     SILC_LOG_DEBUG(("Malformed block"));
150     return FALSE;
151   }
152   if (data[i++] != 0x00) {
153     SILC_LOG_DEBUG(("Malformed block"));
154     return FALSE;
155   }
156   if (i >= data_len) {
157     SILC_LOG_DEBUG(("Malformed block"));
158     return FALSE;
159   }
160   if (dest_data_size < data_len - i) {
161     SILC_LOG_DEBUG(("Destination buffer too small"));
162     return FALSE;
163   }
164
165   /* Copy the data */
166   memcpy(dest_data, data + i, data_len - i);
167
168   /* Return data length */
169   if (dest_len)
170     *dest_len = data_len - i;
171
172   return TRUE;
173 }
174
175
176 /***************************** PKCS #1 PKCS API ******************************/
177
178 /* Generates RSA key pair. */
179
180 SilcBool silc_pkcs1_generate_key(SilcUInt32 keylen,
181                                  SilcRng rng,
182                                  void **ret_public_key,
183                                  void **ret_private_key)
184 {
185   SilcUInt32 prime_bits = keylen / 2;
186   SilcMPInt p, q;
187   SilcBool found = FALSE;
188
189   if (keylen < 768 || keylen > 16384)
190     return FALSE;
191
192   silc_mp_init(&p);
193   silc_mp_init(&q);
194
195   /* Find p and q */
196   while (!found) {
197     silc_math_gen_prime(&p, prime_bits, FALSE, rng);
198     silc_math_gen_prime(&q, prime_bits, FALSE, rng);
199     if ((silc_mp_cmp(&p, &q)) != 0)
200       found = TRUE;
201   }
202
203   /* If p is smaller than q, switch them */
204   if ((silc_mp_cmp(&p, &q)) > 0) {
205     SilcMPInt hlp;
206     silc_mp_init(&hlp);
207
208     silc_mp_set(&hlp, &p);
209     silc_mp_set(&p, &q);
210     silc_mp_set(&q, &hlp);
211
212     silc_mp_uninit(&hlp);
213   }
214
215   /* Generate the actual keys */
216   if (!silc_rsa_generate_keys(keylen, &p, &q, ret_public_key, ret_private_key))
217     return FALSE;
218
219   silc_mp_uninit(&p);
220   silc_mp_uninit(&q);
221
222   return TRUE;
223 }
224
225 /* Import PKCS #1 compliant public key */
226
227 int silc_pkcs1_import_public_key(unsigned char *key,
228                                  SilcUInt32 key_len,
229                                  void **ret_public_key)
230 {
231   SilcAsn1 asn1 = NULL;
232   SilcBufferStruct alg_key;
233   RsaPublicKey *pubkey;
234
235   if (!ret_public_key)
236     return 0;
237
238   asn1 = silc_asn1_alloc();
239   if (!asn1)
240     return 0;
241
242   /* Allocate RSA public key */
243   *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
244   if (!pubkey)
245     goto err;
246
247   /* Parse the PKCS #1 public key */
248   silc_buffer_set(&alg_key, key, key_len);
249   if (!silc_asn1_decode(asn1, &alg_key,
250                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
251                         SILC_ASN1_SEQUENCE,
252                           SILC_ASN1_INT(&pubkey->n),
253                           SILC_ASN1_INT(&pubkey->e),
254                         SILC_ASN1_END, SILC_ASN1_END))
255     goto err;
256
257   /* Set key length */
258   pubkey->bits = ((silc_mp_sizeinbase(&pubkey->n, 2) + 7) / 8) * 8;
259
260   silc_asn1_free(asn1);
261
262   return key_len;
263
264  err:
265   silc_free(pubkey);
266   silc_asn1_free(asn1);
267   return 0;
268 }
269
270 /* Export PKCS #1 compliant public key */
271
272 unsigned char *silc_pkcs1_export_public_key(void *public_key,
273                                             SilcUInt32 *ret_len)
274 {
275   RsaPublicKey *key = public_key;
276   SilcAsn1 asn1 = NULL;
277   SilcBufferStruct alg_key;
278   unsigned char *ret;
279
280   asn1 = silc_asn1_alloc();
281   if (!asn1)
282     goto err;
283
284   /* Encode to PKCS #1 public key */
285   memset(&alg_key, 0, sizeof(alg_key));
286   if (!silc_asn1_encode(asn1, &alg_key,
287                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
288                         SILC_ASN1_SEQUENCE,
289                           SILC_ASN1_INT(&key->n),
290                           SILC_ASN1_INT(&key->e),
291                         SILC_ASN1_END, SILC_ASN1_END))
292     goto err;
293
294   ret = silc_buffer_steal(&alg_key, ret_len);
295   silc_asn1_free(asn1);
296
297   return ret;
298
299  err:
300   if (asn1)
301     silc_asn1_free(asn1);
302   return NULL;
303 }
304
305 /* Returns key length */
306
307 SilcUInt32 silc_pkcs1_public_key_bitlen(void *public_key)
308 {
309   RsaPublicKey *key = public_key;
310   return key->bits;
311 }
312
313 /* Copy public key */
314
315 void *silc_pkcs1_public_key_copy(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 silc_pkcs1_public_key_compare(void *key1, void *key2)
335 {
336   RsaPublicKey *k1 = key1, *k2 = key2;
337
338   if (k1->bits != k2->bits)
339     return FALSE;
340   if (silc_mp_cmp(&k1->e, &k2->e) != 0)
341     return FALSE;
342   if (silc_mp_cmp(&k1->n, &k2->n) != 0)
343     return FALSE;
344
345   return TRUE;
346 }
347
348 /* Frees public key */
349
350 void silc_pkcs1_public_key_free(void *public_key)
351 {
352   RsaPublicKey *key = public_key;
353
354   silc_mp_uninit(&key->n);
355   silc_mp_uninit(&key->e);
356   silc_free(key);
357 }
358
359 /* Import PKCS #1 compliant private key */
360
361 int silc_pkcs1_import_private_key(unsigned char *key,
362                                   SilcUInt32 key_len,
363                                   void **ret_private_key)
364 {
365   SilcAsn1 asn1;
366   SilcBufferStruct alg_key;
367   RsaPrivateKey *privkey;
368   SilcUInt32 ver;
369
370   if (!ret_private_key)
371     return 0;
372
373   asn1 = silc_asn1_alloc();
374   if (!asn1)
375     return 0;
376
377   /* Allocate RSA private key */
378   *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
379   if (!privkey)
380     goto err;
381
382   /* Parse the PKCS #1 private key */
383   silc_buffer_set(&alg_key, key, key_len);
384   if (!silc_asn1_decode(asn1, &alg_key,
385                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
386                         SILC_ASN1_SEQUENCE,
387                           SILC_ASN1_SHORT_INT(&ver),
388                           SILC_ASN1_INT(&privkey->n),
389                           SILC_ASN1_INT(&privkey->e),
390                           SILC_ASN1_INT(&privkey->d),
391                           SILC_ASN1_INT(&privkey->p),
392                           SILC_ASN1_INT(&privkey->q),
393                           SILC_ASN1_INT(&privkey->dP),
394                           SILC_ASN1_INT(&privkey->dQ),
395                           SILC_ASN1_INT(&privkey->qP),
396                         SILC_ASN1_END, SILC_ASN1_END))
397     goto err;
398
399   if (ver != 0)
400     goto err;
401
402   /* Set key length */
403   privkey->bits = ((silc_mp_sizeinbase(&privkey->n, 2) + 7) / 8) * 8;
404
405   silc_asn1_free(asn1);
406
407   return key_len;
408
409  err:
410   silc_free(privkey);
411   silc_asn1_free(asn1);
412   return 0;
413 }
414
415 /* Export PKCS #1 compliant private key */
416
417 unsigned char *silc_pkcs1_export_private_key(void *private_key,
418                                              SilcUInt32 *ret_len)
419 {
420   RsaPrivateKey *key = private_key;
421   SilcAsn1 asn1;
422   SilcBufferStruct alg_key;
423   unsigned char *ret;
424
425   asn1 = silc_asn1_alloc();
426   if (!asn1)
427     return FALSE;
428
429   /* Encode to PKCS #1 private key */
430   memset(&alg_key, 0, sizeof(alg_key));
431   if (!silc_asn1_encode(asn1, &alg_key,
432                         SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
433                         SILC_ASN1_SEQUENCE,
434                           SILC_ASN1_SHORT_INT(0),
435                           SILC_ASN1_INT(&key->n),
436                           SILC_ASN1_INT(&key->e),
437                           SILC_ASN1_INT(&key->d),
438                           SILC_ASN1_INT(&key->p),
439                           SILC_ASN1_INT(&key->q),
440                           SILC_ASN1_INT(&key->dP),
441                           SILC_ASN1_INT(&key->dQ),
442                           SILC_ASN1_INT(&key->qP),
443                         SILC_ASN1_END, SILC_ASN1_END))
444     goto err;
445
446   ret = silc_buffer_steal(&alg_key, ret_len);
447   silc_asn1_free(asn1);
448
449   return ret;
450
451  err:
452   silc_asn1_free(asn1);
453   return NULL;
454 }
455
456 /* Returns key length */
457
458 SilcUInt32 silc_pkcs1_private_key_bitlen(void *private_key)
459 {
460   RsaPrivateKey *key = private_key;
461   return key->bits;
462 }
463
464 /* Frees private key */
465
466 void silc_pkcs1_private_key_free(void *private_key)
467 {
468   RsaPrivateKey *key = private_key;
469
470   silc_mp_uninit(&key->n);
471   silc_mp_uninit(&key->e);
472   silc_mp_uninit(&key->d);
473   silc_mp_uninit(&key->dP);
474   silc_mp_uninit(&key->dQ);
475   silc_mp_uninit(&key->qP);
476   silc_mp_uninit(&key->p);
477   silc_mp_uninit(&key->q);
478   silc_free(key);
479 }
480
481 /* PKCS #1 RSA routines */
482
483 SilcBool silc_pkcs1_encrypt(void *public_key,
484                             unsigned char *src,
485                             SilcUInt32 src_len,
486                             unsigned char *dst,
487                             SilcUInt32 dst_size,
488                             SilcUInt32 *ret_dst_len,
489                             SilcRng rng)
490 {
491   RsaPublicKey *key = public_key;
492   SilcMPInt mp_tmp;
493   SilcMPInt mp_dst;
494   unsigned char padded[2048 + 1];
495   SilcUInt32 len = (key->bits + 7) / 8;
496
497   if (sizeof(padded) < len)
498     return FALSE;
499   if (dst_size < len)
500     return FALSE;
501
502   /* Pad data */
503   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len,
504                          padded, len, rng))
505     return FALSE;
506
507   silc_mp_init(&mp_tmp);
508   silc_mp_init(&mp_dst);
509
510   /* Data to MP */
511   silc_mp_bin2mp(padded, len, &mp_tmp);
512
513   /* Encrypt */
514   silc_rsa_public_operation(key, &mp_tmp, &mp_dst);
515
516   /* MP to data */
517   silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
518   *ret_dst_len = len;
519
520   memset(padded, 0, sizeof(padded));
521   silc_mp_uninit(&mp_tmp);
522   silc_mp_uninit(&mp_dst);
523
524   return TRUE;
525 }
526
527 SilcBool silc_pkcs1_decrypt(void *private_key,
528                             unsigned char *src,
529                             SilcUInt32 src_len,
530                             unsigned char *dst,
531                             SilcUInt32 dst_size,
532                             SilcUInt32 *ret_dst_len)
533 {
534   RsaPrivateKey *key = private_key;
535   SilcMPInt mp_tmp;
536   SilcMPInt mp_dst;
537   unsigned char *padded, unpadded[2048 + 1];
538   SilcUInt32 padded_len;
539
540   if (dst_size < (key->bits + 7) / 8)
541     return FALSE;
542
543   silc_mp_init(&mp_tmp);
544   silc_mp_init(&mp_dst);
545
546   /* Data to MP */
547   silc_mp_bin2mp(src, src_len, &mp_tmp);
548
549   /* Decrypt */
550   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
551
552   /* MP to data */
553   padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
554
555   /* Unpad data */
556   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len,
557                          unpadded, sizeof(unpadded), ret_dst_len)) {
558     memset(padded, 0, padded_len);
559     silc_free(padded);
560     silc_mp_uninit(&mp_tmp);
561     silc_mp_uninit(&mp_dst);
562     return FALSE;
563   }
564
565   /* Copy to destination */
566   memcpy(dst, unpadded, *ret_dst_len);
567
568   memset(padded, 0, padded_len);
569   memset(unpadded, 0, sizeof(unpadded));
570   silc_free(padded);
571   silc_mp_uninit(&mp_tmp);
572   silc_mp_uninit(&mp_dst);
573
574   return TRUE;
575 }
576
577 /* PKCS #1 sign with appendix, hash OID included in the signature */
578
579 SilcBool silc_pkcs1_sign(void *private_key,
580                          unsigned char *src,
581                          SilcUInt32 src_len,
582                          unsigned char *signature,
583                          SilcUInt32 signature_size,
584                          SilcUInt32 *ret_signature_len,
585                          SilcBool compute_hash,
586                          SilcHash hash)
587 {
588   RsaPrivateKey *key = private_key;
589   unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
590   SilcMPInt mp_tmp;
591   SilcMPInt mp_dst;
592   SilcBufferStruct di;
593   SilcUInt32 len = (key->bits + 7) / 8;
594   const char *oid;
595   SilcAsn1 asn1;
596
597   SILC_LOG_DEBUG(("Sign"));
598
599   if (sizeof(padded) < len)
600     return FALSE;
601   if (signature_size < len)
602     return FALSE;
603
604   oid = silc_hash_get_oid(hash);
605   if (!oid)
606     return FALSE;
607
608   asn1 = silc_asn1_alloc();
609   if (!asn1)
610     return FALSE;
611
612   /* Compute hash */
613   if (compute_hash) {
614     silc_hash_make(hash, src, src_len, hashr);
615     src = hashr;
616     src_len = silc_hash_len(hash);
617   }
618
619   /* Encode digest info */
620   memset(&di, 0, sizeof(di));
621   if (!silc_asn1_encode(asn1, &di,
622                         SILC_ASN1_SEQUENCE,
623                           SILC_ASN1_SEQUENCE,
624                             SILC_ASN1_OID(oid),
625                             SILC_ASN1_NULL,
626                           SILC_ASN1_END,
627                           SILC_ASN1_OCTET_STRING(src, src_len),
628                         SILC_ASN1_END, SILC_ASN1_END)) {
629     silc_asn1_free(asn1);
630     return FALSE;
631   }
632   SILC_LOG_HEXDUMP(("DigestInfo"), silc_buffer_data(&di),
633                    silc_buffer_len(&di));
634
635   /* Pad data */
636   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, silc_buffer_data(&di),
637                          silc_buffer_len(&di), padded, len, NULL)) {
638     silc_asn1_free(asn1);
639     return FALSE;
640   }
641
642   silc_mp_init(&mp_tmp);
643   silc_mp_init(&mp_dst);
644
645   /* Data to MP */
646   silc_mp_bin2mp(padded, len, &mp_tmp);
647
648   /* Sign */
649   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
650
651   /* MP to data */
652   silc_mp_mp2bin_noalloc(&mp_dst, signature, len);
653   *ret_signature_len = len;
654
655   memset(padded, 0, sizeof(padded));
656   silc_mp_uninit(&mp_tmp);
657   silc_mp_uninit(&mp_dst);
658   if (compute_hash)
659     memset(hashr, 0, sizeof(hashr));
660   silc_asn1_free(asn1);
661
662   return TRUE;
663 }
664
665 /* PKCS #1 verification with appendix. */
666
667 SilcBool silc_pkcs1_verify(void *public_key,
668                            unsigned char *signature,
669                            SilcUInt32 signature_len,
670                            unsigned char *data,
671                            SilcUInt32 data_len,
672                            SilcHash hash)
673 {
674   RsaPublicKey *key = public_key;
675   SilcBool ret = FALSE;
676   SilcMPInt mp_tmp2;
677   SilcMPInt mp_dst;
678   unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
679   SilcUInt32 verify_len, len = (key->bits + 7) / 8;
680   SilcBufferStruct di, ldi;
681   SilcHash ihash = NULL;
682   SilcAsn1 asn1 = NULL;
683   char *oid;
684
685   SILC_LOG_DEBUG(("Verify signature"));
686
687   asn1 = silc_asn1_alloc();
688   if (!asn1)
689     return FALSE;
690
691   silc_mp_init(&mp_tmp2);
692   silc_mp_init(&mp_dst);
693
694   /* Format the signature into MP int */
695   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
696
697   /* Verify */
698   silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);
699
700   /* MP to data */
701   verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
702
703   /* Unpad data */
704   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
705                          unpadded, sizeof(unpadded), &len))
706     goto err;
707   silc_buffer_set(&di, unpadded, len);
708
709   /* If hash isn't given, allocate the one given in digest info */
710   if (!hash) {
711     /* Decode digest info */
712     if (!silc_asn1_decode(asn1, &di,
713                           SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
714                           SILC_ASN1_SEQUENCE,
715                             SILC_ASN1_SEQUENCE,
716                               SILC_ASN1_OID(&oid),
717                             SILC_ASN1_END,
718                           SILC_ASN1_END, SILC_ASN1_END))
719       goto err;
720
721     if (!silc_hash_alloc_by_oid(oid, &ihash)) {
722       SILC_LOG_DEBUG(("Unknown OID %s", oid));
723       goto err;
724     }
725     hash = ihash;
726   }
727
728   /* Hash the data */
729   silc_hash_make(hash, data, data_len, hashr);
730   data = hashr;
731   data_len = silc_hash_len(hash);
732   oid = (char *)silc_hash_get_oid(hash);
733
734   /* Encode digest info for comparison */
735   memset(&ldi, 0, sizeof(ldi));
736   if (!silc_asn1_encode(asn1, &ldi,
737                         SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL),
738                         SILC_ASN1_SEQUENCE,
739                           SILC_ASN1_SEQUENCE,
740                             SILC_ASN1_OID(oid),
741                             SILC_ASN1_NULL,
742                           SILC_ASN1_END,
743                           SILC_ASN1_OCTET_STRING(data, data_len),
744                         SILC_ASN1_END, SILC_ASN1_END))
745     goto err;
746
747   SILC_LOG_HEXDUMP(("DigestInfo remote"), silc_buffer_data(&di),
748                    silc_buffer_len(&di));
749   SILC_LOG_HEXDUMP(("DigestInfo local"), silc_buffer_data(&ldi),
750                    silc_buffer_len(&ldi));
751
752   /* Compare */
753   if (silc_buffer_len(&di) == silc_buffer_len(&ldi) &&
754       !memcmp(silc_buffer_data(&di), silc_buffer_data(&ldi),
755               silc_buffer_len(&ldi)))
756     ret = TRUE;
757
758   memset(verify, 0, verify_len);
759   memset(unpadded, 0, sizeof(unpadded));
760   silc_free(verify);
761   silc_mp_uninit(&mp_tmp2);
762   silc_mp_uninit(&mp_dst);
763   if (hash)
764     memset(hashr, 0, sizeof(hashr));
765   if (ihash)
766     silc_hash_free(ihash);
767   silc_asn1_free(asn1);
768
769   return ret;
770
771  err:
772   memset(verify, 0, verify_len);
773   silc_free(verify);
774   silc_mp_uninit(&mp_tmp2);
775   silc_mp_uninit(&mp_dst);
776   if (ihash)
777     silc_hash_free(ihash);
778   silc_asn1_free(asn1);
779   return FALSE;
780 }
781
782 /* PKCS #1 sign without hash oid */
783
784 SilcBool silc_pkcs1_sign_no_oid(void *private_key,
785                                 unsigned char *src,
786                                 SilcUInt32 src_len,
787                                 unsigned char *signature,
788                                 SilcUInt32 signature_size,
789                                 SilcUInt32 *ret_signature_len,
790                                 SilcBool compute_hash,
791                                 SilcHash hash)
792 {
793   RsaPrivateKey *key = private_key;
794   SilcMPInt mp_tmp;
795   SilcMPInt mp_dst;
796   unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
797   SilcUInt32 len = (key->bits + 7) / 8;
798
799   SILC_LOG_DEBUG(("Sign"));
800
801   if (sizeof(padded) < len)
802     return FALSE;
803   if (signature_size < len)
804     return FALSE;
805
806   /* Compute hash if requested */
807   if (compute_hash) {
808     silc_hash_make(hash, src, src_len, hashr);
809     src = hashr;
810     src_len = silc_hash_len(hash);
811   }
812
813   /* Pad data */
814   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
815                          padded, len, NULL))
816     return FALSE;
817
818   silc_mp_init(&mp_tmp);
819   silc_mp_init(&mp_dst);
820
821   /* Data to MP */
822   silc_mp_bin2mp(padded, len, &mp_tmp);
823
824   /* Sign */
825   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
826
827   /* MP to data */
828   silc_mp_mp2bin_noalloc(&mp_dst, signature, len);
829   *ret_signature_len = len;
830
831   memset(padded, 0, sizeof(padded));
832   silc_mp_uninit(&mp_tmp);
833   silc_mp_uninit(&mp_dst);
834   if (compute_hash)
835     memset(hashr, 0, sizeof(hashr));
836
837   return TRUE;
838 }
839
840 /* PKCS #1 verify without hash oid */
841
842 SilcBool silc_pkcs1_verify_no_oid(void *public_key,
843                                   unsigned char *signature,
844                                   SilcUInt32 signature_len,
845                                   unsigned char *data,
846                                   SilcUInt32 data_len,
847                                   SilcHash hash)
848 {
849   RsaPublicKey *key = public_key;
850   SilcBool ret = FALSE;
851   SilcMPInt mp_tmp2;
852   SilcMPInt mp_dst;
853   unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
854   SilcUInt32 verify_len, len = (key->bits + 7) / 8;
855
856   SILC_LOG_DEBUG(("Verify signature"));
857
858   silc_mp_init(&mp_tmp2);
859   silc_mp_init(&mp_dst);
860
861   /* Format the signature into MP int */
862   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
863
864   /* Verify */
865   silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);
866
867   /* MP to data */
868   verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
869
870   /* Unpad data */
871   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
872                          unpadded, sizeof(unpadded), &len)) {
873     memset(verify, 0, verify_len);
874     silc_free(verify);
875     silc_mp_uninit(&mp_tmp2);
876     silc_mp_uninit(&mp_dst);
877     return FALSE;
878   }
879
880   /* Hash data if requested */
881   if (hash) {
882     silc_hash_make(hash, data, data_len, hashr);
883     data = hashr;
884     data_len = silc_hash_len(hash);
885   }
886
887   /* Compare */
888   if (len == data_len && !memcmp(data, unpadded, len))
889     ret = TRUE;
890
891   memset(verify, 0, verify_len);
892   memset(unpadded, 0, sizeof(unpadded));
893   silc_free(verify);
894   silc_mp_uninit(&mp_tmp2);
895   silc_mp_uninit(&mp_dst);
896   if (hash)
897     memset(hashr, 0, sizeof(hashr));
898
899   return ret;
900 }