PKCS import routines now return the bytes imported.
[crypto.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);
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);
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 SilcBool silc_pkcs1_sign(void *private_key,
570                          unsigned char *src,
571                          SilcUInt32 src_len,
572                          unsigned char *signature,
573                          SilcUInt32 signature_size,
574                          SilcUInt32 *ret_signature_len,
575                          SilcHash hash)
576 {
577   return FALSE;
578 }
579
580 SilcBool silc_pkcs1_verify(void *public_key,
581                            unsigned char *signature,
582                            SilcUInt32 signature_len,
583                            unsigned char *data,
584                            SilcUInt32 data_len,
585                            SilcHash hash)
586 {
587   return FALSE;
588 }
589
590 /* PKCS #1 sign without hash oid */
591
592 SilcBool silc_pkcs1_sign_no_oid(void *private_key,
593                                 unsigned char *src,
594                                 SilcUInt32 src_len,
595                                 unsigned char *signature,
596                                 SilcUInt32 signature_size,
597                                 SilcUInt32 *ret_signature_len,
598                                 SilcHash hash)
599 {
600   RsaPrivateKey *key = private_key;
601   SilcMPInt mp_tmp;
602   SilcMPInt mp_dst;
603   unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
604   SilcUInt32 len = (key->bits + 7) / 8;
605
606   if (sizeof(padded) < len)
607     return FALSE;
608   if (signature_size < len)
609     return FALSE;
610
611   /* Compute hash if requested */
612   if (hash) {
613     silc_hash_make(hash, src, src_len, hashr);
614     src = hashr;
615     src_len = silc_hash_len(hash);
616   }
617
618   /* Pad data */
619   if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
620                          padded, len, NULL))
621     return FALSE;
622
623   silc_mp_init(&mp_tmp);
624   silc_mp_init(&mp_dst);
625
626   /* Data to MP */
627   silc_mp_bin2mp(padded, len, &mp_tmp);
628
629   /* Sign */
630   silc_rsa_private_operation(key, &mp_tmp, &mp_dst);
631
632   /* MP to data */
633   silc_mp_mp2bin_noalloc(&mp_dst, signature, len);
634   *ret_signature_len = len;
635
636   memset(padded, 0, sizeof(padded));
637   silc_mp_uninit(&mp_tmp);
638   silc_mp_uninit(&mp_dst);
639   if (hash)
640     memset(hashr, 0, sizeof(hashr));
641
642   return TRUE;
643 }
644
645 /* PKCS #1 verify without hash oid */
646
647 SilcBool silc_pkcs1_verify_no_oid(void *public_key,
648                                   unsigned char *signature,
649                                   SilcUInt32 signature_len,
650                                   unsigned char *data,
651                                   SilcUInt32 data_len,
652                                   SilcHash hash)
653 {
654   RsaPublicKey *key = public_key;
655   int ret = TRUE;
656   SilcMPInt mp_tmp2;
657   SilcMPInt mp_dst;
658   unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
659   SilcUInt32 verify_len, len = (key->bits + 7) / 8;
660
661   silc_mp_init(&mp_tmp2);
662   silc_mp_init(&mp_dst);
663
664   /* Format the signature into MP int */
665   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
666
667   /* Verify */
668   silc_rsa_public_operation(key, &mp_tmp2, &mp_dst);
669
670   /* MP to data */
671   verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
672
673   /* Unpad data */
674   if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
675                          unpadded, sizeof(unpadded), &len)) {
676     memset(verify, 0, verify_len);
677     silc_free(verify);
678     silc_mp_uninit(&mp_tmp2);
679     silc_mp_uninit(&mp_dst);
680     return FALSE;
681   }
682
683   /* Hash data if requested */
684   if (hash) {
685     silc_hash_make(hash, data, data_len, hashr);
686     data = hashr;
687     data_len = silc_hash_len(hash);
688   }
689
690   /* Compare */
691   if (len != data_len)
692     ret = FALSE;
693   else if (memcmp(data, unpadded, len))
694     ret = FALSE;
695
696   memset(verify, 0, verify_len);
697   memset(unpadded, 0, sizeof(unpadded));
698   silc_free(verify);
699   silc_mp_uninit(&mp_tmp2);
700   silc_mp_uninit(&mp_dst);
701   if (hash)
702     memset(hashr, 0, sizeof(hashr));
703
704   return ret;
705 }