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