5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2008 Pekka Riikonen
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.
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.
20 #include "silccrypto.h"
22 #include "silcpkcs1_i.h"
25 #include "silcssh_pkcs.h"
26 #endif /* SILC_DIST_SSH */
28 #include "silcpgp_pkcs.h"
29 #endif /* SILC_DIST_PGP */
32 /* Dynamically registered list of PKCS. */
33 SilcDList silc_pkcs_list = NULL;
34 SilcDList silc_pkcs_alg_list = NULL;
35 #define SILC_PKCS_LIST silc_pkcs_list
36 #define SILC_PKCS_ALG_LIST silc_pkcs_alg_list
38 #define SILC_PKCS_LIST TRUE
39 #define SILC_PKCS_ALG_LIST TRUE
40 #endif /* SILC_SYMBIAN */
42 /* Static list of PKCS for silc_pkcs_register_default(). */
43 const SilcPKCSObject silc_default_pkcs[] =
48 silc_pkcs_silc_get_algorithm,
49 silc_pkcs_silc_import_public_key_file,
50 silc_pkcs_silc_import_public_key,
51 silc_pkcs_silc_export_public_key_file,
52 silc_pkcs_silc_export_public_key,
53 silc_pkcs_silc_public_key_bitlen,
54 silc_pkcs_silc_public_key_copy,
55 silc_pkcs_silc_public_key_compare,
56 silc_pkcs_silc_public_key_free,
57 silc_pkcs_silc_import_private_key_file,
58 silc_pkcs_silc_import_private_key,
59 silc_pkcs_silc_export_private_key_file,
60 silc_pkcs_silc_export_private_key,
61 silc_pkcs_silc_private_key_bitlen,
62 silc_pkcs_silc_private_key_free,
63 silc_pkcs_silc_encrypt,
64 silc_pkcs_silc_decrypt,
66 silc_pkcs_silc_verify,
73 silc_pkcs_ssh_get_algorithm,
74 silc_pkcs_ssh_import_public_key_file,
75 silc_pkcs_ssh_import_public_key,
76 silc_pkcs_ssh_export_public_key_file,
77 silc_pkcs_ssh_export_public_key,
78 silc_pkcs_ssh_public_key_bitlen,
79 silc_pkcs_ssh_public_key_copy,
80 silc_pkcs_ssh_public_key_compare,
81 silc_pkcs_ssh_public_key_free,
82 silc_pkcs_ssh_import_private_key_file,
83 silc_pkcs_ssh_import_private_key,
84 silc_pkcs_ssh_export_private_key_file,
85 silc_pkcs_ssh_export_private_key,
86 silc_pkcs_ssh_private_key_bitlen,
87 silc_pkcs_ssh_private_key_free,
88 silc_pkcs_ssh_encrypt,
89 silc_pkcs_ssh_decrypt,
93 #endif /* SILC_DIST_SSH */
99 silc_pkcs_pgp_get_algorithm,
100 silc_pkcs_pgp_import_public_key_file,
101 silc_pkcs_pgp_import_public_key,
102 silc_pkcs_pgp_export_public_key_file,
103 silc_pkcs_pgp_export_public_key,
104 silc_pkcs_pgp_public_key_bitlen,
105 silc_pkcs_pgp_public_key_copy,
106 silc_pkcs_pgp_public_key_compare,
107 silc_pkcs_pgp_public_key_free,
108 silc_pkcs_pgp_import_private_key_file,
109 silc_pkcs_pgp_import_private_key,
110 silc_pkcs_pgp_export_private_key_file,
111 silc_pkcs_pgp_export_private_key,
112 silc_pkcs_pgp_private_key_bitlen,
113 silc_pkcs_pgp_private_key_free,
114 silc_pkcs_pgp_encrypt,
115 silc_pkcs_pgp_decrypt,
117 silc_pkcs_pgp_verify,
119 #endif /* SILC_DIST_PGP */
122 0, NULL, NULL, NULL, NULL, NULL,
123 NULL, NULL, NULL, NULL, NULL
127 /* Builtin PKCS algorithms */
128 const SilcPKCSAlgorithm silc_default_pkcs_alg[] =
130 /* PKCS #1, Version 1.5 without hash OIDs */
135 silc_pkcs1_generate_key,
136 silc_pkcs1_import_public_key,
137 silc_pkcs1_export_public_key,
138 silc_pkcs1_public_key_bitlen,
139 silc_pkcs1_public_key_copy,
140 silc_pkcs1_public_key_compare,
141 silc_pkcs1_public_key_free,
142 silc_pkcs1_import_private_key,
143 silc_pkcs1_export_private_key,
144 silc_pkcs1_private_key_bitlen,
145 silc_pkcs1_private_key_free,
148 silc_pkcs1_sign_no_oid,
149 silc_pkcs1_verify_no_oid
152 /* PKCS #1, Version 1.5 */
157 silc_pkcs1_generate_key,
158 silc_pkcs1_import_public_key,
159 silc_pkcs1_export_public_key,
160 silc_pkcs1_public_key_bitlen,
161 silc_pkcs1_public_key_copy,
162 silc_pkcs1_public_key_compare,
163 silc_pkcs1_public_key_free,
164 silc_pkcs1_import_private_key,
165 silc_pkcs1_export_private_key,
166 silc_pkcs1_private_key_bitlen,
167 silc_pkcs1_private_key_free,
179 silc_dsa_generate_key,
180 silc_dsa_import_public_key,
181 silc_dsa_export_public_key,
182 silc_dsa_public_key_bitlen,
183 silc_dsa_public_key_copy,
184 silc_dsa_public_key_compare,
185 silc_dsa_public_key_free,
186 silc_dsa_import_private_key,
187 silc_dsa_export_private_key,
188 silc_dsa_private_key_bitlen,
189 silc_dsa_private_key_free,
197 /* PKCS #1, SSH2 style public keys */
202 silc_pkcs1_generate_key,
203 silc_ssh_rsa_import_public_key,
204 silc_ssh_rsa_export_public_key,
205 silc_pkcs1_public_key_bitlen,
206 silc_pkcs1_public_key_copy,
207 silc_pkcs1_public_key_compare,
208 silc_pkcs1_public_key_free,
209 silc_pkcs1_import_private_key,
210 silc_pkcs1_export_private_key,
211 silc_pkcs1_private_key_bitlen,
212 silc_pkcs1_private_key_free,
219 /* DSS, SSH2 style public keys */
223 "sha1,sha224,sha256,sha384,sha512",
224 silc_dsa_generate_key,
225 silc_ssh_dsa_import_public_key,
226 silc_ssh_dsa_export_public_key,
227 silc_dsa_public_key_bitlen,
228 silc_dsa_public_key_copy,
229 silc_dsa_public_key_compare,
230 silc_dsa_public_key_free,
231 silc_dsa_import_private_key,
232 silc_dsa_export_private_key,
233 silc_dsa_private_key_bitlen,
234 silc_dsa_private_key_free,
240 #endif /* SILC_DIST_SSH */
243 /* PKCS #1, OpenPGP style public keys */
248 silc_pkcs1_generate_key,
249 silc_pgp_rsa_import_public_key,
250 silc_pgp_rsa_export_public_key,
251 silc_pkcs1_public_key_bitlen,
252 silc_pkcs1_public_key_copy,
253 silc_pkcs1_public_key_compare,
254 silc_pkcs1_public_key_free,
255 silc_pgp_rsa_import_private_key,
256 silc_pgp_rsa_export_private_key,
257 silc_pkcs1_private_key_bitlen,
258 silc_pkcs1_private_key_free,
265 /* DSS, OpenPGP style public keys */
269 "sha1,sha224,sha256,sha384,sha512",
270 silc_dsa_generate_key,
271 silc_pgp_dsa_import_public_key,
272 silc_pgp_dsa_export_public_key,
273 silc_dsa_public_key_bitlen,
274 silc_dsa_public_key_copy,
275 silc_dsa_public_key_compare,
276 silc_dsa_public_key_free,
277 silc_pgp_dsa_import_private_key,
278 silc_pgp_dsa_export_private_key,
279 silc_dsa_private_key_bitlen,
280 silc_dsa_private_key_free,
286 #endif /* SILC_DIST_PGP */
289 NULL, NULL, NULL, NULL,
290 NULL, NULL, NULL, NULL,
291 NULL, NULL, NULL, NULL,
296 /* Register a new PKCS */
298 SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
301 SilcPKCSObject *newpkcs;
303 SILC_LOG_DEBUG(("Registering new PKCS"));
305 /* Check if exists already */
306 if (silc_pkcs_list) {
307 SilcPKCSObject *entry;
308 silc_dlist_start(silc_pkcs_list);
309 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
310 if (entry->type == pkcs->type)
315 newpkcs = silc_calloc(1, sizeof(*newpkcs));
321 if (silc_pkcs_list == NULL)
322 silc_pkcs_list = silc_dlist_init();
323 silc_dlist_add(silc_pkcs_list, newpkcs);
325 #endif /* SILC_SYMBIAN */
329 /* Unregister a PKCS */
331 SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs)
334 SilcPKCSObject *entry;
336 SILC_LOG_DEBUG(("Unregistering PKCS"));
341 silc_dlist_start(silc_pkcs_list);
342 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
343 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
344 silc_dlist_del(silc_pkcs_list, entry);
347 if (silc_dlist_count(silc_pkcs_list) == 0) {
348 silc_dlist_uninit(silc_pkcs_list);
349 silc_pkcs_list = NULL;
356 #endif /* SILC_SYMBIAN */
360 /* Register algorithm */
362 SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs)
365 SilcPKCSAlgorithm *newalg;
367 SILC_LOG_DEBUG(("Registering new PKCS algorithm %s",
370 /* Check if exists already */
371 if (silc_pkcs_alg_list) {
372 SilcPKCSAlgorithm *entry;
373 silc_dlist_start(silc_pkcs_alg_list);
374 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
375 if (!strcmp(entry->name, pkcs->name) &&
376 entry->scheme && pkcs->scheme &&
377 !strcmp(entry->scheme, pkcs->scheme))
382 newalg = silc_calloc(1, sizeof(*newalg));
387 newalg->name = strdup(pkcs->name);
391 newalg->scheme = strdup(pkcs->scheme);
395 newalg->hash = strdup(pkcs->hash);
400 if (silc_pkcs_alg_list == NULL)
401 silc_pkcs_alg_list = silc_dlist_init();
402 silc_dlist_add(silc_pkcs_alg_list, newalg);
404 #endif /* SILC_SYMBIAN */
408 /* Unregister algorithm */
410 SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs)
413 SilcPKCSAlgorithm*entry;
415 SILC_LOG_DEBUG(("Unregistering PKCS algorithm"));
417 if (!silc_pkcs_alg_list)
420 silc_dlist_start(silc_pkcs_alg_list);
421 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
422 if (pkcs == SILC_ALL_PKCS_ALG || entry == pkcs) {
423 silc_dlist_del(silc_pkcs_alg_list, entry);
424 silc_free(entry->name);
425 silc_free(entry->scheme);
426 silc_free(entry->hash);
429 if (silc_dlist_count(silc_pkcs_alg_list) == 0) {
430 silc_dlist_uninit(silc_pkcs_alg_list);
431 silc_pkcs_alg_list = NULL;
438 #endif /* SILC_SYMBIAN */
442 /* Function that registers all the default PKCS and PKCS algorithms. */
444 SilcBool silc_pkcs_register_default(void)
446 /* We use builtin PKCS and algorithms */
450 /* Unregister all PKCS and algorithms */
452 SilcBool silc_pkcs_unregister_all(void)
455 SilcPKCSObject *entry;
456 SilcPKCSAlgorithm *alg;
458 if (silc_pkcs_list) {
459 silc_dlist_start(silc_pkcs_list);
460 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
461 silc_pkcs_unregister(entry);
467 if (silc_pkcs_alg_list) {
468 silc_dlist_start(silc_pkcs_alg_list);
469 while ((alg = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
470 silc_pkcs_algorithm_unregister(alg);
471 if (!silc_pkcs_alg_list)
476 #endif /* SILC_SYMBIAN */
480 /* Returns comma separated list of supported PKCS algorithms */
482 char *silc_pkcs_get_supported(void)
484 SilcPKCSAlgorithm *entry, *entry2;
489 if (silc_pkcs_alg_list) {
490 silc_dlist_start(silc_pkcs_alg_list);
491 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
492 len += strlen(entry->name);
493 list = silc_realloc(list, len + 1);
497 memcpy(list + (len - strlen(entry->name)),
498 entry->name, strlen(entry->name));
499 memcpy(list + len, ",", 1);
503 #endif /* SILC_SYMBIAN */
505 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
506 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
508 if (silc_pkcs_alg_list) {
509 silc_dlist_start(silc_pkcs_alg_list);
510 while ((entry2 = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
511 if (!strcmp(entry2->name, entry->name))
518 len += strlen(entry->name);
519 list = silc_realloc(list, len + 1);
523 memcpy(list + (len - strlen(entry->name)),
524 entry->name, strlen(entry->name));
525 memcpy(list + len, ",", 1);
534 /* Finds PKCS object */
536 const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type)
538 SilcPKCSObject *entry;
542 if (silc_pkcs_list) {
543 silc_dlist_start(silc_pkcs_list);
544 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
545 if (entry->type == type)
546 return (const SilcPKCSObject *)entry;
549 #endif /* SILC_SYMBIAN */
551 for (i = 0; silc_default_pkcs[i].type; i++) {
552 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
553 if (entry->type == type)
554 return (const SilcPKCSObject *)entry;
560 /* Finds PKCS algorithms object */
562 const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
565 SilcPKCSAlgorithm *entry;
569 if (silc_pkcs_alg_list) {
570 silc_dlist_start(silc_pkcs_alg_list);
571 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
572 if (!strcmp(entry->name, algorithm) &&
573 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
574 return (const SilcPKCSAlgorithm *)entry;
577 #endif /* SILC_SYMBIAN */
579 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
580 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
581 if (!strcmp(entry->name, algorithm) &&
582 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
583 return (const SilcPKCSAlgorithm *)entry;
589 /* Returns PKCS context */
591 const SilcPKCSObject *silc_pkcs_get_pkcs(void *key)
593 SilcPublicKey public_key = key;
594 return public_key->pkcs;
597 /* Returns PKCS algorithm context */
599 const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(void *key)
601 SilcPublicKey public_key = key;
602 return public_key->alg;
605 /* Return algorithm name */
607 const char *silc_pkcs_get_name(void *key)
609 const SilcPKCSAlgorithm *pkcs = silc_pkcs_get_algorithm(key);
613 /* Returns PKCS type */
615 SilcPKCSType silc_pkcs_get_type(void *key)
617 SilcPublicKey public_key = key;
618 return public_key->pkcs->type;
621 /* Allocates new public key from the key data */
623 SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
626 SilcPublicKey *ret_public_key)
628 const SilcPKCSObject *pkcs;
629 SilcPublicKey public_key;
634 /* Allocate public key context */
635 public_key = silc_calloc(1, sizeof(*public_key));
639 pkcs = silc_pkcs_find_pkcs(type);
640 public_key->pkcs = (SilcPKCSObject *)pkcs;
641 if (!public_key->pkcs) {
642 silc_free(public_key);
646 /* Import the PKCS public key */
647 if (!pkcs->import_public_key(pkcs, NULL, key, key_len,
648 &public_key->public_key,
650 silc_free(public_key);
654 *ret_public_key = public_key;
659 /* Frees the public key */
661 void silc_pkcs_public_key_free(SilcPublicKey public_key)
663 public_key->pkcs->public_key_free(public_key->pkcs, public_key->public_key);
664 silc_free(public_key);
667 /* Exports public key */
669 unsigned char *silc_pkcs_public_key_encode(SilcStack stack,
670 SilcPublicKey public_key,
673 return public_key->pkcs->export_public_key(public_key->pkcs, stack,
674 public_key->public_key, ret_len);
677 /* Return key length */
679 SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key)
681 return public_key->pkcs->public_key_bitlen(public_key->pkcs,
682 public_key->public_key);
685 /* Returns internal PKCS public key context */
687 void *silc_pkcs_public_key_get_pkcs(SilcPKCSType type,
688 SilcPublicKey public_key)
690 if (public_key->pkcs->type != type)
692 return public_key->public_key;
695 /* Returns internal PKCS private key context */
697 void *silc_pkcs_private_key_get_pkcs(SilcPKCSType type,
698 SilcPrivateKey private_key)
700 if (private_key->pkcs->type != type)
702 return private_key->private_key;
705 /* Allocates new private key from key data */
707 SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
710 SilcPrivateKey *ret_private_key)
712 const SilcPKCSObject *pkcs;
713 SilcPrivateKey private_key;
715 if (!ret_private_key)
718 /* Allocate private key context */
719 private_key = silc_calloc(1, sizeof(*private_key));
723 pkcs = silc_pkcs_find_pkcs(type);
724 private_key->pkcs = (SilcPKCSObject *)pkcs;
725 if (!private_key->pkcs) {
726 silc_free(private_key);
730 /* Import the PKCS private key */
731 if (!pkcs->import_private_key(pkcs, NULL, NULL, 0, key, key_len,
732 &private_key->private_key,
733 &private_key->alg)) {
734 silc_free(private_key);
738 *ret_private_key = private_key;
743 /* Return key length */
745 SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key)
747 return private_key->pkcs->private_key_bitlen(private_key->pkcs,
748 private_key->private_key);
751 /* Frees the private key */
753 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
755 private_key->pkcs->private_key_free(private_key->pkcs,
756 private_key->private_key);
757 silc_free(private_key);
762 SilcAsyncOperation silc_pkcs_encrypt(SilcPublicKey public_key,
763 unsigned char *src, SilcUInt32 src_len,
765 SilcPKCSEncryptCb encrypt_cb,
768 return public_key->pkcs->encrypt(public_key->pkcs,
769 public_key->public_key, src, src_len,
770 rng, encrypt_cb, context);
775 SilcAsyncOperation silc_pkcs_decrypt(SilcPrivateKey private_key,
776 unsigned char *src, SilcUInt32 src_len,
777 SilcPKCSDecryptCb decrypt_cb,
780 return private_key->pkcs->decrypt(private_key->pkcs,
781 private_key->private_key, src, src_len,
782 decrypt_cb, context);
785 /* Generates signature */
787 SilcAsyncOperation silc_pkcs_sign(SilcPrivateKey private_key,
790 SilcBool compute_hash,
793 SilcPKCSSignCb sign_cb,
796 return private_key->pkcs->sign(private_key->pkcs,
797 private_key->private_key, src, src_len,
798 compute_hash, hash, rng, sign_cb, context);
801 /* Verifies signature */
803 SilcAsyncOperation silc_pkcs_verify(SilcPublicKey public_key,
804 unsigned char *signature,
805 SilcUInt32 signature_len,
809 SilcPKCSVerifyCb verify_cb,
812 return public_key->pkcs->verify(public_key->pkcs,
813 public_key->public_key, signature,
814 signature_len, data, data_len, hash, NULL,
818 /* Compares two public keys and returns TRUE if they are same key, and
819 FALSE if they are not same. */
821 SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
823 if (key1->pkcs->type != key2->pkcs->type)
826 return key1->pkcs->public_key_compare(key1->pkcs,
827 key1->public_key, key2->public_key);
830 /* Copies the public key indicated by `public_key' and returns new allocated
831 public key which is indentical to the `public_key'. */
833 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
835 SilcPublicKey key = silc_calloc(1, sizeof(*key));
839 key->pkcs = public_key->pkcs;
840 key->public_key = public_key->pkcs->public_key_copy(public_key->pkcs,
841 public_key->public_key);
842 if (!key->public_key) {
850 /* Loads any kind of public key */
852 SilcBool silc_pkcs_load_public_key(const char *filename,
854 SilcPublicKey *ret_public_key)
858 SilcPublicKey public_key;
860 SILC_LOG_DEBUG(("Loading public key file '%s'", filename));
865 data = silc_file_readfile(filename, &data_len, NULL);
867 SILC_LOG_ERROR(("No such file: %s", filename));
871 /* Allocate public key context */
872 *ret_public_key = public_key = silc_calloc(1, sizeof(*public_key));
878 if (type == SILC_PKCS_ANY) {
879 /* Try loading all types until one succeeds. */
880 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
881 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
882 if (!public_key->pkcs)
885 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
887 SILC_PKCS_FILE_BASE64,
888 &public_key->public_key,
894 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
897 &public_key->public_key,
904 /* Load specific type */
905 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
906 if (!public_key->pkcs) {
908 silc_free(public_key);
909 *ret_public_key = NULL;
910 SILC_LOG_ERROR(("Unsupported public key type"));
914 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
916 SILC_PKCS_FILE_BASE64,
917 &public_key->public_key,
923 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
926 &public_key->public_key,
934 silc_free(public_key);
935 *ret_public_key = NULL;
936 SILC_LOG_ERROR(("Unsupported public key type"));
940 /* Saves public key into a file */
942 SilcBool silc_pkcs_save_public_key(const char *filename,
943 SilcPublicKey public_key,
944 SilcPKCSFileEncoding encoding)
950 stack = silc_stack_alloc(2048, silc_crypto_stack());
952 /* Export the public key file */
953 data = public_key->pkcs->export_public_key_file(public_key->pkcs,
955 public_key->public_key,
956 encoding, &data_len);
958 silc_stack_free(stack);
963 if (silc_file_writefile(filename, data, data_len)) {
964 silc_sfree(stack, data);
965 silc_stack_free(stack);
969 silc_sfree(stack, data);
970 silc_stack_free(stack);
974 /* Loads any kind of private key */
976 SilcBool silc_pkcs_load_private_key(const char *filename,
977 const unsigned char *passphrase,
978 SilcUInt32 passphrase_len,
980 SilcPrivateKey *ret_private_key)
984 SilcPrivateKey private_key;
986 SILC_LOG_DEBUG(("Loading private key file '%s'", filename));
988 if (!ret_private_key)
991 data = silc_file_readfile(filename, &data_len, NULL);
993 SILC_LOG_ERROR(("No such file: %s", filename));
997 /* Allocate private key context */
998 *ret_private_key = private_key = silc_calloc(1, sizeof(*private_key));
1004 if (type == SILC_PKCS_ANY) {
1005 /* Try loading all types until one succeeds. */
1006 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
1007 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
1008 if (!private_key->pkcs)
1011 if (private_key->pkcs->import_private_key_file(
1017 &private_key->private_key,
1018 &private_key->alg)) {
1023 if (private_key->pkcs->import_private_key_file(
1028 SILC_PKCS_FILE_BASE64,
1029 &private_key->private_key,
1030 &private_key->alg)) {
1036 /* Load specific type */
1037 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
1038 if (!private_key->pkcs) {
1040 silc_free(private_key);
1041 *ret_private_key = NULL;
1042 SILC_LOG_ERROR(("Unsupported private key type"));
1046 if (private_key->pkcs->import_private_key_file(
1052 &private_key->private_key,
1053 &private_key->alg)) {
1058 if (private_key->pkcs->import_private_key_file(
1063 SILC_PKCS_FILE_BASE64,
1064 &private_key->private_key,
1065 &private_key->alg)) {
1072 silc_free(private_key);
1073 *ret_private_key = NULL;
1077 /* Saves private key into a file */
1079 SilcBool silc_pkcs_save_private_key(const char *filename,
1080 SilcPrivateKey private_key,
1081 const unsigned char *passphrase,
1082 SilcUInt32 passphrase_len,
1083 SilcPKCSFileEncoding encoding,
1086 unsigned char *data;
1087 SilcUInt32 data_len;
1090 stack = silc_stack_alloc(2048, silc_crypto_stack());
1092 /* Export the private key file */
1093 data = private_key->pkcs->export_private_key_file(private_key->pkcs, stack,
1094 private_key->private_key,
1097 encoding, rng, &data_len);
1099 silc_stack_free(stack);
1104 if (silc_file_writefile(filename, data, data_len)) {
1105 silc_sfree(stack, data);
1106 silc_stack_free(stack);
1110 silc_sfree(stack, data);
1111 silc_stack_free(stack);
1115 /* Hash public key of any type. */
1117 SilcUInt32 silc_hash_public_key(void *key, void *user_context)
1119 SilcPublicKey public_key = key;
1122 SilcUInt32 hash = 0;
1123 SilcStack stack = NULL;
1125 if (silc_crypto_stack())
1126 stack = silc_stack_alloc(2048, silc_crypto_stack());
1128 pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len);
1130 silc_stack_free(stack);
1134 hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len));
1136 silc_sfree(stack, pk);
1137 silc_stack_free(stack);
1142 /* Compares two SILC Public keys. It may be used as SilcHashTable
1143 comparison function. */
1145 SilcBool silc_hash_public_key_compare(void *key1, void *key2,
1148 return silc_pkcs_public_key_compare(key1, key2);