Merged from silc_1_0_branch.
[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   silc_buffer_set(&buf, data, data_len);
899   ret = silc_buffer_unformat(&buf,
900                              SILC_STR_UI_SHORT(&pk_len),
901                              SILC_STR_UI_SHORT(&pk_type),
902                              SILC_STR_END);
903   if (ret < 0 || pk_len > data_len - 4)
904     return FALSE;
905
906   /* For now we support only SILC public keys */
907   if (pk_type != SILC_SKE_PK_TYPE_SILC)
908     return FALSE;
909
910   silc_buffer_pull(&buf, 4);
911   ret = silc_buffer_unformat(&buf,
912                              SILC_STR_UI_XNSTRING(&pk, pk_len),
913                              SILC_STR_END);
914   silc_buffer_push(&buf, 4);
915   if (ret < 0)
916     return FALSE;
917
918   if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
919     return FALSE;
920   (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
921
922   return TRUE;
923 }
924
925 /* Compares two public keys and returns TRUE if they are same key, and
926    FALSE if they are not same. */
927
928 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
929 {
930   if (key1 == key2)
931     return TRUE;
932
933   if (key1->len == key2->len &&
934       key1->name && key2->name && key1->identifier && key2->identifier &&
935       !strcmp(key1->name, key2->name) &&
936       !strcmp(key1->identifier, key2->identifier) &&
937       !memcmp(key1->pk, key2->pk, key1->pk_len) &&
938       key1->pk_len == key2->pk_len)
939     return TRUE;
940
941   return FALSE;
942 }
943
944 /* Copies the public key indicated by `public_key' and returns new allocated
945    public key which is indentical to the `public_key'. */
946
947 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
948 {
949   SilcPublicKey key = silc_calloc(1, sizeof(*key));
950   if (!key)
951     return NULL;
952
953   key->len = public_key->len;
954   key->name = silc_memdup(public_key->name, strlen(public_key->name));
955   key->identifier = silc_memdup(public_key->identifier,
956                                 strlen(public_key->identifier));
957   key->pk = silc_memdup(public_key->pk, public_key->pk_len);
958   key->pk_len = public_key->pk_len;
959   key->pk_type = public_key->pk_type;
960
961   return key;
962 }
963
964 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
965
966 unsigned char *
967 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
968 {
969   SilcBuffer buf;
970   unsigned char *ret;
971   SilcUInt32 totlen;
972
973   totlen = 2 + strlen(private_key->name) + private_key->prv_len;
974   buf = silc_buffer_alloc(totlen);
975   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
976
977   silc_buffer_format(buf,
978                      SILC_STR_UI_SHORT(strlen(private_key->name)),
979                      SILC_STR_UI32_STRING(private_key->name),
980                      SILC_STR_UI_XNSTRING(private_key->prv, 
981                                           private_key->prv_len),
982                      SILC_STR_END);
983   if (len)
984     *len = totlen;
985
986   ret = silc_calloc(buf->len, sizeof(*ret));
987   memcpy(ret, buf->data, buf->len);
988   silc_buffer_clear(buf);
989   silc_buffer_free(buf);
990
991   return ret;
992 }
993
994 /* Encodes SILC private key. Returns the encoded data. */
995
996 unsigned char *
997 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
998                                   char *pkcs, SilcUInt32 *len)
999 {
1000   SilcBuffer buf;
1001   unsigned char *ret;
1002   SilcUInt32 totlen;
1003
1004   totlen = 2 + strlen(pkcs) + prv_len;
1005   buf = silc_buffer_alloc(totlen);
1006   silc_buffer_pull_tail(buf, totlen);
1007
1008   silc_buffer_format(buf,
1009                      SILC_STR_UI_SHORT(strlen(pkcs)),
1010                      SILC_STR_UI32_STRING(pkcs),
1011                      SILC_STR_UI_XNSTRING(prv, prv_len),
1012                      SILC_STR_END);
1013   if (len)
1014     *len = totlen;
1015
1016   ret = silc_calloc(buf->len, sizeof(*ret));
1017   memcpy(ret, buf->data, buf->len);
1018   silc_buffer_clear(buf);
1019   silc_buffer_free(buf);
1020
1021   return ret;
1022 }
1023
1024 /* Decodes SILC style private key. Returns TRUE if the decoding was
1025    successful. Allocates new private key as well. */
1026
1027 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
1028                                   SilcPrivateKey *private_key)
1029 {
1030   SilcBuffer buf;
1031   SilcPKCS alg;
1032   SilcUInt16 pkcs_len;
1033   SilcUInt32 key_len;
1034   unsigned char *pkcs_name = NULL, *key_data = NULL;
1035   int ret;
1036
1037   buf = silc_buffer_alloc(data_len);
1038   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1039   silc_buffer_put(buf, data, data_len);
1040
1041   /* Get algorithm name and identifier */
1042   ret = 
1043     silc_buffer_unformat(buf,
1044                          SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1045                          SILC_STR_END);
1046   if (ret == -1) {
1047     SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1048     goto err;
1049   }
1050
1051   if (pkcs_len < 1 || pkcs_len > buf->truelen) {
1052     SILC_LOG_DEBUG(("Malformed private key buffer"));
1053     goto err;
1054   }
1055
1056   /* See if we support this algorithm (check only if PKCS are registered). */
1057   if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1058     SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1059     goto err;
1060   }
1061
1062   /* Get key data. We assume that rest of the buffer is key data. */
1063   silc_buffer_pull(buf, 2 + pkcs_len);
1064   key_len = buf->len;
1065   ret = silc_buffer_unformat(buf,
1066                              SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1067                              SILC_STR_END);
1068   if (ret == -1)
1069     goto err;
1070
1071   /* Try to set the key. If this fails the key must be malformed. This
1072      code assumes that the PKCS routine checks the format of the key. 
1073      (check only if PKCS are registered) */
1074   if (SILC_PKCS_LIST) {
1075     silc_pkcs_alloc(pkcs_name, &alg);
1076     if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1077       SILC_LOG_DEBUG(("Could not set private key data"));
1078       goto err;
1079     }
1080     silc_pkcs_free(alg);
1081   }
1082   
1083   if (private_key) {
1084     *private_key = silc_calloc(1, sizeof(**private_key));
1085     (*private_key)->name = pkcs_name;
1086     (*private_key)->prv = key_data;
1087     (*private_key)->prv_len = key_len;
1088   }
1089
1090   silc_buffer_clear(buf);
1091   silc_buffer_free(buf);
1092   return TRUE;
1093
1094  err:
1095   if (pkcs_name)
1096     silc_free(pkcs_name);
1097   if (key_data)
1098     silc_free(key_data);
1099   silc_buffer_clear(buf);
1100   silc_buffer_free(buf);
1101   return FALSE;
1102 }
1103
1104 /* Internal routine to save public key */
1105
1106 static bool silc_pkcs_save_public_key_internal(const char *filename,
1107                                                unsigned char *data,
1108                                                SilcUInt32 data_len,
1109                                                SilcUInt32 encoding)
1110 {
1111   SilcBuffer buf;
1112   SilcUInt32 len;
1113
1114   switch(encoding) {
1115   case SILC_PKCS_FILE_BIN:
1116     break;
1117   case SILC_PKCS_FILE_PEM:
1118     data = silc_pem_encode_file(data, data_len);
1119     data_len = strlen(data);
1120     break;
1121   }
1122
1123   len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1124                     strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1125   buf = silc_buffer_alloc(len);
1126   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1127
1128   silc_buffer_format(buf,
1129                      SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1130                      SILC_STR_UI_XNSTRING(data, data_len),
1131                      SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1132                      SILC_STR_END);
1133
1134   /* Save into file */
1135   if (silc_file_writefile(filename, buf->data, buf->len)) {
1136     silc_buffer_free(buf);
1137     return FALSE;
1138   }
1139
1140   silc_buffer_free(buf);
1141   return TRUE;
1142 }
1143
1144 /* Saves public key into file */
1145
1146 bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1147                                SilcUInt32 encoding)
1148 {
1149   unsigned char *data;
1150   SilcUInt32 data_len;
1151   bool ret;
1152
1153   data = silc_pkcs_public_key_encode(public_key, &data_len);
1154   ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1155                                            encoding);
1156   silc_free(data);
1157   return ret;
1158 }
1159
1160 /* Saves public key into file */
1161
1162 bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1163                                     SilcUInt32 data_len, SilcUInt32 encoding)
1164 {
1165   return silc_pkcs_save_public_key_internal(filename, data, data_len,
1166                                             encoding);
1167 }
1168
1169 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1170
1171 /* Internal routine to save private key. */
1172
1173 static bool silc_pkcs_save_private_key_internal(const char *filename,
1174                                                 unsigned char *data,
1175                                                 SilcUInt32 data_len,
1176                                                 unsigned char *key,
1177                                                 SilcUInt32 key_len,
1178                                                 SilcUInt32 encoding)
1179 {
1180   SilcCipher aes;
1181   SilcHash sha1;
1182   SilcHmac sha1hmac;
1183   SilcBuffer buf, enc;
1184   SilcUInt32 len, blocklen, padlen;
1185   unsigned char tmp[32], keymat[64];
1186   int i;
1187
1188   memset(tmp, 0, sizeof(tmp));
1189   memset(keymat, 0, sizeof(keymat));
1190
1191   /* Allocate the AES cipher */
1192   if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1193     SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1194     return FALSE;
1195   }
1196   blocklen = silc_cipher_get_block_len(aes);
1197   if (blocklen * 2 > sizeof(tmp))
1198     return FALSE;
1199
1200   /* Allocate SHA1 hash */
1201   if (!silc_hash_alloc("sha1", &sha1)) {
1202     SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1203     silc_cipher_free(aes);
1204     return FALSE;
1205   }
1206
1207   /* Allocate HMAC */
1208   if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1209     SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1210     silc_hash_free(sha1);
1211     silc_cipher_free(aes);
1212     return FALSE;
1213   }
1214
1215   /* Derive the encryption key from the provided key material.  The key
1216      is 256 bits length, and derived by taking hash of the data, then 
1217      re-hashing the data and the previous digest, and using the first and
1218      second digest as the key. */
1219   silc_hash_init(sha1);
1220   silc_hash_update(sha1, key, key_len);
1221   silc_hash_final(sha1, keymat);
1222   silc_hash_init(sha1);
1223   silc_hash_update(sha1, key, key_len);
1224   silc_hash_update(sha1, keymat, 16);
1225   silc_hash_final(sha1, keymat + 16);
1226
1227   /* Set the key to the cipher */
1228   silc_cipher_set_key(aes, keymat, 256);
1229
1230   /* Encode the buffer to be encrypted.  Add padding to it too, at least
1231      block size of the cipher. */
1232
1233   /* Allocate buffer for encryption */
1234   len = silc_hmac_len(sha1hmac);
1235   padlen = 16 + (16 - ((data_len + 4) % blocklen));
1236   enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1237   if (!enc) {
1238     silc_hmac_free(sha1hmac);
1239     silc_hash_free(sha1);
1240     silc_cipher_free(aes);
1241     return FALSE;
1242   }
1243
1244   /* Generate padding */
1245   for (i = 0; i < padlen; i++)
1246     tmp[i] = silc_rng_global_get_byte_fast();
1247
1248   /* Put magic number */
1249   SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1250   silc_buffer_pull(enc, 4);
1251
1252   /* Encode the buffer */
1253   silc_buffer_format(enc,
1254                      SILC_STR_UI_INT(data_len),
1255                      SILC_STR_UI_XNSTRING(data, data_len),
1256                      SILC_STR_UI_XNSTRING(tmp, padlen),
1257                      SILC_STR_END);
1258
1259   /* Encrypt. */
1260   silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
1261                       silc_cipher_get_iv(aes));
1262
1263   silc_buffer_push(enc, 4);
1264
1265   /* Compute HMAC over the encrypted data and append the MAC to data.
1266      The key is the first digest of the original key material. */
1267   data_len = enc->len - len;
1268   silc_hmac_init_with_key(sha1hmac, keymat, 16);
1269   silc_hmac_update(sha1hmac, enc->data, data_len);
1270   silc_buffer_pull(enc, data_len);
1271   silc_hmac_final(sha1hmac, enc->data, NULL);
1272   silc_buffer_push(enc, data_len);
1273
1274   /* Cleanup */
1275   memset(keymat, 0, sizeof(keymat));
1276   memset(tmp, 0, sizeof(tmp));
1277   silc_hmac_free(sha1hmac);
1278   silc_hash_free(sha1);
1279   silc_cipher_free(aes);
1280
1281   data = enc->data;
1282   data_len = enc->len;
1283
1284   switch (encoding) {
1285   case SILC_PKCS_FILE_BIN:
1286     break;
1287   case SILC_PKCS_FILE_PEM:
1288     data = silc_pem_encode_file(data, data_len);
1289     data_len = strlen(data);
1290     break;
1291   }
1292
1293   /* Encode the data and save to file */
1294   len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1295                     strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1296   buf = silc_buffer_alloc_size(len);
1297   silc_buffer_format(buf,
1298                      SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1299                      SILC_STR_UI_XNSTRING(data, data_len),
1300                      SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1301                      SILC_STR_END);
1302
1303   /* Save into a file */
1304   if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
1305     silc_buffer_clear(buf);
1306     silc_buffer_free(buf);
1307     silc_buffer_clear(enc);
1308     silc_buffer_free(enc);
1309     return FALSE;
1310   }
1311
1312   silc_buffer_clear(buf);
1313   silc_buffer_free(buf);
1314   silc_buffer_clear(enc);
1315   silc_buffer_free(enc);
1316   return TRUE;
1317 }
1318
1319 /* Saves private key into file. */
1320
1321 bool silc_pkcs_save_private_key(const char *filename,
1322                                 SilcPrivateKey private_key,
1323                                 unsigned char *passphrase,
1324                                 SilcUInt32 passphrase_len,
1325                                 SilcUInt32 encoding)
1326 {
1327   unsigned char *data;
1328   SilcUInt32 data_len;
1329   bool ret;
1330
1331   data = silc_pkcs_private_key_encode(private_key, &data_len);
1332   ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1333                                             passphrase, passphrase_len,
1334                                             encoding);
1335   memset(data, 0, data_len);
1336   silc_free(data);
1337   return ret;
1338 }
1339
1340 /* Loads public key from file and allocates new public key. Returns TRUE
1341    if loading was successful. */
1342
1343 bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1344                                SilcUInt32 encoding)
1345 {
1346   unsigned char *cp, *old, *data, byte;
1347   SilcUInt32 i, data_len, len;
1348
1349   SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1350                   encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1351                   encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1352   
1353   old = data = silc_file_readfile(filename, &data_len);
1354   if (!data)
1355     return FALSE;
1356
1357   /* Check start of file and remove header from the data. */
1358   len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1359   cp = data;
1360   for (i = 0; i < len; i++) {
1361     byte = cp[0];
1362     cp++;
1363     if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1364       memset(old, 0, data_len);
1365       silc_free(old);
1366       return FALSE;
1367     }
1368   }
1369   data = cp;
1370
1371   /* Decode public key */
1372   if (public_key) {
1373     len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1374                       strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1375
1376     switch(encoding) {
1377     case SILC_PKCS_FILE_BIN:
1378       break;
1379     case SILC_PKCS_FILE_PEM:
1380       data = silc_pem_decode(data, len, &len);
1381       memset(old, 0, data_len);
1382       silc_free(old);
1383       old = data; 
1384       data_len = len;
1385       break;
1386     }
1387
1388     if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1389       memset(old, 0, data_len);
1390       silc_free(old);
1391       return FALSE;
1392     }
1393   }
1394
1395   memset(old, 0, data_len);
1396   silc_free(old);
1397   return TRUE;
1398 }
1399
1400 /* Load private key from file and allocates new private key. Returns TRUE
1401    if loading was successful. */
1402
1403 bool silc_pkcs_load_private_key(const char *filename,
1404                                 SilcPrivateKey *private_key,
1405                                 unsigned char *passphrase,
1406                                 SilcUInt32 passphrase_len,
1407                                 SilcUInt32 encoding)
1408 {
1409   SilcCipher aes;
1410   SilcHash sha1;
1411   SilcHmac sha1hmac;
1412   SilcUInt32 blocklen;
1413   unsigned char tmp[32], keymat[64];
1414   unsigned char *cp, *old, *data, byte;
1415   SilcUInt32 i, data_len, len, magic, mac_len;
1416
1417   SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1418                   encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1419                   encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1420   
1421   old = data = silc_file_readfile(filename, &data_len);
1422   if (!data)
1423     return FALSE;
1424
1425   /* Check start of file and remove header from the data. */
1426   len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1427   cp = data;
1428   for (i = 0; i < len; i++) {
1429     byte = cp[0];
1430     cp++;
1431     if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1432       memset(old, 0, data_len);
1433       silc_free(old);
1434       return FALSE;
1435     }
1436   }
1437   data = cp;
1438
1439   /* Decode private key */
1440   len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1441                     strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1442
1443   switch(encoding) {
1444   case SILC_PKCS_FILE_BIN:
1445     break;
1446   case SILC_PKCS_FILE_PEM:
1447     data = silc_pem_decode(data, len, &len);
1448     if (!data) {
1449       memset(old, 0, data_len);
1450       silc_free(old);
1451       return FALSE;
1452     }
1453     break;
1454   }
1455
1456   memset(tmp, 0, sizeof(tmp));
1457   memset(keymat, 0, sizeof(keymat));
1458
1459   /* Private key files without the specific magic number are assumed
1460      to be the old-style private keys that are not encrypted. */
1461   SILC_GET32_MSB(magic, data);
1462   if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1463     SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1464
1465     /* Now decode the actual private key */
1466     if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1467       memset(old, 0, data_len);
1468       silc_free(old);
1469       return FALSE;
1470     }
1471
1472     memset(old, 0, data_len);
1473     silc_free(old);
1474     return TRUE;
1475   }
1476
1477   /* Allocate the AES cipher */
1478   if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1479     SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1480     memset(old, 0, data_len);
1481     silc_free(old);
1482     return FALSE;
1483   }
1484   blocklen = silc_cipher_get_block_len(aes);
1485   if (blocklen * 2 > sizeof(tmp)) {
1486     memset(old, 0, data_len);
1487     silc_free(old);
1488     return FALSE;
1489   }
1490
1491   /* Allocate SHA1 hash */
1492   if (!silc_hash_alloc("sha1", &sha1)) {
1493     SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1494     silc_cipher_free(aes);
1495     memset(old, 0, data_len);
1496     silc_free(old);
1497     return FALSE;
1498   }
1499
1500   /* Allocate HMAC */
1501   if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1502     SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1503     silc_hash_free(sha1);
1504     silc_cipher_free(aes);
1505     memset(old, 0, data_len);
1506     silc_free(old);
1507     return FALSE;
1508   }
1509
1510   /* Derive the decryption key from the provided key material.  The key
1511      is 256 bits length, and derived by taking hash of the data, then 
1512      re-hashing the data and the previous digest, and using the first and
1513      second digest as the key. */
1514   silc_hash_init(sha1);
1515   silc_hash_update(sha1, passphrase, passphrase_len);
1516   silc_hash_final(sha1, keymat);
1517   silc_hash_init(sha1);
1518   silc_hash_update(sha1, passphrase, passphrase_len);
1519   silc_hash_update(sha1, keymat, 16);
1520   silc_hash_final(sha1, keymat + 16);
1521
1522   /* Set the key to the cipher */
1523   silc_cipher_set_key(aes, keymat, 256);
1524
1525   /* First, verify the MAC of the private key data */
1526   mac_len = silc_hmac_len(sha1hmac);
1527   silc_hmac_init_with_key(sha1hmac, keymat, 16);
1528   silc_hmac_update(sha1hmac, data, len - mac_len);
1529   silc_hmac_final(sha1hmac, tmp, NULL);
1530   if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1531     SILC_LOG_DEBUG(("Integrity check for private key failed"));
1532     memset(keymat, 0, sizeof(keymat));
1533     memset(tmp, 0, sizeof(tmp));
1534     silc_hmac_free(sha1hmac);
1535     silc_hash_free(sha1);
1536     silc_cipher_free(aes);
1537     memset(old, 0, data_len);
1538     silc_free(old);
1539     return FALSE;
1540   }
1541   data += 4;
1542   len -= 4;
1543
1544   /* Decrypt the private key buffer */
1545   silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1546   SILC_GET32_MSB(i, data);
1547   if (i > len) {
1548     SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1549     memset(keymat, 0, sizeof(keymat));
1550     memset(tmp, 0, sizeof(tmp));
1551     silc_hmac_free(sha1hmac);
1552     silc_hash_free(sha1);
1553     silc_cipher_free(aes);
1554     memset(old, 0, data_len);
1555     silc_free(old);
1556     return FALSE;
1557   }
1558   data += 4;
1559   len = i;
1560
1561   /* Cleanup */
1562   memset(keymat, 0, sizeof(keymat));
1563   memset(tmp, 0, sizeof(tmp));
1564   silc_hmac_free(sha1hmac);
1565   silc_hash_free(sha1);
1566   silc_cipher_free(aes);
1567
1568   /* Now decode the actual private key */
1569   if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1570     memset(old, 0, data_len);
1571     silc_free(old);
1572     return FALSE;
1573   }
1574
1575   memset(old, 0, data_len);
1576   silc_free(old);
1577   return TRUE;
1578 }