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