Rewrote crypto library init/uninit. Added silc_crypto_init
[silc.git] / lib / silccrypt / silcpk.c
1 /*
2
3   silcpk.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silc.h"
21 #include "silcpk_i.h"
22
23 /****************************** Key generation *******************************/
24
25 /* Generate new SILC key pair. */
26
27 SilcBool silc_pkcs_silc_generate_key(const char *algorithm,
28                                      SilcUInt32 bits_key_len,
29                                      const char *identifier,
30                                      SilcRng rng,
31                                      SilcPublicKey *ret_public_key,
32                                      SilcPrivateKey *ret_private_key)
33 {
34   SilcSILCPublicKey pubkey;
35   SilcSILCPrivateKey privkey;
36   const SilcPKCSAlgorithm *alg;
37   const SilcPKCSObject *pkcs;
38   SilcUInt32 version;
39
40   SILC_LOG_DEBUG(("Generating SILC %s key pair with key length %d bits",
41                   algorithm, bits_key_len));
42
43   if (!rng)
44     return FALSE;
45
46   pkcs = silc_pkcs_find_pkcs(SILC_PKCS_SILC);
47   if (!pkcs)
48     return FALSE;
49
50   /* Allocate SILC public key */
51   pubkey = silc_calloc(1, sizeof(*pubkey));
52   if (!pubkey)
53     return FALSE;
54
55   /* Decode identifier */
56   if (!silc_pkcs_silc_decode_identifier(identifier, &pubkey->identifier))
57     return FALSE;
58
59   if (pubkey->identifier.version && atoi(pubkey->identifier.version) >= 2)
60     version = 2;
61   else
62     version = 1;
63
64   /* Allocate algorithm */
65   alg = silc_pkcs_find_algorithm(algorithm, (version == 1 ? "pkcs1-no-oid" :
66                                              "pkcs1"));
67   if (!alg) {
68     silc_free(pubkey);
69     return FALSE;
70   }
71   pubkey->pkcs = alg;
72
73   /* Allocate SILC private key */
74   privkey = silc_calloc(1, sizeof(*privkey));
75   if (!privkey) {
76     silc_free(pubkey);
77     return FALSE;
78   }
79   privkey->pkcs = alg;
80
81   /* Allocate public key */
82   *ret_public_key = silc_calloc(1, sizeof(**ret_public_key));
83   if (!(*ret_public_key)) {
84     silc_free(pubkey);
85     silc_free(privkey);
86     return FALSE;
87   }
88   (*ret_public_key)->pkcs = pkcs;
89   (*ret_public_key)->public_key = pubkey;
90
91   /* Allocate private key */
92   *ret_private_key = silc_calloc(1, sizeof(**ret_private_key));
93   if (!(*ret_private_key)) {
94     silc_free(pubkey);
95     silc_free(privkey);
96     silc_free(*ret_public_key);
97     return FALSE;
98   }
99   (*ret_private_key)->pkcs = pkcs;
100   (*ret_private_key)->private_key = privkey;
101
102   /* Generate the algorithm key pair */
103   if (!alg->generate_key(alg, bits_key_len, rng, &pubkey->public_key,
104                          &privkey->private_key)) {
105     silc_free(pubkey);
106     silc_free(privkey);
107     silc_free(*ret_public_key);
108     silc_free(*ret_private_key);
109     return FALSE;
110   }
111
112   return TRUE;
113 }
114
115
116 /**************************** Utility functions ******************************/
117
118 /* Decodes the provided `identifier' */
119
120 SilcBool silc_pkcs_silc_decode_identifier(const char *identifier,
121                                           SilcPublicKeyIdentifier ident)
122 {
123   char *cp, *item;
124   int len;
125
126   /* Protocol says that at least UN and HN must be provided as identifier */
127   if (!strstr(identifier, "UN=") && !strstr(identifier, "HN=")) {
128     SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
129                     "identifiers"));
130     return FALSE;
131   }
132
133   cp = (char *)identifier;
134   while (cp) {
135     len = strcspn(cp, ",");
136     if (len < 1) {
137       cp = NULL;
138       break;
139     }
140     if (len - 1 >= 0 && cp[len - 1] == '\\') {
141       while (cp) {
142         if (len + 1 > strlen(cp)) {
143           cp = NULL;
144           break;
145         }
146         cp += len + 1;
147         len = strcspn(cp, ",") + len;
148         if (len < 1) {
149           cp = NULL;
150           break;
151         }
152         if (len - 1 >= 0 && cp[len - 1] != '\\')
153           break;
154       }
155     }
156
157     if (!cp)
158       break;
159
160     item = silc_calloc(len + 1, sizeof(char));
161     if (!item)
162       return FALSE;
163     if (len > strlen(cp))
164       break;
165     memcpy(item, cp, len);
166
167     if (strstr(item, "UN="))
168       ident->username = strdup(item + strcspn(cp, "=") + 1);
169     else if (strstr(item, "HN="))
170       ident->host = strdup(item + strcspn(cp, "=") + 1);
171     else if (strstr(item, "RN="))
172       ident->realname = strdup(item + strcspn(cp, "=") + 1);
173     else if (strstr(item, "E="))
174       ident->email = strdup(item + strcspn(cp, "=") + 1);
175     else if (strstr(item, "O="))
176       ident->org = strdup(item + strcspn(cp, "=") + 1);
177     else if (strstr(item, "C="))
178       ident->country = strdup(item + strcspn(cp, "=") + 1);
179     else if (strstr(item, "V="))
180       ident->version = strdup(item + strcspn(cp, "=") + 1);
181
182     cp += len;
183     if (strlen(cp) < 1)
184       cp = NULL;
185     else
186       cp += 1;
187
188     if (item)
189       silc_free(item);
190   }
191
192   return TRUE;
193 }
194
195 /* Encodes and returns SILC public key identifier.  If some of the
196    arguments is NULL those are not encoded into the identifier string.
197    Protocol says that at least username and host must be provided. */
198
199 char *silc_pkcs_silc_encode_identifier(SilcStack stack,
200                                        char *username, char *host,
201                                        char *realname, char *email,
202                                        char *org, char *country,
203                                        char *version)
204 {
205   SilcBufferStruct buf;
206   char *identifier;
207
208   if (!username || !host)
209     return NULL;
210   if (strlen(username) < 3 || strlen(host) < 3)
211     return NULL;
212
213   memset(&buf, 0, sizeof(buf));
214
215   if (username)
216     silc_buffer_sformat(stack, &buf,
217                         SILC_STR_ADVANCE,
218                         SILC_STR_UI32_STRING("UN="),
219                         SILC_STR_UI32_STRING(username),
220                         SILC_STR_END);
221
222   if (host)
223     silc_buffer_sformat(stack, &buf,
224                         SILC_STR_ADVANCE,
225                         SILC_STR_UI32_STRING(", "),
226                         SILC_STR_UI32_STRING("HN="),
227                         SILC_STR_UI32_STRING(host),
228                         SILC_STR_END);
229
230   if (realname)
231     silc_buffer_sformat(stack, &buf,
232                         SILC_STR_ADVANCE,
233                         SILC_STR_UI32_STRING(", "),
234                         SILC_STR_UI32_STRING("RN="),
235                         SILC_STR_UI32_STRING(realname),
236                         SILC_STR_END);
237
238   if (email)
239     silc_buffer_sformat(stack, &buf,
240                         SILC_STR_ADVANCE,
241                         SILC_STR_UI32_STRING(", "),
242                         SILC_STR_UI32_STRING("E="),
243                         SILC_STR_UI32_STRING(email),
244                         SILC_STR_END);
245
246   if (org)
247     silc_buffer_sformat(stack, &buf,
248                         SILC_STR_ADVANCE,
249                         SILC_STR_UI32_STRING(", "),
250                         SILC_STR_UI32_STRING("O="),
251                         SILC_STR_UI32_STRING(org),
252                         SILC_STR_END);
253
254   if (country)
255     silc_buffer_sformat(stack, &buf,
256                         SILC_STR_ADVANCE,
257                         SILC_STR_UI32_STRING(", "),
258                         SILC_STR_UI32_STRING("C="),
259                         SILC_STR_UI32_STRING(country),
260                         SILC_STR_END);
261
262   if (version) {
263     if (strlen(version) > 1 || !isdigit(version[0])) {
264       silc_buffer_spurge(stack, &buf);
265       return NULL;
266     }
267     silc_buffer_sformat(stack, &buf,
268                         SILC_STR_ADVANCE,
269                         SILC_STR_UI32_STRING(", "),
270                         SILC_STR_UI32_STRING("V="),
271                         SILC_STR_UI32_STRING(version),
272                         SILC_STR_END);
273   }
274
275   silc_buffer_sformat(stack, &buf, SILC_STR_UI_CHAR(0), SILC_STR_END);
276
277   identifier = silc_buffer_steal(&buf, NULL);
278   return identifier;
279 }
280
281 /* Return SILC public key version */
282
283 int silc_pkcs_silc_public_key_version(SilcPublicKey public_key)
284 {
285   SilcSILCPublicKey silc_pubkey;
286
287   if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
288     return -1;
289
290   silc_pubkey = public_key->public_key;
291
292   /* If version identifire is not present it is version 1. */
293   if (!silc_pubkey->identifier.version)
294     return 1;
295
296   return atoi(silc_pubkey->identifier.version);
297 }
298
299 /*************************** Public key routines *****************************/
300
301 /* Returns PKCS algorithm context */
302
303 const SilcPKCSAlgorithm *
304 silc_pkcs_silc_get_algorithm(const struct SilcPKCSObjectStruct *pkcs,
305                              void *public_key)
306 {
307   SilcSILCPublicKey silc_pubkey = public_key;
308   return silc_pubkey->pkcs;
309 }
310
311 /* Imports SILC protocol style public key from SILC public key file */
312
313 SilcBool
314 silc_pkcs_silc_import_public_key_file(const struct SilcPKCSObjectStruct *pkcs,
315                                       unsigned char *filedata,
316                                       SilcUInt32 filedata_len,
317                                       SilcPKCSFileEncoding encoding,
318                                       void **ret_public_key)
319 {
320   SilcUInt32 i, len;
321   unsigned char *data = NULL;
322   int ret;
323
324   SILC_LOG_DEBUG(("Parsing SILC public key file"));
325
326   if (!ret_public_key)
327     return FALSE;
328
329   /* Check start of file and remove header from the data. */
330   len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
331   if (filedata_len < len + strlen(SILC_PKCS_PUBLIC_KEYFILE_END)) {
332     SILC_LOG_ERROR(("Malformed SILC public key header"));
333     return FALSE;
334   }
335   for (i = 0; i < len; i++) {
336     if (*filedata != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
337       SILC_LOG_ERROR(("Malformed SILC public key header"));
338       return FALSE;
339     }
340     filedata++;
341   }
342   filedata_len -= (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
343                    strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
344
345   switch (encoding) {
346   case SILC_PKCS_FILE_BIN:
347     break;
348
349   case SILC_PKCS_FILE_BASE64:
350     data = silc_base64_decode(NULL, filedata, filedata_len, &filedata_len);
351     if (!data)
352       return FALSE;
353     filedata = data;
354     break;
355   }
356
357   ret = silc_pkcs_silc_import_public_key(pkcs, filedata, filedata_len,
358                                          ret_public_key);
359   silc_free(data);
360
361   return ret ? TRUE : FALSE;
362 }
363
364 /* Imports SILC protocol style public key */
365
366 int silc_pkcs_silc_import_public_key(const struct SilcPKCSObjectStruct *pkcs,
367                                      void *key,
368                                      SilcUInt32 key_len,
369                                      void **ret_public_key)
370 {
371   const SilcPKCSAlgorithm *alg;
372   SilcBufferStruct buf, alg_key;
373   SilcSILCPublicKey silc_pubkey = NULL;
374   SilcAsn1 asn1 = NULL;
375   SilcUInt32 totlen, keydata_len;
376   SilcUInt16 pkcs_len, identifier_len;
377   unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
378   int ret;
379
380   SILC_LOG_DEBUG(("Parsing SILC public key"));
381
382   if (!ret_public_key)
383     return 0;
384
385   silc_buffer_set(&buf, key, key_len);
386
387   /* Get length */
388   ret = silc_buffer_unformat(&buf,
389                              SILC_STR_ADVANCE,
390                              SILC_STR_UI_INT(&totlen),
391                              SILC_STR_END);
392   if (ret == -1)
393     goto err;
394
395   /* Backwards compatibility */
396   if (totlen == key_len)
397     totlen -= 4;
398
399   if (totlen + 4 != key_len)
400     goto err;
401
402   /* Get algorithm name and identifier */
403   ret =
404     silc_buffer_unformat(&buf,
405                          SILC_STR_ADVANCE,
406                          SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
407                          SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
408                          SILC_STR_END);
409   if (ret == -1)
410     goto err;
411
412   if (pkcs_len < 1 || identifier_len < 3 ||
413       pkcs_len + identifier_len > totlen)
414     goto err;
415
416   /* Get key data */
417   keydata_len = silc_buffer_len(&buf);
418   ret = silc_buffer_unformat(&buf,
419                              SILC_STR_DATA(&key_data, keydata_len),
420                              SILC_STR_END);
421   if (ret == -1)
422     goto err;
423
424   /* Allocate SILC public key context */
425   silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
426   if (!silc_pubkey)
427     goto err;
428
429   /* Decode SILC identifier */
430   if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
431     goto err;
432
433   asn1 = silc_asn1_alloc(NULL);
434   if (!asn1)
435     goto err;
436
437   SILC_LOG_DEBUG(("Public key version %s",
438                   (!silc_pubkey->identifier.version ? "1" :
439                    silc_pubkey->identifier.version)));
440
441   if (!strcmp(pkcs_name, "rsa")) {
442     /* Parse the SILC RSA public key */
443     SilcUInt32 e_len, n_len;
444     SilcMPInt n, e;
445
446     /* Get PKCS object.  Different PKCS #1 scheme is used with different
447        versions. */
448     if (!silc_pubkey->identifier.version ||
449         atoi(silc_pubkey->identifier.version) <= 1) {
450       /* Version 1 */
451       alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
452     } else {
453       /* Version 2 and newer */
454       alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
455     }
456     if (!alg) {
457       SILC_LOG_DEBUG(("Unsupported PKCS algorithm: rsa"));
458       goto err;
459     }
460     silc_pubkey->pkcs = alg;
461
462     if (keydata_len < 4)
463       goto err;
464     SILC_GET32_MSB(e_len, key_data);
465     if (!e_len || e_len + 4 > keydata_len)
466       goto err;
467     silc_mp_init(&e);
468     silc_mp_bin2mp(key_data + 4, e_len, &e);
469     if (keydata_len < 4 + e_len + 4) {
470       silc_mp_uninit(&e);
471       goto err;
472     }
473     SILC_GET32_MSB(n_len, key_data + 4 + e_len);
474     if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
475       silc_mp_uninit(&e);
476       goto err;
477     }
478     silc_mp_init(&n);
479     silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
480
481     /* Encode to PKCS #1 format */
482     memset(&alg_key, 0, sizeof(alg_key));
483     if (!silc_asn1_encode(asn1, &alg_key,
484                           SILC_ASN1_SEQUENCE,
485                             SILC_ASN1_INT(&n),
486                             SILC_ASN1_INT(&e),
487                           SILC_ASN1_END, SILC_ASN1_END)) {
488       silc_mp_uninit(&e);
489       silc_mp_uninit(&n);
490       goto err;
491     }
492
493     silc_mp_uninit(&e);
494     silc_mp_uninit(&n);
495
496   } else if (!strcmp(pkcs_name, "dsa")) {
497     SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
498     goto err;
499
500   } else {
501     SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
502     goto err;
503   }
504
505   /* Import PKCS algorithm public key */
506   if (!alg->import_public_key(alg, alg_key.data, silc_buffer_len(&alg_key),
507                               &silc_pubkey->public_key))
508     goto err;
509
510   silc_free(pkcs_name);
511   silc_free(ident);
512   silc_asn1_free(asn1);
513
514   *ret_public_key = silc_pubkey;
515
516   return key_len;
517
518  err:
519   silc_free(pkcs_name);
520   silc_free(ident);
521   silc_free(silc_pubkey);
522   if (asn1)
523     silc_asn1_free(asn1);
524   return 0;
525 }
526
527 /* Exports public key as SILC protocol style public key file */
528
529 unsigned char *
530 silc_pkcs_silc_export_public_key_file(const struct SilcPKCSObjectStruct *pkcs,
531                                       SilcStack stack,
532                                       void *public_key,
533                                       SilcPKCSFileEncoding encoding,
534                                       SilcUInt32 *ret_len)
535 {
536   SilcBuffer buf;
537   unsigned char *key, *data;
538   SilcUInt32 key_len;
539
540   SILC_LOG_DEBUG(("Encoding SILC public key file"));
541
542   /* Export key */
543   key = silc_pkcs_silc_export_public_key(pkcs, stack, public_key, &key_len);
544   if (!key)
545     return NULL;
546
547   switch (encoding) {
548   case SILC_PKCS_FILE_BIN:
549     break;
550
551   case SILC_PKCS_FILE_BASE64:
552     data = silc_base64_encode_file(stack, key, key_len);
553     if (!data)
554       return NULL;
555     silc_sfree(stack, key);
556     key = data;
557     key_len = strlen(data);
558     break;
559   }
560
561   /* Encode SILC public key file */
562   buf = silc_buffer_salloc_size(stack, key_len +
563                                 (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
564                                  strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
565   if (!buf) {
566     silc_sfree(stack, key);
567     return NULL;
568   }
569
570   if (silc_buffer_sformat(stack, buf,
571                           SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
572                           SILC_STR_UI_XNSTRING(key, key_len),
573                           SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
574                           SILC_STR_END) < 0) {
575     silc_buffer_sfree(stack, buf);
576     silc_sfree(stack, key);
577     return NULL;
578   }
579
580   silc_sfree(stack, key);
581   key = silc_buffer_steal(buf, ret_len);
582   silc_buffer_sfree(stack, buf);
583
584   return key;
585 }
586
587 /* Exports public key as SILC protocol style public key */
588
589 unsigned char *
590 silc_pkcs_silc_export_public_key(const struct SilcPKCSObjectStruct *pkcs,
591                                  SilcStack stack,
592                                  void *public_key,
593                                  SilcUInt32 *ret_len)
594 {
595   SilcSILCPublicKey silc_pubkey = public_key;
596   const SilcPKCSAlgorithm *alg = silc_pubkey->pkcs;
597   SilcBufferStruct alg_key;
598   SilcBuffer buf = NULL;
599   SilcAsn1 asn1 = NULL;
600   unsigned char *pk = NULL, *key = NULL, *ret;
601   SilcUInt32 pk_len, key_len, totlen;
602   char *identifier;
603
604   SILC_LOG_DEBUG(("Encoding SILC public key"));
605
606   /* Export PKCS algorithm public key */
607   if (alg->export_public_key)
608     pk = alg->export_public_key(alg, stack, silc_pubkey->public_key, &pk_len);
609   if (!pk) {
610     SILC_LOG_ERROR(("Error exporting PKCS algorithm key"));
611     return NULL;
612   }
613   silc_buffer_set(&alg_key, pk, pk_len);
614
615   /* Encode identifier */
616   identifier =
617     silc_pkcs_silc_encode_identifier(stack,
618                                      silc_pubkey->identifier.username,
619                                      silc_pubkey->identifier.host,
620                                      silc_pubkey->identifier.realname,
621                                      silc_pubkey->identifier.email,
622                                      silc_pubkey->identifier.org,
623                                      silc_pubkey->identifier.country,
624                                      silc_pubkey->identifier.version);
625   if (!identifier) {
626     SILC_LOG_ERROR(("Error encoding SILC public key identifier"));
627     goto err;
628   }
629
630   asn1 = silc_asn1_alloc(stack);
631   if (!asn1)
632     goto err;
633
634   if (!strcmp(alg->name, "rsa")) {
635     /* Parse the PKCS #1 public key */
636     SilcMPInt n, e;
637     SilcUInt32 n_len, e_len;
638     unsigned char *nb, *eb;
639
640     memset(&n, 0, sizeof(n));
641     memset(&e, 0, sizeof(e));
642     if (!silc_asn1_decode(asn1, &alg_key,
643                           SILC_ASN1_SEQUENCE,
644                             SILC_ASN1_INT(&n),
645                             SILC_ASN1_INT(&e),
646                           SILC_ASN1_END, SILC_ASN1_END))
647       goto err;
648
649     /* Encode to SILC RSA public key */
650     eb = silc_mp_mp2bin(&e, 0, &e_len);
651     if (!eb)
652       goto err;
653     nb = silc_mp_mp2bin(&n, 0, &n_len);
654     if (!nb)
655       goto err;
656     key_len = e_len + 4 + n_len + 4;
657     key = silc_scalloc(stack, key_len, sizeof(*key));
658     if (!key)
659       goto err;
660
661     /* Put e length and e */
662     SILC_PUT32_MSB(e_len, key);
663     memcpy(key + 4, eb, e_len);
664
665     /* Put n length and n. */
666     SILC_PUT32_MSB(n_len, key + 4 + e_len);
667     memcpy(key + 4 + e_len + 4, nb, n_len);
668
669     silc_free(nb);
670     silc_free(eb);
671
672   } else if (!strcmp(alg->name, "dsa")) {
673     SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
674     goto err;
675
676   } else {
677     SILC_LOG_ERROR(("Unsupported PKCS algorithm: %s", alg->name));
678     goto err;
679   }
680
681   /* Encode SILC Public Key */
682   totlen = 2 + strlen(alg->name) + 2 + strlen(identifier) + key_len;
683   buf = silc_buffer_salloc_size(stack, totlen + 4);
684   if (!buf)
685     goto err;
686   if (silc_buffer_sformat(stack, buf,
687                           SILC_STR_UI_INT(totlen),
688                           SILC_STR_UI_SHORT(strlen(alg->name)),
689                           SILC_STR_UI32_STRING(alg->name),
690                           SILC_STR_UI_SHORT(strlen(identifier)),
691                           SILC_STR_UI32_STRING(identifier),
692                           SILC_STR_UI_XNSTRING(key, key_len),
693                           SILC_STR_END) < 0)
694     goto err;
695
696   ret = silc_buffer_steal(buf, ret_len);
697   silc_buffer_sfree(stack, buf);
698   silc_sfree(stack, key);
699   silc_sfree(stack, identifier);
700   silc_buffer_spurge(stack, &alg_key);
701   silc_asn1_free(asn1);
702
703   return ret;
704
705  err:
706   silc_sfree(stack, identifier);
707   silc_sfree(stack, pk);
708   silc_sfree(stack, key);
709   silc_buffer_sfree(stack, buf);
710   if (asn1)
711     silc_asn1_free(asn1);
712   return NULL;
713 }
714
715 /* Return key length */
716
717 SilcUInt32
718 silc_pkcs_silc_public_key_bitlen(const struct SilcPKCSObjectStruct *pkcs,
719                                  void *public_key)
720 {
721   SilcSILCPublicKey silc_pubkey = public_key;
722   return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->pkcs,
723                                               silc_pubkey->public_key);
724 }
725
726 /* Copy public key */
727
728 void *silc_pkcs_silc_public_key_copy(const struct SilcPKCSObjectStruct *pkcs,
729                                      void *public_key)
730 {
731   SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
732   SilcPublicKeyIdentifier ident = &silc_pubkey->identifier;
733
734   new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
735   if (!new_pubkey)
736     return NULL;
737   new_pubkey->pkcs = silc_pubkey->pkcs;
738
739   new_pubkey->public_key =
740     silc_pubkey->pkcs->public_key_copy(silc_pubkey->pkcs,
741                                        silc_pubkey->public_key);
742   if (!new_pubkey->public_key) {
743     silc_free(new_pubkey);
744     return NULL;
745   }
746
747   if (ident->username)
748     new_pubkey->identifier.username =
749       silc_memdup(ident->username, strlen(ident->username));
750   if (ident->host)
751     new_pubkey->identifier.host =
752       silc_memdup(ident->host, strlen(ident->host));
753   if (ident->realname)
754     new_pubkey->identifier.realname =
755       silc_memdup(ident->realname, strlen(ident->realname));
756   if (ident->email)
757     new_pubkey->identifier.email =
758       silc_memdup(ident->email, strlen(ident->email));
759   if (ident->org)
760     new_pubkey->identifier.org =
761       silc_memdup(ident->org, strlen(ident->org));
762   if (ident->country)
763     new_pubkey->identifier.country =
764       silc_memdup(ident->country, strlen(ident->country));
765   if (ident->version)
766     new_pubkey->identifier.version =
767       silc_memdup(ident->version, strlen(ident->version));
768
769   return new_pubkey;
770 }
771
772 /* Compares public keys */
773
774 SilcBool
775 silc_pkcs_silc_public_key_compare(const struct SilcPKCSObjectStruct *pkcs,
776                                   void *key1, void *key2)
777 {
778   SilcSILCPublicKey k1 = key1, k2 = key2;
779
780   if (strcmp(k1->pkcs->name, k2->pkcs->name))
781     return FALSE;
782
783   if ((k1->identifier.username && !k2->identifier.username) ||
784       (!k1->identifier.username && k2->identifier.username) ||
785       (k1->identifier.username && k2->identifier.username &&
786        strcmp(k1->identifier.username, k2->identifier.username)))
787     return FALSE;
788
789   if ((k1->identifier.host && !k2->identifier.host) ||
790       (!k1->identifier.host && k2->identifier.host) ||
791       (k1->identifier.host && k2->identifier.host &&
792        strcmp(k1->identifier.host, k2->identifier.host)))
793     return FALSE;
794
795   if ((k1->identifier.realname && !k2->identifier.realname) ||
796       (!k1->identifier.realname && k2->identifier.realname) ||
797       (k1->identifier.realname && k2->identifier.realname &&
798        strcmp(k1->identifier.realname, k2->identifier.realname)))
799     return FALSE;
800
801   if ((k1->identifier.email && !k2->identifier.email) ||
802       (!k1->identifier.email && k2->identifier.email) ||
803       (k1->identifier.email && k2->identifier.email &&
804        strcmp(k1->identifier.email, k2->identifier.email)))
805     return FALSE;
806
807   if ((k1->identifier.org && !k2->identifier.org) ||
808       (!k1->identifier.org && k2->identifier.org) ||
809       (k1->identifier.org && k2->identifier.org &&
810        strcmp(k1->identifier.org, k2->identifier.org)))
811     return FALSE;
812
813   if ((k1->identifier.country && !k2->identifier.country) ||
814       (!k1->identifier.country && k2->identifier.country) ||
815       (k1->identifier.country && k2->identifier.country &&
816        strcmp(k1->identifier.country, k2->identifier.country)))
817     return FALSE;
818
819   if ((k1->identifier.version && !k2->identifier.version) ||
820       (!k1->identifier.version && k2->identifier.version) ||
821       (k1->identifier.version && k2->identifier.version &&
822        strcmp(k1->identifier.version, k2->identifier.version)))
823     return FALSE;
824
825   return k1->pkcs->public_key_compare(k1->pkcs, k1->public_key, k2->public_key);
826 }
827
828 /* Frees public key */
829
830 void silc_pkcs_silc_public_key_free(const struct SilcPKCSObjectStruct *pkcs,
831                                     void *public_key)
832 {
833   SilcSILCPublicKey silc_pubkey = public_key;
834
835   silc_pubkey->pkcs->public_key_free(silc_pubkey->pkcs,
836                                      silc_pubkey->public_key);
837
838   silc_free(silc_pubkey->identifier.username);
839   silc_free(silc_pubkey->identifier.host);
840   silc_free(silc_pubkey->identifier.realname);
841   silc_free(silc_pubkey->identifier.email);
842   silc_free(silc_pubkey->identifier.org);
843   silc_free(silc_pubkey->identifier.country);
844   silc_free(silc_pubkey->identifier.version);
845   silc_free(silc_pubkey);
846 }
847
848
849 /*************************** Private key routines ****************************/
850
851 /* Private key file magic */
852 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
853
854 /* Imports SILC implementation style private key file */
855
856 SilcBool
857 silc_pkcs_silc_import_private_key_file(const struct SilcPKCSObjectStruct *pkcs,
858                                        unsigned char *filedata,
859                                        SilcUInt32 filedata_len,
860                                        const char *passphrase,
861                                        SilcUInt32 passphrase_len,
862                                        SilcPKCSFileEncoding encoding,
863                                        void **ret_private_key)
864 {
865   SilcCipher aes;
866   SilcHash sha1;
867   SilcHmac sha1hmac;
868   SilcUInt32 blocklen;
869   unsigned char tmp[32], keymat[64], *data = NULL;
870   SilcUInt32 i, len, magic, mac_len;
871   int ret;
872
873   SILC_LOG_DEBUG(("Parsing SILC private key file"));
874
875   /* Check start of file and remove header from the data. */
876   len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
877   if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END)) {
878     SILC_LOG_ERROR(("Malformed SILC private key header"));
879     return FALSE;
880   }
881   for (i = 0; i < len; i++) {
882     if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
883       SILC_LOG_ERROR(("Malformed SILC private key header"));
884       return FALSE;
885     }
886     filedata++;
887   }
888
889   len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
890                         strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
891
892   switch (encoding) {
893   case SILC_PKCS_FILE_BIN:
894     break;
895
896   case SILC_PKCS_FILE_BASE64:
897     data = silc_base64_decode(NULL, filedata, filedata_len, &len);
898     if (!data)
899       return FALSE;
900     filedata = data;
901     break;
902   }
903
904   memset(tmp, 0, sizeof(tmp));
905   memset(keymat, 0, sizeof(keymat));
906
907   /* Check file magic */
908   SILC_GET32_MSB(magic, filedata);
909   if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
910     SILC_LOG_DEBUG(("Private key does not have correct magic"));
911     return FALSE;
912   }
913
914   /* Allocate the AES cipher */
915   if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
916     SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
917     return FALSE;
918   }
919   blocklen = silc_cipher_get_block_len(aes);
920   if (blocklen * 2 > sizeof(tmp)) {
921     silc_cipher_free(aes);
922     return FALSE;
923   }
924
925   /* Allocate SHA1 hash */
926   if (!silc_hash_alloc("sha1", &sha1)) {
927     SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
928     silc_cipher_free(aes);
929     return FALSE;
930   }
931
932   /* Allocate HMAC */
933   if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
934     SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
935     silc_hash_free(sha1);
936     silc_cipher_free(aes);
937     return FALSE;
938   }
939
940   /* Derive the decryption key from the provided key material.  The key
941      is 256 bits length, and derived by taking hash of the data, then
942      re-hashing the data and the previous digest, and using the first and
943      second digest as the key. */
944   silc_hash_init(sha1);
945   silc_hash_update(sha1, passphrase, passphrase_len);
946   silc_hash_final(sha1, keymat);
947   silc_hash_init(sha1);
948   silc_hash_update(sha1, passphrase, passphrase_len);
949   silc_hash_update(sha1, keymat, 16);
950   silc_hash_final(sha1, keymat + 16);
951
952   /* Set the key to the cipher */
953   silc_cipher_set_key(aes, keymat, 256, FALSE);
954
955   /* First, verify the MAC of the private key data */
956   mac_len = silc_hmac_len(sha1hmac);
957   silc_hmac_init_with_key(sha1hmac, keymat, 16);
958   silc_hmac_update(sha1hmac, filedata, len - mac_len);
959   silc_hmac_final(sha1hmac, tmp, NULL);
960   if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
961     SILC_LOG_DEBUG(("Integrity check for private key failed"));
962     memset(keymat, 0, sizeof(keymat));
963     memset(tmp, 0, sizeof(tmp));
964     silc_hmac_free(sha1hmac);
965     silc_hash_free(sha1);
966     silc_cipher_free(aes);
967     return FALSE;
968   }
969   filedata += 4;
970   len -= 4;
971
972   /* Decrypt the private key buffer */
973   silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
974   SILC_GET32_MSB(i, filedata);
975   if (i > len) {
976     SILC_LOG_DEBUG(("Bad private key length in buffer!"));
977     memset(keymat, 0, sizeof(keymat));
978     memset(tmp, 0, sizeof(tmp));
979     silc_hmac_free(sha1hmac);
980     silc_hash_free(sha1);
981     silc_cipher_free(aes);
982     return FALSE;
983   }
984   filedata += 4;
985   len = i;
986
987   /* Cleanup */
988   memset(keymat, 0, sizeof(keymat));
989   memset(tmp, 0, sizeof(tmp));
990   silc_hmac_free(sha1hmac);
991   silc_hash_free(sha1);
992   silc_cipher_free(aes);
993
994   /* Import the private key */
995   ret = silc_pkcs_silc_import_private_key(pkcs, filedata, len, ret_private_key);
996
997   silc_free(data);
998
999   return ret ? TRUE : FALSE;
1000 }
1001
1002 /* Private key version */
1003 #define SILC_PRIVATE_KEY_VERSION_1 0x82171273
1004 #define SILC_PRIVATE_KEY_VERSION_2 0xf911a3d1
1005
1006 /* Imports SILC implementation style private key */
1007
1008 int silc_pkcs_silc_import_private_key(const struct SilcPKCSObjectStruct *pkcs,
1009                                       void *key,
1010                                       SilcUInt32 key_len,
1011                                       void **ret_private_key)
1012 {
1013   SilcBufferStruct buf;
1014   const SilcPKCSAlgorithm *alg;
1015   SilcBufferStruct alg_key;
1016   SilcSILCPrivateKey silc_privkey = NULL;
1017   SilcAsn1 asn1 = NULL;
1018   SilcUInt16 pkcs_len;
1019   SilcUInt32 keydata_len;
1020   unsigned char *pkcs_name = NULL, *key_data;
1021   int ret;
1022
1023   SILC_LOG_DEBUG(("Parsing SILC private key"));
1024
1025   if (!ret_private_key)
1026     return 0;
1027
1028   silc_buffer_set(&buf, (unsigned char *)key, key_len);
1029
1030   /* Get algorithm name and identifier */
1031   ret =
1032     silc_buffer_unformat(&buf,
1033                          SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1034                          SILC_STR_END);
1035   if (ret == -1) {
1036     SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1037     goto err;
1038   }
1039
1040   if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1041     SILC_LOG_DEBUG(("Malformed private key buffer"));
1042     goto err;
1043   }
1044
1045   /* Get key data. We assume that rest of the buffer is key data. */
1046   silc_buffer_pull(&buf, 2 + pkcs_len);
1047   keydata_len = silc_buffer_len(&buf);
1048   ret = silc_buffer_unformat(&buf,
1049                              SILC_STR_UI_XNSTRING(&key_data, keydata_len),
1050                              SILC_STR_END);
1051   if (ret == -1)
1052     goto err;
1053
1054   /* Allocate SILC private key context */
1055   silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
1056   if (!silc_privkey)
1057     goto err;
1058
1059   asn1 = silc_asn1_alloc(NULL);
1060   if (!asn1)
1061     goto err;
1062
1063   if (!strcmp(pkcs_name, "rsa")) {
1064     /* Parse the RSA SILC private key */
1065     SilcBufferStruct k;
1066     SilcMPInt n, e, d, dp, dq, qp, p, q;
1067     unsigned char *tmp;
1068     SilcUInt32 len, ver;
1069
1070     if (keydata_len < 4)
1071       goto err;
1072     silc_buffer_set(&k, key_data, keydata_len);
1073
1074     /* Get version.  Key without the version is old style private key
1075        and we need to do some computation to get it to correct format. */
1076     if (silc_buffer_unformat(&k,
1077                              SILC_STR_UI_INT(&ver),
1078                              SILC_STR_END) < 0)
1079       goto err;
1080     silc_buffer_pull(&k, 4);
1081
1082     if (ver != SILC_PRIVATE_KEY_VERSION_1 &&
1083         ver != SILC_PRIVATE_KEY_VERSION_2) {
1084       len = ver;
1085       ver = 0;
1086     } else {
1087       if (silc_buffer_unformat(&k,
1088                                SILC_STR_UI_INT(&len),
1089                                SILC_STR_END) < 0)
1090         goto err;
1091       silc_buffer_pull(&k, 4);
1092     }
1093
1094     /* Get PKCS object.  Different PKCS #1 scheme is used with different
1095        versions. */
1096     if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) {
1097       /* Version 0 and 1 */
1098       alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
1099     } else {
1100       /* Version 2 and newer */
1101       alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
1102     }
1103     if (!alg) {
1104       SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1105       goto err;
1106     }
1107     silc_privkey->pkcs = alg;
1108
1109     SILC_LOG_DEBUG(("Private key version %s",
1110                     (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" :
1111                      ver == SILC_PRIVATE_KEY_VERSION_2 ? "2" : "0")));
1112
1113     /* Get e */
1114     if (silc_buffer_unformat(&k,
1115                              SILC_STR_DATA(&tmp, len),
1116                              SILC_STR_END) < 0)
1117       goto err;
1118     silc_mp_init(&e);
1119     silc_mp_bin2mp(tmp, len, &e);
1120     silc_buffer_pull(&k, len);
1121
1122     /* Get n */
1123     if (silc_buffer_unformat(&k,
1124                              SILC_STR_UI_INT(&len),
1125                              SILC_STR_END) < 0)
1126       goto err;
1127     silc_buffer_pull(&k, 4);
1128     if (silc_buffer_unformat(&k,
1129                              SILC_STR_DATA(&tmp, len),
1130                              SILC_STR_END) < 0)
1131       goto err;
1132     silc_mp_init(&n);
1133     silc_mp_bin2mp(tmp, len, &n);
1134     silc_buffer_pull(&k, len);
1135
1136     /* Get d */
1137     if (silc_buffer_unformat(&k,
1138                              SILC_STR_UI_INT(&len),
1139                              SILC_STR_END) < 0)
1140       goto err;
1141     silc_buffer_pull(&k, 4);
1142     if (silc_buffer_unformat(&k,
1143                              SILC_STR_DATA(&tmp, len),
1144                              SILC_STR_END) < 0)
1145       goto err;
1146     silc_mp_init(&d);
1147     silc_mp_bin2mp(tmp, len, &d);
1148     silc_buffer_pull(&k, len);
1149
1150     /* Get dP */
1151     if (silc_buffer_unformat(&k,
1152                              SILC_STR_UI_INT(&len),
1153                              SILC_STR_END) < 0)
1154       goto err;
1155     silc_buffer_pull(&k, 4);
1156     if (silc_buffer_unformat(&k,
1157                              SILC_STR_DATA(&tmp, len),
1158                              SILC_STR_END) < 0)
1159       goto err;
1160     silc_mp_init(&dp);
1161     silc_mp_bin2mp(tmp, len, &dp);
1162     silc_buffer_pull(&k, len);
1163
1164     /* Get dQ */
1165     if (silc_buffer_unformat(&k,
1166                              SILC_STR_UI_INT(&len),
1167                              SILC_STR_END) < 0)
1168       goto err;
1169     silc_buffer_pull(&k, 4);
1170     if (silc_buffer_unformat(&k,
1171                              SILC_STR_DATA(&tmp, len),
1172                              SILC_STR_END) < 0)
1173       goto err;
1174     silc_mp_init(&dq);
1175     silc_mp_bin2mp(tmp, len, &dq);
1176     silc_buffer_pull(&k, len);
1177
1178     if (ver == 0) {
1179       /* Old version */
1180
1181       /* Get pQ len */
1182       if (silc_buffer_unformat(&k,
1183                                SILC_STR_UI_INT(&len),
1184                                SILC_STR_END) < 0)
1185         goto err;
1186       silc_buffer_pull(&k, 4);
1187       if (silc_buffer_len(&k) < len)
1188         goto err;
1189       silc_buffer_pull(&k, len);
1190
1191       /* Get qP len */
1192       if (silc_buffer_unformat(&k,
1193                                SILC_STR_UI_INT(&len),
1194                                SILC_STR_END) < 0)
1195         goto err;
1196       silc_buffer_pull(&k, 4);
1197       if (silc_buffer_len(&k) < len)
1198         goto err;
1199       silc_buffer_pull(&k, len);
1200     } else {
1201       /* New version */
1202
1203       /* Get qP */
1204       if (silc_buffer_unformat(&k,
1205                                SILC_STR_UI_INT(&len),
1206                                SILC_STR_END) < 0)
1207         goto err;
1208       silc_buffer_pull(&k, 4);
1209       if (silc_buffer_unformat(&k,
1210                                SILC_STR_DATA(&tmp, len),
1211                                SILC_STR_END) < 0)
1212         goto err;
1213       silc_mp_init(&qp);
1214       silc_mp_bin2mp(tmp, len, &qp);
1215       silc_buffer_pull(&k, len);
1216     }
1217
1218     /* Get p */
1219     if (silc_buffer_unformat(&k,
1220                              SILC_STR_UI_INT(&len),
1221                              SILC_STR_END) < 0)
1222       goto err;
1223     silc_buffer_pull(&k, 4);
1224     if (silc_buffer_unformat(&k,
1225                              SILC_STR_DATA(&tmp, len),
1226                              SILC_STR_END) < 0)
1227       goto err;
1228     silc_mp_init(&p);
1229     silc_mp_bin2mp(tmp, len, &p);
1230     silc_buffer_pull(&k, len);
1231
1232     /* Get q */
1233     if (silc_buffer_unformat(&k,
1234                              SILC_STR_UI_INT(&len),
1235                              SILC_STR_END) < 0)
1236       goto err;
1237     silc_buffer_pull(&k, 4);
1238     if (silc_buffer_unformat(&k,
1239                              SILC_STR_DATA(&tmp, len),
1240                              SILC_STR_END) < 0)
1241       goto err;
1242     silc_mp_init(&q);
1243     silc_mp_bin2mp(tmp, len, &q);
1244     silc_buffer_pull(&k, len);
1245
1246     if (ver == 0) {
1247       /* Old version.  Compute to new version */
1248       SILC_LOG_DEBUG(("Old version private key"));
1249       silc_mp_init(&qp);
1250       silc_mp_modinv(&qp, &q, &p);
1251     }
1252
1253     /* Encode to PKCS #1 format */
1254     memset(&alg_key, 0, sizeof(alg_key));
1255     if (!silc_asn1_encode(asn1, &alg_key,
1256                           SILC_ASN1_SEQUENCE,
1257                             SILC_ASN1_SHORT_INT(0),
1258                             SILC_ASN1_INT(&n),
1259                             SILC_ASN1_INT(&e),
1260                             SILC_ASN1_INT(&d),
1261                             SILC_ASN1_INT(&p),
1262                             SILC_ASN1_INT(&q),
1263                             SILC_ASN1_INT(&dp),
1264                             SILC_ASN1_INT(&dq),
1265                             SILC_ASN1_INT(&qp),
1266                           SILC_ASN1_END, SILC_ASN1_END))
1267       goto err;
1268
1269     silc_mp_uninit(&n);
1270     silc_mp_uninit(&e);
1271     silc_mp_uninit(&e);
1272     silc_mp_uninit(&d);
1273     silc_mp_uninit(&p);
1274     silc_mp_uninit(&q);
1275     silc_mp_uninit(&dp);
1276     silc_mp_uninit(&dq);
1277     silc_mp_uninit(&qp);
1278
1279   } else if (!strcmp(pkcs_name, "dsa")) {
1280     SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
1281     goto err;
1282
1283   } else {
1284     SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1285     goto err;
1286   }
1287
1288   /* Import PKCS algorithm private key */
1289   if (!alg->import_private_key(alg, alg_key.data, silc_buffer_len(&alg_key),
1290                                &silc_privkey->private_key))
1291     goto err;
1292
1293   silc_free(pkcs_name);
1294   silc_asn1_free(asn1);
1295
1296   *ret_private_key = silc_privkey;
1297
1298   return key_len;
1299
1300  err:
1301   silc_free(pkcs_name);
1302   silc_free(silc_privkey);
1303   if (asn1)
1304     silc_asn1_free(asn1);
1305   SILC_LOG_ERROR(("Malformed SILC private key "));
1306   return 0;
1307 }
1308
1309 /* Exports private key as SILC implementation style private key file */
1310
1311 unsigned char *
1312 silc_pkcs_silc_export_private_key_file(const struct SilcPKCSObjectStruct *pkcs,
1313                                        SilcStack stack,
1314                                        void *private_key,
1315                                        const char *passphrase,
1316                                        SilcUInt32 passphrase_len,
1317                                        SilcPKCSFileEncoding encoding,
1318                                        SilcRng rng,
1319                                        SilcUInt32 *ret_len)
1320 {
1321   SilcCipher aes;
1322   SilcHash sha1;
1323   SilcHmac sha1hmac;
1324   SilcBuffer buf, enc;
1325   SilcUInt32 len, blocklen, padlen, key_len;
1326   unsigned char *key, *data;
1327   unsigned char tmp[32], keymat[64];
1328   int i;
1329
1330   SILC_LOG_DEBUG(("Encoding SILC private key file"));
1331
1332   /* Export the private key */
1333   key = silc_pkcs_silc_export_private_key(pkcs, stack, private_key, &key_len);
1334   if (!key)
1335     return NULL;
1336
1337   memset(tmp, 0, sizeof(tmp));
1338   memset(keymat, 0, sizeof(keymat));
1339
1340   /* Allocate the AES cipher */
1341   if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1342     SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1343     silc_sfree(stack, key);
1344     return NULL;
1345   }
1346   blocklen = silc_cipher_get_block_len(aes);
1347   if (blocklen * 2 > sizeof(tmp)) {
1348     silc_cipher_free(aes);
1349     silc_sfree(stack, key);
1350     return NULL;
1351   }
1352
1353   /* Allocate SHA1 hash */
1354   if (!silc_hash_alloc("sha1", &sha1)) {
1355     SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1356     silc_sfree(stack, key);
1357     silc_cipher_free(aes);
1358     return NULL;
1359   }
1360
1361   /* Allocate HMAC */
1362   if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1363     SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1364     silc_sfree(stack, key);
1365     silc_hash_free(sha1);
1366     silc_cipher_free(aes);
1367     return NULL;
1368   }
1369
1370   /* Derive the encryption key from the provided key material.  The key
1371      is 256 bits length, and derived by taking hash of the data, then
1372      re-hashing the data and the previous digest, and using the first and
1373      second digest as the key. */
1374   silc_hash_init(sha1);
1375   silc_hash_update(sha1, passphrase, passphrase_len);
1376   silc_hash_final(sha1, keymat);
1377   silc_hash_init(sha1);
1378   silc_hash_update(sha1, passphrase, passphrase_len);
1379   silc_hash_update(sha1, keymat, 16);
1380   silc_hash_final(sha1, keymat + 16);
1381
1382   /* Set the key to the cipher */
1383   silc_cipher_set_key(aes, keymat, 256, TRUE);
1384
1385   /* Encode the buffer to be encrypted.  Add padding to it too, at least
1386      block size of the cipher. */
1387
1388   /* Allocate buffer for encryption */
1389   len = silc_hmac_len(sha1hmac);
1390   padlen = 16 + (16 - ((key_len + 4) % blocklen));
1391   enc = silc_buffer_salloc_size(stack, 4 + 4 + key_len + padlen + len);
1392   if (!enc) {
1393     silc_sfree(stack, key);
1394     silc_hmac_free(sha1hmac);
1395     silc_hash_free(sha1);
1396     silc_cipher_free(aes);
1397     return FALSE;
1398   }
1399
1400   /* Generate padding */
1401   for (i = 0; i < padlen; i++)
1402     tmp[i] = silc_rng_get_byte_fast(rng);
1403
1404   /* Put magic number */
1405   SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1406   silc_buffer_pull(enc, 4);
1407
1408   /* Encode the buffer */
1409   silc_buffer_sformat(stack, enc,
1410                       SILC_STR_UI_INT(key_len),
1411                       SILC_STR_UI_XNSTRING(key, key_len),
1412                       SILC_STR_UI_XNSTRING(tmp, padlen),
1413                       SILC_STR_END);
1414   silc_sfree(stack, key);
1415
1416   /* Encrypt. */
1417   silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1418                       silc_cipher_get_iv(aes));
1419
1420   silc_buffer_push(enc, 4);
1421
1422   /* Compute HMAC over the encrypted data and append the MAC to data.
1423      The key is the first digest of the original key material. */
1424   key_len = silc_buffer_len(enc) - len;
1425   silc_hmac_init_with_key(sha1hmac, keymat, 16);
1426   silc_hmac_update(sha1hmac, enc->data, key_len);
1427   silc_buffer_pull(enc, key_len);
1428   silc_hmac_final(sha1hmac, enc->data, NULL);
1429   silc_buffer_push(enc, key_len);
1430
1431   /* Cleanup */
1432   memset(keymat, 0, sizeof(keymat));
1433   memset(tmp, 0, sizeof(tmp));
1434   silc_hmac_free(sha1hmac);
1435   silc_hash_free(sha1);
1436   silc_cipher_free(aes);
1437
1438   switch (encoding) {
1439   case SILC_PKCS_FILE_BIN:
1440     break;
1441
1442   case SILC_PKCS_FILE_BASE64:
1443     data = silc_base64_encode_file(stack, enc->data, silc_buffer_len(enc));
1444     if (!data) {
1445       silc_buffer_clear(enc);
1446       silc_buffer_sfree(stack, enc);
1447       return NULL;
1448     }
1449     silc_sfree(stack, silc_buffer_steal(enc, NULL));
1450     silc_buffer_set(enc, data, strlen(data));
1451     break;
1452   }
1453
1454   key = enc->data;
1455   key_len = silc_buffer_len(enc);
1456
1457   /* Encode the data and save to file */
1458   len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1459                    strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1460   buf = silc_buffer_salloc_size(stack, len);
1461   if (!buf) {
1462     silc_buffer_sfree(stack, enc);
1463     return NULL;
1464   }
1465   silc_buffer_sformat(stack, buf,
1466                       SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1467                       SILC_STR_UI_XNSTRING(key, key_len),
1468                       SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1469                       SILC_STR_END);
1470
1471   silc_buffer_sfree(stack, enc);
1472   data = silc_buffer_steal(buf, ret_len);
1473   silc_buffer_sfree(stack, buf);
1474
1475   return data;
1476 }
1477
1478 /* Exports private key as SILC implementation style private key */
1479
1480 unsigned char *
1481 silc_pkcs_silc_export_private_key(const struct SilcPKCSObjectStruct *pkcs,
1482                                   SilcStack stack,
1483                                   void *private_key,
1484                                   SilcUInt32 *ret_len)
1485 {
1486   SilcSILCPrivateKey silc_privkey = private_key;
1487   const SilcPKCSAlgorithm *alg = silc_privkey->pkcs;
1488   SilcBufferStruct alg_key;
1489   SilcBuffer buf = NULL;
1490   SilcAsn1 asn1 = NULL;
1491   unsigned char *prv = NULL, *key = NULL, *ret;
1492   SilcUInt32 prv_len, key_len, totlen;
1493
1494   SILC_LOG_DEBUG(("Encoding SILC private key"));
1495
1496   /* Export PKCS algorithm private key */
1497   if (alg->export_private_key)
1498     prv = alg->export_private_key(alg, stack,
1499                                   silc_privkey->private_key, &prv_len);
1500   if (!prv)
1501     return NULL;
1502   silc_buffer_set(&alg_key, prv, prv_len);
1503
1504   asn1 = silc_asn1_alloc(stack);
1505   if (!asn1)
1506     goto err;
1507
1508   if (!strcmp(alg->name, "rsa")) {
1509     /* Parse the PKCS #1 private key */
1510     SilcMPInt n, e, d, dp, dq, qp, p, q;
1511     SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
1512       qp_len, p_len, q_len, len = 0;
1513     unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
1514
1515     if (!silc_asn1_decode(asn1, &alg_key,
1516                           SILC_ASN1_SEQUENCE,
1517                             SILC_ASN1_INT(NULL),
1518                             SILC_ASN1_INT(&n),
1519                             SILC_ASN1_INT(&e),
1520                             SILC_ASN1_INT(&d),
1521                             SILC_ASN1_INT(&p),
1522                             SILC_ASN1_INT(&q),
1523                             SILC_ASN1_INT(&dp),
1524                             SILC_ASN1_INT(&dq),
1525                             SILC_ASN1_INT(&qp),
1526                           SILC_ASN1_END, SILC_ASN1_END))
1527       goto err;
1528
1529     /* Encode to SILC RSA private key */
1530     eb = silc_mp_mp2bin(&e, 0, &e_len);
1531     nb = silc_mp_mp2bin(&n, 0, &n_len);
1532     db = silc_mp_mp2bin(&d, 0, &d_len);
1533     dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
1534     dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
1535     qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
1536     pb = silc_mp_mp2bin(&p, 0, &p_len);
1537     qb = silc_mp_mp2bin(&q, 0, &q_len);
1538     len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
1539       dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
1540
1541     buf = silc_buffer_salloc_size(stack, len);
1542     if (!buf)
1543       goto err;
1544     if (silc_buffer_sformat(stack, buf,
1545                             SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
1546                             SILC_STR_UI_INT(e_len),
1547                             SILC_STR_UI_XNSTRING(eb, e_len),
1548                             SILC_STR_UI_INT(n_len),
1549                             SILC_STR_UI_XNSTRING(nb, n_len),
1550                             SILC_STR_UI_INT(d_len),
1551                             SILC_STR_UI_XNSTRING(db, d_len),
1552                             SILC_STR_UI_INT(dp_len),
1553                             SILC_STR_UI_XNSTRING(dpb, dp_len),
1554                             SILC_STR_UI_INT(dq_len),
1555                             SILC_STR_UI_XNSTRING(dqb, dq_len),
1556                             SILC_STR_UI_INT(qp_len),
1557                             SILC_STR_UI_XNSTRING(qpb, qp_len),
1558                             SILC_STR_UI_INT(p_len),
1559                             SILC_STR_UI_XNSTRING(pb, p_len),
1560                             SILC_STR_UI_INT(q_len),
1561                             SILC_STR_UI_XNSTRING(qb, q_len),
1562                             SILC_STR_END) < 0)
1563       goto err;
1564
1565     key = silc_buffer_steal(buf, &key_len);
1566     silc_buffer_sfree(stack, buf);
1567     silc_free(nb);
1568     silc_free(eb);
1569     silc_free(db);
1570     silc_free(dpb);
1571     silc_free(dqb);
1572     silc_free(qpb);
1573     silc_free(pb);
1574     silc_free(qb);
1575
1576   } else if (!strcmp(alg->name, "dsa")) {
1577     SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
1578     goto err;
1579
1580   } else {
1581     SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1582     goto err;
1583   }
1584
1585   /* Encode SILC private key */
1586   totlen = 2 + strlen(alg->name) + key_len;
1587   buf = silc_buffer_salloc_size(stack, totlen);
1588   if (!buf)
1589     goto err;
1590   if (silc_buffer_sformat(stack, buf,
1591                           SILC_STR_UI_SHORT(strlen(alg->name)),
1592                           SILC_STR_UI32_STRING(alg->name),
1593                           SILC_STR_UI_XNSTRING(key, key_len),
1594                           SILC_STR_END) < 0)
1595     goto err;
1596
1597   ret = silc_buffer_steal(buf, ret_len);
1598   silc_buffer_sfree(stack, buf);
1599   silc_sfree(stack, prv);
1600   silc_sfree(stack, key);
1601   silc_asn1_free(asn1);
1602
1603   return ret;
1604
1605  err:
1606   silc_sfree(stack, prv);
1607   silc_sfree(stack, key);
1608   silc_buffer_sfree(stack, buf);
1609   return NULL;
1610 }
1611
1612 /* Return key length */
1613
1614 SilcUInt32
1615 silc_pkcs_silc_private_key_bitlen(const struct SilcPKCSObjectStruct *pkcs,
1616                                   void *private_key)
1617 {
1618   SilcSILCPrivateKey silc_privkey = private_key;
1619   return silc_privkey->pkcs->private_key_bitlen(silc_privkey->pkcs,
1620                                                 silc_privkey->private_key);
1621 }
1622
1623 /* Frees private key */
1624
1625 void silc_pkcs_silc_private_key_free(const struct SilcPKCSObjectStruct *pkcs,
1626                                      void *private_key)
1627 {
1628   SilcSILCPrivateKey silc_privkey = private_key;
1629
1630   silc_privkey->pkcs->private_key_free(silc_privkey->pkcs,
1631                                        silc_privkey->private_key);
1632   silc_free(silc_privkey);
1633 }
1634
1635
1636 /***************************** PKCS operations ******************************/
1637
1638 /* Encrypts as specified in SILC protocol specification */
1639
1640 SilcAsyncOperation
1641 silc_pkcs_silc_encrypt(const struct SilcPKCSObjectStruct *pkcs,
1642                        void *public_key,
1643                        unsigned char *src,
1644                        SilcUInt32 src_len,
1645                        SilcRng rng,
1646                        SilcPKCSEncryptCb encrypt_cb,
1647                        void *context)
1648 {
1649   SilcSILCPublicKey silc_pubkey = public_key;
1650
1651   if (!silc_pubkey->pkcs->encrypt) {
1652     encrypt_cb(FALSE, NULL, 0, context);
1653     return NULL;
1654   }
1655
1656   return silc_pubkey->pkcs->encrypt(silc_pubkey->pkcs,
1657                                     silc_pubkey->public_key,
1658                                     src, src_len, rng, encrypt_cb, context);
1659 }
1660
1661 /* Decrypts as specified in SILC protocol specification */
1662
1663 SilcAsyncOperation
1664 silc_pkcs_silc_decrypt(const struct SilcPKCSObjectStruct *pkcs,
1665                        void *private_key,
1666                        unsigned char *src,
1667                        SilcUInt32 src_len,
1668                        SilcPKCSDecryptCb decrypt_cb,
1669                        void *context)
1670 {
1671   SilcSILCPrivateKey silc_privkey = private_key;
1672
1673   if (!silc_privkey->pkcs->decrypt) {
1674     decrypt_cb(FALSE, NULL, 0, context);
1675     return NULL;
1676   }
1677
1678   return silc_privkey->pkcs->decrypt(silc_privkey->pkcs,
1679                                      silc_privkey->private_key,
1680                                      src, src_len, decrypt_cb, context);
1681 }
1682
1683 /* Signs as specified in SILC protocol specification */
1684
1685 SilcAsyncOperation
1686 silc_pkcs_silc_sign(const struct SilcPKCSObjectStruct *pkcs,
1687                     void *private_key,
1688                     unsigned char *src,
1689                     SilcUInt32 src_len,
1690                     SilcBool compute_hash,
1691                     SilcHash hash,
1692                     SilcPKCSSignCb sign_cb,
1693                     void *context)
1694 {
1695   SilcSILCPrivateKey silc_privkey = private_key;
1696
1697   if (!silc_privkey->pkcs->sign) {
1698     sign_cb(FALSE, NULL, 0, context);
1699     return NULL;
1700   }
1701
1702   return silc_privkey->pkcs->sign(silc_privkey->pkcs,
1703                                   silc_privkey->private_key,
1704                                   src, src_len,
1705                                   compute_hash, hash,
1706                                   sign_cb, context);
1707 }
1708
1709 /* Verifies as specified in SILC protocol specification */
1710
1711 SilcAsyncOperation
1712 silc_pkcs_silc_verify(const struct SilcPKCSObjectStruct *pkcs,
1713                       void *public_key,
1714                       unsigned char *signature,
1715                       SilcUInt32 signature_len,
1716                       unsigned char *data,
1717                       SilcUInt32 data_len,
1718                       SilcHash hash,
1719                       SilcPKCSVerifyCb verify_cb,
1720                       void *context)
1721 {
1722   SilcSILCPublicKey silc_pubkey = public_key;
1723
1724   if (!silc_pubkey->pkcs->verify) {
1725     verify_cb(FALSE, context);
1726     return NULL;
1727   }
1728
1729   return silc_pubkey->pkcs->verify(silc_pubkey->pkcs,
1730                                    silc_pubkey->public_key,
1731                                    signature, signature_len,
1732                                    data, data_len, hash,
1733                                    verify_cb, context);
1734 }