Added checks for encryption/decryption lengths that they must
[silc.git] / lib / silccrypt / silcpkcs.c
1 /*
2
3   silcpkcs.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silcincludes.h"
22
23 #include "rsa.h"
24 #include "pkcs1.h"
25
26 /* The main SILC PKCS structure. */
27 struct SilcPKCSStruct {
28   void *context;                /* Algorithm internal context */
29   SilcPKCSObject *pkcs;         /* Algorithm implementation */
30   SilcUInt32 key_len;           /* Key length in bits */
31 };
32
33 #ifndef SILC_EPOC
34 /* Dynamically registered list of PKCS. */
35 SilcDList silc_pkcs_list = NULL;
36 #define SILC_PKCS_LIST silc_pkcs_list
37 #else
38 #define SILC_PKCS_LIST TRUE
39 #endif /* SILC_EPOC */
40
41 /* Static list of PKCS for silc_pkcs_register_default(). */
42 const SilcPKCSObject silc_default_pkcs[] =
43 {
44   /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
45   { "rsa", 
46     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
47     silc_rsa_get_private_key, silc_rsa_set_public_key,
48     silc_rsa_set_private_key, silc_rsa_context_len,
49     silc_pkcs1_encrypt, silc_pkcs1_decrypt,
50     silc_pkcs1_sign, silc_pkcs1_verify },
51
52   /* Raw RSA operations */
53   { "rsa-raw", 
54     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
55     silc_rsa_get_private_key, silc_rsa_set_public_key,
56     silc_rsa_set_private_key, silc_rsa_context_len,
57     silc_rsa_encrypt, silc_rsa_decrypt,
58     silc_rsa_sign, silc_rsa_verify },
59
60   { NULL, NULL, NULL, NULL, NULL,
61     NULL, NULL, NULL, NULL, NULL, NULL }
62 };
63
64 /* Register a new PKCS into SILC. This is used at the initialization of
65    the SILC. */
66
67 bool silc_pkcs_register(const SilcPKCSObject *pkcs)
68 {
69 #ifndef SILC_EPOC
70   SilcPKCSObject *new;
71
72   SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
73
74   /* Check if exists already */
75   if (silc_pkcs_list) {
76     SilcPKCSObject *entry;
77     silc_dlist_start(silc_pkcs_list);
78     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
79       if (!strcmp(entry->name, pkcs->name))
80         return FALSE;
81     }
82   }
83
84   new = silc_calloc(1, sizeof(*new));
85   new->name = strdup(pkcs->name);
86   new->init = pkcs->init;
87   new->clear_keys = pkcs->clear_keys;
88   new->get_public_key = pkcs->get_public_key;
89   new->get_private_key = pkcs->get_private_key;
90   new->set_public_key = pkcs->set_public_key;
91   new->set_private_key = pkcs->set_private_key;
92   new->context_len = pkcs->context_len;
93   new->encrypt = pkcs->encrypt;
94   new->decrypt = pkcs->decrypt;
95   new->sign = pkcs->sign;
96   new->verify = pkcs->verify;
97
98   /* Add to list */
99   if (silc_pkcs_list == NULL)
100     silc_pkcs_list = silc_dlist_init();
101   silc_dlist_add(silc_pkcs_list, new);
102
103 #endif /* SILC_EPOC */
104   return TRUE;
105 }
106
107 /* Unregister a PKCS from the SILC. */
108
109 bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
110 {
111 #ifndef SILC_EPOC
112   SilcPKCSObject *entry;
113
114   SILC_LOG_DEBUG(("Unregistering PKCS"));
115
116   if (!silc_pkcs_list)
117     return FALSE;
118
119   silc_dlist_start(silc_pkcs_list);
120   while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
121     if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
122       silc_dlist_del(silc_pkcs_list, entry);
123       silc_free(entry->name);
124       silc_free(entry);
125
126       if (silc_dlist_count(silc_pkcs_list) == 0) {
127         silc_dlist_uninit(silc_pkcs_list);
128         silc_pkcs_list = NULL;
129       }
130
131       return TRUE;
132     }
133   }
134
135 #endif /* SILC_EPOC */
136   return FALSE;
137 }
138
139 /* Function that registers all the default PKCS (all builtin PKCS). 
140    The application may use this to register the default PKCS if specific
141    PKCS in any specific order is not wanted. */
142
143 bool silc_pkcs_register_default(void)
144 {
145 #ifndef SILC_EPOC
146   int i;
147
148   for (i = 0; silc_default_pkcs[i].name; i++)
149     silc_pkcs_register(&(silc_default_pkcs[i]));
150
151 #endif /* SILC_EPOC */
152   return TRUE;
153 }
154
155 bool silc_pkcs_unregister_all(void)
156 {
157 #ifndef SILC_EPOC
158   SilcPKCSObject *entry;
159
160   if (!silc_pkcs_list)
161     return FALSE;
162
163   silc_dlist_start(silc_pkcs_list);
164   while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
165     silc_pkcs_unregister(entry);
166     if (!silc_pkcs_list)
167       break;
168   }
169 #endif /* SILC_EPOC */
170   return TRUE;
171 }
172
173 /* Allocates a new SilcPKCS object. The new allocated object is returned
174    to the 'new_pkcs' argument. */
175
176 bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
177 {
178   SilcPKCSObject *entry = NULL;
179
180   SILC_LOG_DEBUG(("Allocating new PKCS object"));
181
182 #ifndef SILC_EPOC
183   if (silc_pkcs_list) {
184     silc_dlist_start(silc_pkcs_list);
185     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
186       if (!strcmp(entry->name, name))
187         break;
188     }
189   }
190 #else
191   {
192     /* On EPOC which don't have globals we check our constant hash list. */
193     int i;
194     for (i = 0; silc_default_pkcs[i].name; i++) {
195       if (!strcmp(silc_default_pkcs[i].name, name)) {
196         entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
197         break;
198       }
199     }
200   }
201 #endif /* SILC_EPOC */
202
203   if (entry) {
204     *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
205     (*new_pkcs)->pkcs = entry;
206     (*new_pkcs)->context = silc_calloc(1, entry->context_len());
207     return TRUE;
208   }
209
210   return FALSE;
211 }
212
213 /* Free's the PKCS object */
214
215 void silc_pkcs_free(SilcPKCS pkcs)
216 {
217   if (pkcs) {
218     pkcs->pkcs->clear_keys(pkcs->context);
219     silc_free(pkcs->context);
220   }
221   silc_free(pkcs);
222 }
223
224 /* Return TRUE if PKCS algorithm `name' is supported. */
225
226 bool silc_pkcs_is_supported(const unsigned char *name)
227 {
228 #ifndef SILC_EPOC
229   SilcPKCSObject *entry;
230
231   if (silc_pkcs_list) {
232     silc_dlist_start(silc_pkcs_list);
233     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
234       if (!strcmp(entry->name, name))
235         return TRUE;
236     }
237   }
238 #else
239   {
240     int i;
241     for (i = 0; silc_default_pkcs[i].name; i++)
242       if (!strcmp(silc_default_pkcs[i].name, name))
243         return TRUE;
244   }
245 #endif /* SILC_EPOC */
246   return FALSE;
247 }
248
249 /* Returns comma separated list of supported PKCS algorithms */
250
251 char *silc_pkcs_get_supported(void)
252 {
253   SilcPKCSObject *entry;
254   char *list = NULL;
255   int len = 0;
256
257 #ifndef SILC_EPOC
258   if (silc_pkcs_list) {
259     silc_dlist_start(silc_pkcs_list);
260     while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
261       len += strlen(entry->name);
262       list = silc_realloc(list, len + 1);
263       
264       memcpy(list + (len - strlen(entry->name)), 
265              entry->name, strlen(entry->name));
266       memcpy(list + len, ",", 1);
267       len++;
268     }
269   }
270 #else
271   {
272     int i;
273     for (i = 0; silc_default_pkcs[i].name; i++) {
274       entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
275       len += strlen(entry->name);
276       list = silc_realloc(list, len + 1);
277       
278       memcpy(list + (len - strlen(entry->name)), 
279              entry->name, strlen(entry->name));
280       memcpy(list + len, ",", 1);
281       len++;
282     }
283   }
284 #endif /* SILC_EPOC */
285
286   list[len - 1] = 0;
287
288   return list;
289 }
290
291 /* Generate new key pair into the `pkcs' context. */
292
293 bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
294                             SilcRng rng)
295 {
296   return pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
297 }
298
299 /* Returns the length of the key */
300
301 SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
302 {
303   return pkcs->key_len;
304 }
305
306 const char *silc_pkcs_get_name(SilcPKCS pkcs)
307 {
308   return pkcs->pkcs->name;
309 }
310
311 /* Returns SILC style public key */
312
313 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
314 {
315   return pkcs->pkcs->get_public_key(pkcs->context, len);
316 }
317
318 /* Returns SILC style private key */
319
320 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
321 {
322   return pkcs->pkcs->get_private_key(pkcs->context, len);
323 }
324
325 /* Sets public key from SilcPublicKey. */
326
327 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
328 {
329   pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk, 
330                                              public_key->pk_len);
331   return pkcs->key_len;
332 }
333
334 /* Sets public key from data. */
335
336 SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
337                                      SilcUInt32 pk_len)
338 {
339   pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
340   return pkcs->key_len;
341 }
342
343 /* Sets private key from SilcPrivateKey. */
344
345 SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
346 {
347   SilcUInt32 key_len;
348   key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv, 
349                                         private_key->prv_len);
350   if (!pkcs->key_len)
351     pkcs->key_len = key_len;
352   return pkcs->key_len;
353 }
354
355 /* Sets private key from data. */
356
357 SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
358                                           SilcUInt32 prv_len)
359 {
360   SilcUInt32 key_len;
361   key_len = pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
362   if (!pkcs->key_len)
363     pkcs->key_len = key_len;
364   return pkcs->key_len;
365 }
366
367 /* Encrypts */
368
369 bool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
370                        unsigned char *dst, SilcUInt32 *dst_len)
371 {
372   return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
373 }
374
375 /* Decrypts */
376
377 bool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
378                        unsigned char *dst, SilcUInt32 *dst_len)
379 {
380   return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
381 }
382
383 /* Generates signature */
384
385 bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
386                     unsigned char *dst, SilcUInt32 *dst_len)
387 {
388   return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
389 }
390
391 /* Verifies signature */
392
393 bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature, 
394                       SilcUInt32 signature_len, unsigned char *data, 
395                       SilcUInt32 data_len)
396 {
397   return pkcs->pkcs->verify(pkcs->context, signature, signature_len, 
398                             data, data_len);
399 }
400
401 /* Generates signature with hash. The hash is signed. */
402
403 bool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
404                               unsigned char *src, SilcUInt32 src_len,
405                               unsigned char *dst, SilcUInt32 *dst_len)
406 {
407   unsigned char hashr[32];
408   SilcUInt32 hash_len;
409   int ret;
410
411   silc_hash_make(hash, src, src_len, hashr);
412   hash_len = silc_hash_len(hash);
413
414   SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
415
416   ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
417   memset(hashr, 0, sizeof(hashr));
418
419   return ret;
420 }
421
422 /* Verifies signature with hash. The `data' is hashed and verified against
423    the `signature'. */
424
425 bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash, 
426                                 unsigned char *signature, 
427                                 SilcUInt32 signature_len, 
428                                 unsigned char *data, 
429                                 SilcUInt32 data_len)
430 {
431   unsigned char hashr[32];
432   SilcUInt32 hash_len;
433   int ret;
434
435   silc_hash_make(hash, data, data_len, hashr);
436   hash_len = silc_hash_len(hash);
437
438   SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
439
440   ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len, 
441                            hashr, hash_len);
442   memset(hashr, 0, sizeof(hashr));
443
444   return ret;
445 }
446
447 /* Encodes and returns SILC public key identifier. If some of the 
448    arguments is NULL those are not encoded into the identifier string.
449    Protocol says that at least username and host must be provided. */
450
451 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
452                                   char *email, char *org, char *country)
453 {
454   SilcBuffer buf;
455   char *identifier;
456   SilcUInt32 len, tlen = 0;
457
458   if (!username || !host)
459     return NULL;
460
461   len = (username ? strlen(username) : 0) +
462         (host     ? strlen(host)     : 0) +
463         (realname ? strlen(realname) : 0) +
464         (email    ? strlen(email)    : 0) +
465         (org      ? strlen(org)      : 0) +
466         (country  ? strlen(country)  : 0);
467   
468   if (len < 3)
469     return NULL;
470
471   len += 3 + 5 + 5 + 4 + 4 + 4;
472   buf = silc_buffer_alloc(len);
473   silc_buffer_pull_tail(buf, len);
474
475   if (username) {
476     silc_buffer_format(buf,
477                        SILC_STR_UI32_STRING("UN="),
478                        SILC_STR_UI32_STRING(username),
479                        SILC_STR_END);
480     silc_buffer_pull(buf, 3 + strlen(username));
481     tlen = 3 + strlen(username); 
482   }
483     
484   if (host) {
485     silc_buffer_format(buf,
486                        SILC_STR_UI32_STRING(", "),
487                        SILC_STR_UI32_STRING("HN="),
488                        SILC_STR_UI32_STRING(host),
489                        SILC_STR_END);
490     silc_buffer_pull(buf, 5 + strlen(host));
491     tlen += 5 + strlen(host); 
492   }
493
494   if (realname) {
495     silc_buffer_format(buf,
496                        SILC_STR_UI32_STRING(", "),
497                        SILC_STR_UI32_STRING("RN="),
498                        SILC_STR_UI32_STRING(realname),
499                        SILC_STR_END);
500     silc_buffer_pull(buf, 5 + strlen(realname));
501     tlen += 5 + strlen(realname); 
502   }
503
504   if (email) {
505     silc_buffer_format(buf,
506                        SILC_STR_UI32_STRING(", "),
507                        SILC_STR_UI32_STRING("E="),
508                        SILC_STR_UI32_STRING(email),
509                        SILC_STR_END);
510     silc_buffer_pull(buf, 4 + strlen(email));
511     tlen += 4 + strlen(email); 
512   }
513
514   if (org) {
515     silc_buffer_format(buf,
516                        SILC_STR_UI32_STRING(", "),
517                        SILC_STR_UI32_STRING("O="),
518                        SILC_STR_UI32_STRING(org),
519                        SILC_STR_END);
520     silc_buffer_pull(buf, 4 + strlen(org));
521     tlen += 4 + strlen(org); 
522   }
523
524   if (country) {
525     silc_buffer_format(buf,
526                        SILC_STR_UI32_STRING(", "),
527                        SILC_STR_UI32_STRING("C="),
528                        SILC_STR_UI32_STRING(country),
529                        SILC_STR_END);
530     silc_buffer_pull(buf, 4 + strlen(country));
531     tlen += 4 + strlen(country); 
532   }
533
534   silc_buffer_push(buf, buf->data - buf->head);
535   identifier = silc_calloc(tlen + 1, sizeof(*identifier));
536   memcpy(identifier, buf->data, tlen);
537   silc_buffer_free(buf);
538
539   return identifier;
540 }
541
542 /* Decodes the provided `identifier' and returns allocated context for
543    the identifier. */
544
545 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
546 {
547   SilcPublicKeyIdentifier ident;
548   char *cp, *item;
549   int len;
550
551   ident = silc_calloc(1, sizeof(*ident));
552
553   cp = identifier;
554   while (cp) {
555     len = strcspn(cp, ",");
556     if (len - 1 >= 0 && cp[len - 1] == '\\') {
557       while (cp) {
558         cp += len + 1;
559         len = strcspn(cp, ",") + len;
560         if (len - 1 >= 0 && cp[len - 1] != '\\')
561           break;
562       }
563     }
564
565     item = silc_calloc(len + 1, sizeof(char));
566     memcpy(item, cp, len);
567
568     if (strstr(item, "UN="))
569       ident->username = strdup(item + strcspn(cp, "=") + 1);
570     else if (strstr(item, "HN="))
571       ident->host = strdup(item + strcspn(cp, "=") + 1);
572     else if (strstr(item, "RN="))
573       ident->realname = strdup(item + strcspn(cp, "=") + 1);
574     else if (strstr(item, "E="))
575       ident->email = strdup(item + strcspn(cp, "=") + 1);
576     else if (strstr(item, "O="))
577       ident->org = strdup(item + strcspn(cp, "=") + 1);
578     else if (strstr(item, "C="))
579       ident->country = strdup(item + strcspn(cp, "=") + 1);
580     
581     cp += len;
582     if (strlen(cp) == 0)
583       cp = NULL;
584     else
585       cp += 1;
586     
587     if (item)
588       silc_free(item);
589   }
590
591   return ident;
592 }
593
594 /* Free's decoded public key identifier context. Call this to free the
595    context returned by the silc_pkcs_decode_identifier. */
596
597 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
598 {
599   silc_free(identifier->username);
600   silc_free(identifier->host);
601   silc_free(identifier->realname);
602   silc_free(identifier->email);
603   silc_free(identifier->org);
604   silc_free(identifier->country);
605   silc_free(identifier);
606 }
607
608 /* Allocates SILC style public key formed from sent arguments. All data
609    is duplicated. */
610
611 SilcPublicKey silc_pkcs_public_key_alloc(const char *name, 
612                                          const char *identifier,
613                                          const unsigned char *pk, 
614                                          SilcUInt32 pk_len)
615 {
616   SilcPublicKey public_key;
617   char *tmp = NULL;
618
619   public_key = silc_calloc(1, sizeof(*public_key));
620   public_key->name = strdup(name);
621   public_key->pk_len = pk_len;
622   public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
623   public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
624   memcpy(public_key->pk, pk, pk_len);
625
626   if (!silc_utf8_valid(identifier, strlen(identifier))) {
627     int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
628     tmp = silc_calloc(len + 1, sizeof(*tmp));
629     silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
630     identifier = tmp;
631   }
632
633   public_key->identifier = strdup(identifier);
634   public_key->len = 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
635   silc_free(tmp);
636
637   return public_key;
638 }
639
640 /* Free's public key */
641
642 void silc_pkcs_public_key_free(SilcPublicKey public_key)
643 {
644   if (public_key) {
645     silc_free(public_key->name);
646     silc_free(public_key->identifier);
647     silc_free(public_key->pk);
648     silc_free(public_key);
649   }
650 }
651
652 /* Allocates SILC private key formed from sent arguments. All data is
653    duplicated. */
654
655 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
656                                            const unsigned char *prv,
657                                            SilcUInt32 prv_len)
658 {
659   SilcPrivateKey private_key;
660
661   private_key = silc_calloc(1, sizeof(*private_key));
662   private_key->name = strdup(name);
663   private_key->prv_len = prv_len;
664   private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
665   memcpy(private_key->prv, prv, prv_len);
666
667   return private_key;
668 }
669
670 /* Free's private key */
671
672 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
673 {
674   if (private_key) {
675     silc_free(private_key->name);
676     silc_free(private_key->prv);
677     silc_free(private_key);
678   }
679 }
680
681 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
682    data. */
683
684 unsigned char *
685 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
686 {
687   SilcBuffer buf;
688   unsigned char *ret;
689
690   buf = silc_buffer_alloc(public_key->len + 4);
691   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
692
693   silc_buffer_format(buf,
694                      SILC_STR_UI_INT(public_key->len),
695                      SILC_STR_UI_SHORT(strlen(public_key->name)),
696                      SILC_STR_UI32_STRING(public_key->name),
697                      SILC_STR_UI_SHORT(strlen(public_key->identifier)),
698                      SILC_STR_UI32_STRING(public_key->identifier),
699                      SILC_STR_UI_XNSTRING(public_key->pk, 
700                                           public_key->pk_len),
701                      SILC_STR_END);
702   if (len)
703     *len = public_key->len + 4;
704
705   ret = silc_calloc(buf->len, sizeof(*ret));
706   memcpy(ret, buf->data, buf->len);
707   silc_buffer_free(buf);
708
709   return ret;
710 }
711
712 /* Encodes SILC style public key. Returns the encoded data. */
713
714 unsigned char *
715 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
716                                  char *pkcs, char *identifier, 
717                                  SilcUInt32 *len)
718 {
719   SilcBuffer buf;
720   unsigned char *ret;
721   SilcUInt32 totlen;
722
723   totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
724   buf = silc_buffer_alloc(totlen + 4);
725   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
726
727   silc_buffer_format(buf,
728                      SILC_STR_UI_INT(totlen),
729                      SILC_STR_UI_SHORT(strlen(pkcs)),
730                      SILC_STR_UI32_STRING(pkcs),
731                      SILC_STR_UI_SHORT(strlen(identifier)),
732                      SILC_STR_UI32_STRING(identifier),
733                      SILC_STR_UI_XNSTRING(pk, pk_len),
734                      SILC_STR_END);
735   if (len)
736     *len = totlen + 4;
737
738   ret = silc_calloc(buf->len, sizeof(*ret));
739   memcpy(ret, buf->data, buf->len);
740   silc_buffer_free(buf);
741
742   return ret;
743 }
744
745 /* Decodes SILC style public key. Returns TRUE if the decoding was
746    successful. Allocates new public key as well. */
747
748 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
749                                  SilcPublicKey *public_key)
750 {
751   SilcBuffer buf;
752   SilcPKCS alg;
753   SilcUInt16 pkcs_len, identifier_len;
754   SilcUInt32 totlen, key_len;
755   unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
756   int ret;
757
758   buf = silc_buffer_alloc(data_len);
759   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
760   silc_buffer_put(buf, data, data_len);
761
762   /* Get length */
763   ret = silc_buffer_unformat(buf,
764                              SILC_STR_UI_INT(&totlen),
765                              SILC_STR_END);
766   if (ret == -1) {
767     silc_buffer_free(buf);
768     return FALSE;
769   }
770
771 #if 1 /* Backwards support, remove! */
772   if (totlen == data_len)
773     totlen -= 4;
774 #endif
775
776   if (totlen + 4 != data_len) {
777     silc_buffer_free(buf);
778     return FALSE;
779   }
780
781   /* Get algorithm name and identifier */
782   silc_buffer_pull(buf, 4);
783   ret =
784     silc_buffer_unformat(buf,
785                          SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
786                          SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
787                          SILC_STR_END);
788   if (ret == -1)
789     goto err;
790
791   if (pkcs_len < 1 || identifier_len < 3 || 
792       pkcs_len + identifier_len > totlen)
793     goto err;
794
795   /* See if we support this algorithm (check only if PKCS are registered) */
796   if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
797     SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
798     goto err;
799   }
800
801   /* Protocol says that at least UN and HN must be provided as identifier,
802      check for these. */
803   if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
804     SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
805                     "identifiers"));
806     goto err;
807   }
808
809   /* Get key data. We assume that rest of the buffer is key data. */
810   silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
811   key_len = buf->len;
812   ret = silc_buffer_unformat(buf,
813                              SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
814                              SILC_STR_END);
815   if (ret == -1)
816     goto err;
817
818   /* Try to set the key. If this fails the key must be malformed. This
819      code assumes that the PKCS routine checks the format of the key. 
820      (check only if PKCS are registered) */
821   if (SILC_PKCS_LIST) {
822     silc_pkcs_alloc(pkcs_name, &alg);
823     if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
824       goto err;
825     silc_pkcs_free(alg);
826   }
827   
828   if (public_key) {
829     *public_key = silc_calloc(1, sizeof(**public_key));
830     (*public_key)->len = totlen;
831     (*public_key)->name = pkcs_name;
832     (*public_key)->identifier = ident;
833     (*public_key)->pk = key_data;
834     (*public_key)->pk_len = key_len;
835     (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
836   }
837
838   silc_buffer_free(buf);
839   return TRUE;
840
841  err:
842   if (pkcs_name)
843     silc_free(pkcs_name);
844   if (ident)
845     silc_free(ident);
846   if (key_data)
847     silc_free(key_data);
848   silc_buffer_free(buf);
849   return FALSE;
850 }
851
852 /* Encodes Public Key Payload for transmitting public keys and certificates. */
853
854 SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
855 {
856   SilcBuffer buffer;
857   unsigned char *pk;
858   SilcUInt32 pk_len;
859
860   if (!public_key)
861     return NULL;
862
863   pk = silc_pkcs_public_key_encode(public_key, &pk_len);
864   if (!pk)
865     return NULL;
866
867   buffer = silc_buffer_alloc_size(4 + pk_len);
868   if (!buffer) {
869     silc_free(pk);
870     return NULL;
871   }
872
873   silc_buffer_format(buffer,
874                      SILC_STR_UI_SHORT(pk_len),
875                      SILC_STR_UI_SHORT(public_key->pk_type),
876                      SILC_STR_UI_XNSTRING(pk, pk_len),
877                      SILC_STR_END);
878
879   silc_free(pk);
880   return buffer;
881 }
882
883 /* Decode Public Key Payload and decodes the public key inside it to
884    to `payload'. */
885
886 bool silc_pkcs_public_key_payload_decode(unsigned char *data,
887                                          SilcUInt32 data_len,
888                                          SilcPublicKey *public_key)
889 {
890   SilcBufferStruct buf;
891   SilcUInt16 pk_len, pk_type;
892   unsigned char *pk;
893   int ret;
894
895   if (!public_key)
896     return FALSE;
897
898 #if 1
899   /* XXX 1.1 version support.  Check whether the data is actually raw
900      public key and attempt to decode.  Remove this later! */
901   if (silc_pkcs_public_key_decode(data, data_len, public_key)) {
902     (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
903     return TRUE;
904   }
905 #endif
906
907   silc_buffer_set(&buf, data, data_len);
908   ret = silc_buffer_unformat(&buf,
909                              SILC_STR_UI_SHORT(&pk_len),
910                              SILC_STR_UI_SHORT(&pk_type),
911                              SILC_STR_END);
912   if (ret < 0 || pk_len > data_len - 4)
913     return FALSE;
914
915   /* For now we support only SILC public keys */
916   if (pk_type != SILC_SKE_PK_TYPE_SILC)
917     return FALSE;
918
919   silc_buffer_pull(&buf, 4);
920   ret = silc_buffer_unformat(&buf,
921                              SILC_STR_UI_XNSTRING(&pk, pk_len),
922                              SILC_STR_END);
923   silc_buffer_push(&buf, 4);
924   if (ret < 0)
925     return FALSE;
926
927   if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
928     return FALSE;
929   (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
930
931   return TRUE;
932 }
933
934 /* Compares two public keys and returns TRUE if they are same key, and
935    FALSE if they are not same. */
936
937 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
938 {
939   if (key1 == key2)
940     return TRUE;
941
942   if (key1->len == key2->len &&
943       key1->name && key2->name && key1->identifier && key2->identifier &&
944       !strcmp(key1->name, key2->name) &&
945       !strcmp(key1->identifier, key2->identifier) &&
946       !memcmp(key1->pk, key2->pk, key1->pk_len) &&
947       key1->pk_len == key2->pk_len)
948     return TRUE;
949
950   return FALSE;
951 }
952
953 /* Copies the public key indicated by `public_key' and returns new allocated
954    public key which is indentical to the `public_key'. */
955
956 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
957 {
958   SilcPublicKey key = silc_calloc(1, sizeof(*key));
959   if (!key)
960     return NULL;
961
962   key->len = public_key->len;
963   key->name = silc_memdup(public_key->name, strlen(public_key->name));
964   key->identifier = silc_memdup(public_key->identifier,
965                                 strlen(public_key->identifier));
966   key->pk = silc_memdup(public_key->pk, public_key->pk_len);
967   key->pk_len = public_key->pk_len;
968   key->pk_type = public_key->pk_type;
969
970   return key;
971 }
972
973 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
974
975 unsigned char *
976 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
977 {
978   SilcBuffer buf;
979   unsigned char *ret;
980   SilcUInt32 totlen;
981
982   totlen = 2 + strlen(private_key->name) + private_key->prv_len;
983   buf = silc_buffer_alloc(totlen);
984   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
985
986   silc_buffer_format(buf,
987                      SILC_STR_UI_SHORT(strlen(private_key->name)),
988                      SILC_STR_UI32_STRING(private_key->name),
989                      SILC_STR_UI_XNSTRING(private_key->prv, 
990                                           private_key->prv_len),
991                      SILC_STR_END);
992   if (len)
993     *len = totlen;
994
995   ret = silc_calloc(buf->len, sizeof(*ret));
996   memcpy(ret, buf->data, buf->len);
997   silc_buffer_clear(buf);
998   silc_buffer_free(buf);
999
1000   return ret;
1001 }
1002
1003 /* Encodes SILC private key. Returns the encoded data. */
1004
1005 unsigned char *
1006 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
1007                                   char *pkcs, SilcUInt32 *len)
1008 {
1009   SilcBuffer buf;
1010   unsigned char *ret;
1011   SilcUInt32 totlen;
1012
1013   totlen = 2 + strlen(pkcs) + prv_len;
1014   buf = silc_buffer_alloc(totlen);
1015   silc_buffer_pull_tail(buf, totlen);
1016
1017   silc_buffer_format(buf,
1018                      SILC_STR_UI_SHORT(strlen(pkcs)),
1019                      SILC_STR_UI32_STRING(pkcs),
1020                      SILC_STR_UI_XNSTRING(prv, prv_len),
1021                      SILC_STR_END);
1022   if (len)
1023     *len = totlen;
1024
1025   ret = silc_calloc(buf->len, sizeof(*ret));
1026   memcpy(ret, buf->data, buf->len);
1027   silc_buffer_clear(buf);
1028   silc_buffer_free(buf);
1029
1030   return ret;
1031 }
1032
1033 /* Decodes SILC style private key. Returns TRUE if the decoding was
1034    successful. Allocates new private key as well. */
1035
1036 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
1037                                   SilcPrivateKey *private_key)
1038 {
1039   SilcBuffer buf;
1040   SilcPKCS alg;
1041   SilcUInt16 pkcs_len;
1042   SilcUInt32 key_len;
1043   unsigned char *pkcs_name = NULL, *key_data = NULL;
1044   int ret;
1045
1046   buf = silc_buffer_alloc(data_len);
1047   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1048   silc_buffer_put(buf, data, data_len);
1049
1050   /* Get algorithm name and identifier */
1051   ret = 
1052     silc_buffer_unformat(buf,
1053                          SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1054                          SILC_STR_END);
1055   if (ret == -1) {
1056     SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1057     goto err;
1058   }
1059
1060   if (pkcs_len < 1 || pkcs_len > buf->truelen) {
1061     SILC_LOG_DEBUG(("Malformed private key buffer"));
1062     goto err;
1063   }
1064
1065   /* See if we support this algorithm (check only if PKCS are registered). */
1066   if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1067     SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1068     goto err;
1069   }
1070
1071   /* Get key data. We assume that rest of the buffer is key data. */
1072   silc_buffer_pull(buf, 2 + pkcs_len);
1073   key_len = buf->len;
1074   ret = silc_buffer_unformat(buf,
1075                              SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1076                              SILC_STR_END);
1077   if (ret == -1)
1078     goto err;
1079
1080   /* Try to set the key. If this fails the key must be malformed. This
1081      code assumes that the PKCS routine checks the format of the key. 
1082      (check only if PKCS are registered) */
1083   if (SILC_PKCS_LIST) {
1084     silc_pkcs_alloc(pkcs_name, &alg);
1085     if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1086       SILC_LOG_DEBUG(("Could not set private key data"));
1087       goto err;
1088     }
1089     silc_pkcs_free(alg);
1090   }
1091   
1092   if (private_key) {
1093     *private_key = silc_calloc(1, sizeof(**private_key));
1094     (*private_key)->name = pkcs_name;
1095     (*private_key)->prv = key_data;
1096     (*private_key)->prv_len = key_len;
1097   }
1098
1099   silc_buffer_clear(buf);
1100   silc_buffer_free(buf);
1101   return TRUE;
1102
1103  err:
1104   if (pkcs_name)
1105     silc_free(pkcs_name);
1106   if (key_data)
1107     silc_free(key_data);
1108   silc_buffer_clear(buf);
1109   silc_buffer_free(buf);
1110   return FALSE;
1111 }
1112
1113 /* Internal routine to save public key */
1114
1115 static bool silc_pkcs_save_public_key_internal(const char *filename,
1116                                                unsigned char *data,
1117                                                SilcUInt32 data_len,
1118                                                SilcUInt32 encoding)
1119 {
1120   SilcBuffer buf;
1121   SilcUInt32 len;
1122
1123   switch(encoding) {
1124   case SILC_PKCS_FILE_BIN:
1125     break;
1126   case SILC_PKCS_FILE_PEM:
1127     data = silc_pem_encode_file(data, data_len);
1128     data_len = strlen(data);
1129     break;
1130   }
1131
1132   len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1133                     strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1134   buf = silc_buffer_alloc(len);
1135   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1136
1137   silc_buffer_format(buf,
1138                      SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1139                      SILC_STR_UI_XNSTRING(data, data_len),
1140                      SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1141                      SILC_STR_END);
1142
1143   /* Save into file */
1144   if (silc_file_writefile(filename, buf->data, buf->len)) {
1145     silc_buffer_free(buf);
1146     return FALSE;
1147   }
1148
1149   silc_buffer_free(buf);
1150   return TRUE;
1151 }
1152
1153 /* Saves public key into file */
1154
1155 bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1156                                SilcUInt32 encoding)
1157 {
1158   unsigned char *data;
1159   SilcUInt32 data_len;
1160   bool ret;
1161
1162   data = silc_pkcs_public_key_encode(public_key, &data_len);
1163   ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1164                                            encoding);
1165   silc_free(data);
1166   return ret;
1167 }
1168
1169 /* Saves public key into file */
1170
1171 bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1172                                     SilcUInt32 data_len, SilcUInt32 encoding)
1173 {
1174   return silc_pkcs_save_public_key_internal(filename, data, data_len,
1175                                             encoding);
1176 }
1177
1178 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1179
1180 /* Internal routine to save private key. */
1181
1182 static bool silc_pkcs_save_private_key_internal(const char *filename,
1183                                                 unsigned char *data,
1184                                                 SilcUInt32 data_len,
1185                                                 unsigned char *key,
1186                                                 SilcUInt32 key_len,
1187                                                 SilcUInt32 encoding)
1188 {
1189   SilcCipher aes;
1190   SilcHash sha1;
1191   SilcHmac sha1hmac;
1192   SilcBuffer buf, enc;
1193   SilcUInt32 len, blocklen, padlen;
1194   unsigned char tmp[32], keymat[64];
1195   int i;
1196
1197   memset(tmp, 0, sizeof(tmp));
1198   memset(keymat, 0, sizeof(keymat));
1199
1200   /* Allocate the AES cipher */
1201   if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1202     SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1203     return FALSE;
1204   }
1205   blocklen = silc_cipher_get_block_len(aes);
1206   if (blocklen * 2 > sizeof(tmp))
1207     return FALSE;
1208
1209   /* Allocate SHA1 hash */
1210   if (!silc_hash_alloc("sha1", &sha1)) {
1211     SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1212     silc_cipher_free(aes);
1213     return FALSE;
1214   }
1215
1216   /* Allocate HMAC */
1217   if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1218     SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1219     silc_hash_free(sha1);
1220     silc_cipher_free(aes);
1221     return FALSE;
1222   }
1223
1224   /* Derive the encryption key from the provided key material.  The key
1225      is 256 bits length, and derived by taking hash of the data, then 
1226      re-hashing the data and the previous digest, and using the first and
1227      second digest as the key. */
1228   silc_hash_init(sha1);
1229   silc_hash_update(sha1, key, key_len);
1230   silc_hash_final(sha1, keymat);
1231   silc_hash_init(sha1);
1232   silc_hash_update(sha1, key, key_len);
1233   silc_hash_update(sha1, keymat, 16);
1234   silc_hash_final(sha1, keymat + 16);
1235
1236   /* Set the key to the cipher */
1237   silc_cipher_set_key(aes, keymat, 256);
1238
1239   /* Encode the buffer to be encrypted.  Add padding to it too, at least
1240      block size of the cipher. */
1241
1242   /* Allocate buffer for encryption */
1243   len = silc_hmac_len(sha1hmac);
1244   padlen = 16 + (16 - ((data_len + 4) % blocklen));
1245   enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1246   if (!enc) {
1247     silc_hmac_free(sha1hmac);
1248     silc_hash_free(sha1);
1249     silc_cipher_free(aes);
1250     return FALSE;
1251   }
1252
1253   /* Generate padding */
1254   for (i = 0; i < padlen; i++)
1255     tmp[i] = silc_rng_global_get_byte_fast();
1256
1257   /* Put magic number */
1258   SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1259   silc_buffer_pull(enc, 4);
1260
1261   /* Encode the buffer */
1262   silc_buffer_format(enc,
1263                      SILC_STR_UI_INT(data_len),
1264                      SILC_STR_UI_XNSTRING(data, data_len),
1265                      SILC_STR_UI_XNSTRING(tmp, padlen),
1266                      SILC_STR_END);
1267
1268   /* Encrypt. */
1269   silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
1270                       silc_cipher_get_iv(aes));
1271
1272   silc_buffer_push(enc, 4);
1273
1274   /* Compute HMAC over the encrypted data and append the MAC to data.
1275      The key is the first digest of the original key material. */
1276   data_len = enc->len - len;
1277   silc_hmac_init_with_key(sha1hmac, keymat, 16);
1278   silc_hmac_update(sha1hmac, enc->data, data_len);
1279   silc_buffer_pull(enc, data_len);
1280   silc_hmac_final(sha1hmac, enc->data, NULL);
1281   silc_buffer_push(enc, data_len);
1282
1283   /* Cleanup */
1284   memset(keymat, 0, sizeof(keymat));
1285   memset(tmp, 0, sizeof(tmp));
1286   silc_hmac_free(sha1hmac);
1287   silc_hash_free(sha1);
1288   silc_cipher_free(aes);
1289
1290   data = enc->data;
1291   data_len = enc->len;
1292
1293   switch (encoding) {
1294   case SILC_PKCS_FILE_BIN:
1295     break;
1296   case SILC_PKCS_FILE_PEM:
1297     data = silc_pem_encode_file(data, data_len);
1298     data_len = strlen(data);
1299     break;
1300   }
1301
1302   /* Encode the data and save to file */
1303   len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1304                     strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1305   buf = silc_buffer_alloc_size(len);
1306   silc_buffer_format(buf,
1307                      SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1308                      SILC_STR_UI_XNSTRING(data, data_len),
1309                      SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1310                      SILC_STR_END);
1311
1312   /* Save into a file */
1313   if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
1314     silc_buffer_clear(buf);
1315     silc_buffer_free(buf);
1316     silc_buffer_clear(enc);
1317     silc_buffer_free(enc);
1318     return FALSE;
1319   }
1320
1321   silc_buffer_clear(buf);
1322   silc_buffer_free(buf);
1323   silc_buffer_clear(enc);
1324   silc_buffer_free(enc);
1325   return TRUE;
1326 }
1327
1328 /* Saves private key into file. */
1329
1330 bool silc_pkcs_save_private_key(const char *filename,
1331                                 SilcPrivateKey private_key,
1332                                 unsigned char *passphrase,
1333                                 SilcUInt32 passphrase_len,
1334                                 SilcUInt32 encoding)
1335 {
1336   unsigned char *data;
1337   SilcUInt32 data_len;
1338   bool ret;
1339
1340   data = silc_pkcs_private_key_encode(private_key, &data_len);
1341   ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1342                                             passphrase, passphrase_len,
1343                                             encoding);
1344   memset(data, 0, data_len);
1345   silc_free(data);
1346   return ret;
1347 }
1348
1349 /* Loads public key from file and allocates new public key. Returns TRUE
1350    if loading was successful. */
1351
1352 bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1353                                SilcUInt32 encoding)
1354 {
1355   unsigned char *cp, *old, *data, byte;
1356   SilcUInt32 i, data_len, len;
1357
1358   SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1359                   encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1360                   encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1361   
1362   old = data = silc_file_readfile(filename, &data_len);
1363   if (!data)
1364     return FALSE;
1365
1366   /* Check start of file and remove header from the data. */
1367   len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1368   cp = data;
1369   for (i = 0; i < len; i++) {
1370     byte = cp[0];
1371     cp++;
1372     if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1373       memset(old, 0, data_len);
1374       silc_free(old);
1375       return FALSE;
1376     }
1377   }
1378   data = cp;
1379
1380   /* Decode public key */
1381   if (public_key) {
1382     len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1383                       strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1384
1385     switch(encoding) {
1386     case SILC_PKCS_FILE_BIN:
1387       break;
1388     case SILC_PKCS_FILE_PEM:
1389       data = silc_pem_decode(data, len, &len);
1390       memset(old, 0, data_len);
1391       silc_free(old);
1392       old = data; 
1393       data_len = len;
1394       break;
1395     }
1396
1397     if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1398       memset(old, 0, data_len);
1399       silc_free(old);
1400       return FALSE;
1401     }
1402   }
1403
1404   memset(old, 0, data_len);
1405   silc_free(old);
1406   return TRUE;
1407 }
1408
1409 #if 1 /* Old MD5 routine for private key loading, remove later! */
1410 struct MD5Context {
1411   SilcUInt32 buf[4];
1412   SilcUInt32 bits[2];
1413   unsigned char in[64];
1414 };
1415 static void MD5Init(struct MD5Context *ctx)
1416 {
1417   ctx->buf[0] = 0x67452301;
1418   ctx->buf[1] = 0xefcdab89;
1419   ctx->buf[2] = 0x98badcfe;
1420   ctx->buf[3] = 0x10325476;
1421   ctx->bits[0] = ctx->bits[1] = 0;
1422 }
1423 static void
1424 MD5Transform(SilcUInt32 buf[4], const unsigned char kbuf[64]);
1425 static void
1426 MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
1427 {
1428   SilcUInt32 t;
1429
1430   t = ctx->bits[0];
1431   if ((ctx->bits[0] = t + ((SilcUInt32)len << 3)) < t)
1432     ctx->bits[1]++;     /* Carry from low to high */
1433   ctx->bits[1] += (SilcUInt32)len >> 29;
1434   t = (t >> 3) & 0x3f;  /* Bytes already in shsInfo->data */
1435   if ( t ) {
1436     unsigned char *p = (unsigned char *)ctx->in + t;
1437
1438     t = 64-t;
1439     if (len < t) {
1440       memcpy(p, buf, len);
1441       return;
1442     }
1443     memcpy(p, buf, t);
1444     MD5Transform(ctx->buf, ctx->in);
1445     buf += t;
1446     len -= t;
1447   }  while (len >= 64) {
1448     memcpy(ctx->in, buf, 64);
1449     MD5Transform(ctx->buf, ctx->in);
1450     buf += 64;
1451     len -= 64;
1452   }
1453   memcpy(ctx->in, buf, len);
1454 }
1455
1456 static void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
1457 {
1458   unsigned count;
1459   unsigned char *p;
1460   count = (ctx->bits[0] >> 3) & 0x3F;
1461   p = ctx->in + count;
1462   *p++ = 0x80;
1463   count = 64 - 1 - count;
1464   if (count < 8) {
1465     memset(p, 0, count);
1466     MD5Transform(ctx->buf, ctx->in);
1467     memset(ctx->in, 0, 56);
1468   } else {
1469     memset(p, 0, count-8);
1470   }
1471   ((SilcUInt32 *)ctx->in)[ 14 ] = ctx->bits[0];
1472   ((SilcUInt32 *)ctx->in)[ 15 ] = ctx->bits[1];   
1473   MD5Transform(ctx->buf, ctx->in);  
1474   memcpy(digest, ctx->buf, 16);
1475   memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
1476 }
1477 #define F1(x, y, z) (z ^ (x & (y ^ z)))
1478 #define F2(x, y, z) F1(z, x, y)
1479 #define F3(x, y, z) (x ^ y ^ z)
1480 #define F4(x, y, z) (y ^ (x | ~z))
1481 #define MD5STEP(f, w, x, y, z, data, s) \
1482         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s), w += x )
1483 static void
1484 MD5Transform(SilcUInt32 buf[4], const unsigned char kbuf[64])
1485 {
1486   register SilcUInt32 a, b, c, d, i;
1487   SilcUInt32 in[16];
1488   for (i = 0; i < 16; i++)
1489     SILC_GET32_MSB(in[i], kbuf + 4 * i);
1490   a = buf[0];  b = buf[1];  c = buf[2];  d = buf[3];
1491   MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
1492   MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
1493   MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
1494   MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
1495   MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
1496   MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
1497   MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
1498   MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
1499   MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
1500   MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
1501   MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
1502   MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
1503   MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
1504   MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
1505   MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
1506   MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
1507   MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
1508   MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
1509   MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
1510   MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
1511   MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
1512   MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
1513   MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
1514   MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
1515   MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
1516   MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
1517   MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
1518   MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
1519   MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
1520   MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
1521   MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
1522   MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
1523   MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
1524   MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
1525   MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
1526   MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
1527   MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
1528   MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
1529   MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
1530   MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
1531   MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
1532   MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
1533   MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
1534   MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
1535   MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
1536   MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
1537   MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
1538   MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
1539   MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
1540   MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
1541   MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
1542   MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
1543   MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
1544   MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
1545   MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
1546   MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
1547   MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
1548   MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
1549   MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
1550   MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
1551   MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
1552   MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
1553   MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
1554   MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
1555   buf[0] += a;  buf[1] += b;  buf[2] += c;  buf[3] += d;
1556 }
1557 #endif /* 1 */
1558
1559 /* Load private key from file and allocates new private key. Returns TRUE
1560    if loading was successful. */
1561
1562 bool silc_pkcs_load_private_key(const char *filename,
1563                                 SilcPrivateKey *private_key,
1564                                 unsigned char *passphrase,
1565                                 SilcUInt32 passphrase_len,
1566                                 SilcUInt32 encoding)
1567 {
1568   SilcCipher aes;
1569   SilcHash sha1;
1570   SilcHmac sha1hmac;
1571   SilcUInt32 blocklen;
1572   unsigned char tmp[32], keymat[64];
1573   unsigned char *cp, *old, *data, byte;
1574   SilcUInt32 i, data_len, len, magic, mac_len;
1575
1576 #if 1
1577   /* Old support */
1578   struct MD5Context md5;
1579   bool oldsupport = FALSE;
1580   int oldlen = 0;
1581 #endif /* 1 */
1582
1583   SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1584                   encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1585                   encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1586   
1587   old = data = silc_file_readfile(filename, &data_len);
1588   if (!data)
1589     return FALSE;
1590
1591   /* Check start of file and remove header from the data. */
1592   len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1593   cp = data;
1594   for (i = 0; i < len; i++) {
1595     byte = cp[0];
1596     cp++;
1597     if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1598       memset(old, 0, data_len);
1599       silc_free(old);
1600       return FALSE;
1601     }
1602   }
1603   data = cp;
1604
1605   /* Decode private key */
1606   len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1607                     strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1608
1609   switch(encoding) {
1610   case SILC_PKCS_FILE_BIN:
1611     break;
1612   case SILC_PKCS_FILE_PEM:
1613     data = silc_pem_decode(data, len, &len);
1614     if (!data) {
1615       memset(old, 0, data_len);
1616       silc_free(old);
1617       return FALSE;
1618     }
1619     break;
1620   }
1621
1622   memset(tmp, 0, sizeof(tmp));
1623   memset(keymat, 0, sizeof(keymat));
1624
1625   /* Private key files without the specific magic number are assumed
1626      to be the old-style private keys that are not encrypted. */
1627   SILC_GET32_MSB(magic, data);
1628   if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1629     SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1630
1631     /* Now decode the actual private key */
1632     if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1633       memset(old, 0, data_len);
1634       silc_free(old);
1635       return FALSE;
1636     }
1637
1638     memset(old, 0, data_len);
1639     silc_free(old);
1640     return TRUE;
1641   }
1642
1643   /* Allocate the AES cipher */
1644   if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1645     SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1646     memset(old, 0, data_len);
1647     silc_free(old);
1648     return FALSE;
1649   }
1650   blocklen = silc_cipher_get_block_len(aes);
1651   if (blocklen * 2 > sizeof(tmp)) {
1652     memset(old, 0, data_len);
1653     silc_free(old);
1654     return FALSE;
1655   }
1656
1657   /* Allocate SHA1 hash */
1658   if (!silc_hash_alloc("sha1", &sha1)) {
1659     SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1660     silc_cipher_free(aes);
1661     memset(old, 0, data_len);
1662     silc_free(old);
1663     return FALSE;
1664   }
1665
1666   /* Allocate HMAC */
1667   if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1668     SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1669     silc_hash_free(sha1);
1670     silc_cipher_free(aes);
1671     memset(old, 0, data_len);
1672     silc_free(old);
1673     return FALSE;
1674   }
1675
1676   /* Derive the decryption key from the provided key material.  The key
1677      is 256 bits length, and derived by taking hash of the data, then 
1678      re-hashing the data and the previous digest, and using the first and
1679      second digest as the key. */
1680   silc_hash_init(sha1);
1681   silc_hash_update(sha1, passphrase, passphrase_len);
1682   silc_hash_final(sha1, keymat);
1683   silc_hash_init(sha1);
1684   silc_hash_update(sha1, passphrase, passphrase_len);
1685   silc_hash_update(sha1, keymat, 16);
1686   silc_hash_final(sha1, keymat + 16);
1687
1688 #if 1
1689  olds:
1690   /* Old support */
1691   if (oldsupport) {
1692     MD5Init(&md5);
1693     MD5Update(&md5, passphrase, passphrase_len);
1694     MD5Final(keymat, &md5);
1695     MD5Init(&md5);
1696     MD5Update(&md5, passphrase, passphrase_len);
1697     MD5Update(&md5, keymat, 16);
1698     MD5Final(keymat + 16, &md5);
1699   }
1700 #endif /* 1 */
1701   
1702   /* Set the key to the cipher */
1703   silc_cipher_set_key(aes, keymat, 256);
1704
1705   /* First, verify the MAC of the private key data */
1706   mac_len = silc_hmac_len(sha1hmac);
1707   silc_hmac_init_with_key(sha1hmac, keymat, 16);
1708   silc_hmac_update(sha1hmac, data, len - mac_len);
1709   silc_hmac_final(sha1hmac, tmp, NULL);
1710   if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1711 #if 1
1712     /* Old support */
1713     if (!oldsupport) {
1714       oldsupport = TRUE;
1715       goto olds;
1716     }
1717 #endif
1718     
1719     SILC_LOG_DEBUG(("Integrity check for private key failed"));
1720     memset(keymat, 0, sizeof(keymat));
1721     memset(tmp, 0, sizeof(tmp));
1722     silc_hmac_free(sha1hmac);
1723     silc_hash_free(sha1);
1724     silc_cipher_free(aes);
1725     memset(old, 0, data_len);
1726     silc_free(old);
1727     return FALSE;
1728   }
1729   data += 4;
1730   len -= 4;
1731
1732 #if 1
1733   /* Old support */
1734   oldlen = len - mac_len;
1735 #endif
1736
1737   /* Decrypt the private key buffer */
1738   silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1739   SILC_GET32_MSB(i, data);
1740   if (i > len) {
1741     SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1742     memset(keymat, 0, sizeof(keymat));
1743     memset(tmp, 0, sizeof(tmp));
1744     silc_hmac_free(sha1hmac);
1745     silc_hash_free(sha1);
1746     silc_cipher_free(aes);
1747     memset(old, 0, data_len);
1748     silc_free(old);
1749     return FALSE;
1750   }
1751   data += 4;
1752   len = i;
1753
1754   /* Cleanup */
1755   memset(keymat, 0, sizeof(keymat));
1756   memset(tmp, 0, sizeof(tmp));
1757   silc_hmac_free(sha1hmac);
1758   silc_hash_free(sha1);
1759   silc_cipher_free(aes);
1760
1761   /* Now decode the actual private key */
1762   if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1763     memset(old, 0, data_len);
1764     silc_free(old);
1765     return FALSE;
1766   }
1767
1768 #if 1
1769   /* Old support */
1770   if (oldsupport || (oldlen & 15))
1771     silc_pkcs_save_private_key((char *)filename, *private_key,
1772                                passphrase, passphrase_len, encoding);
1773 #endif
1774     
1775   memset(old, 0, data_len);
1776   silc_free(old);
1777   return TRUE;
1778 }