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 */
29 /* Dynamically registered list of PKCS. */
30 SilcDList silc_pkcs_list = NULL;
31 SilcDList silc_pkcs_alg_list = NULL;
32 #define SILC_PKCS_LIST silc_pkcs_list
33 #define SILC_PKCS_ALG_LIST silc_pkcs_alg_list
35 #define SILC_PKCS_LIST TRUE
36 #define SILC_PKCS_ALG_LIST TRUE
37 #endif /* SILC_SYMBIAN */
39 /* Static list of PKCS for silc_pkcs_register_default(). */
40 const SilcPKCSObject silc_default_pkcs[] =
45 silc_pkcs_silc_get_algorithm,
46 silc_pkcs_silc_import_public_key_file,
47 silc_pkcs_silc_import_public_key,
48 silc_pkcs_silc_export_public_key_file,
49 silc_pkcs_silc_export_public_key,
50 silc_pkcs_silc_public_key_bitlen,
51 silc_pkcs_silc_public_key_copy,
52 silc_pkcs_silc_public_key_compare,
53 silc_pkcs_silc_public_key_free,
54 silc_pkcs_silc_import_private_key_file,
55 silc_pkcs_silc_import_private_key,
56 silc_pkcs_silc_export_private_key_file,
57 silc_pkcs_silc_export_private_key,
58 silc_pkcs_silc_private_key_bitlen,
59 silc_pkcs_silc_private_key_free,
60 silc_pkcs_silc_encrypt,
61 silc_pkcs_silc_decrypt,
63 silc_pkcs_silc_verify,
70 silc_pkcs_ssh_get_algorithm,
71 silc_pkcs_ssh_import_public_key_file,
72 silc_pkcs_ssh_import_public_key,
73 silc_pkcs_ssh_export_public_key_file,
74 silc_pkcs_ssh_export_public_key,
75 silc_pkcs_ssh_public_key_bitlen,
76 silc_pkcs_ssh_public_key_copy,
77 silc_pkcs_ssh_public_key_compare,
78 silc_pkcs_ssh_public_key_free,
79 silc_pkcs_ssh_import_private_key_file,
80 silc_pkcs_ssh_import_private_key,
81 silc_pkcs_ssh_export_private_key_file,
82 silc_pkcs_ssh_export_private_key,
83 silc_pkcs_ssh_private_key_bitlen,
84 silc_pkcs_ssh_private_key_free,
85 silc_pkcs_ssh_encrypt,
86 silc_pkcs_ssh_decrypt,
90 #endif /* SILC_DIST_SSH */
93 0, NULL, NULL, NULL, NULL, NULL,
94 NULL, NULL, NULL, NULL, NULL
98 /* Builtin PKCS algorithms */
99 const SilcPKCSAlgorithm silc_default_pkcs_alg[] =
101 /* PKCS #1, Version 1.5 without hash OIDs */
106 silc_pkcs1_generate_key,
107 silc_pkcs1_import_public_key,
108 silc_pkcs1_export_public_key,
109 silc_pkcs1_public_key_bitlen,
110 silc_pkcs1_public_key_copy,
111 silc_pkcs1_public_key_compare,
112 silc_pkcs1_public_key_free,
113 silc_pkcs1_import_private_key,
114 silc_pkcs1_export_private_key,
115 silc_pkcs1_private_key_bitlen,
116 silc_pkcs1_private_key_free,
119 silc_pkcs1_sign_no_oid,
120 silc_pkcs1_verify_no_oid
123 /* PKCS #1, Version 1.5 */
128 silc_pkcs1_generate_key,
129 silc_pkcs1_import_public_key,
130 silc_pkcs1_export_public_key,
131 silc_pkcs1_public_key_bitlen,
132 silc_pkcs1_public_key_copy,
133 silc_pkcs1_public_key_compare,
134 silc_pkcs1_public_key_free,
135 silc_pkcs1_import_private_key,
136 silc_pkcs1_export_private_key,
137 silc_pkcs1_private_key_bitlen,
138 silc_pkcs1_private_key_free,
150 silc_dsa_generate_key,
151 silc_dsa_import_public_key,
152 silc_dsa_export_public_key,
153 silc_dsa_public_key_bitlen,
154 silc_dsa_public_key_copy,
155 silc_dsa_public_key_compare,
156 silc_dsa_public_key_free,
157 silc_dsa_import_private_key,
158 silc_dsa_export_private_key,
159 silc_dsa_private_key_bitlen,
160 silc_dsa_private_key_free,
168 /* PKCS #1, SSH2 style public keys */
173 silc_pkcs1_generate_key,
174 silc_ssh_rsa_import_public_key,
175 silc_ssh_rsa_export_public_key,
176 silc_pkcs1_public_key_bitlen,
177 silc_pkcs1_public_key_copy,
178 silc_pkcs1_public_key_compare,
179 silc_pkcs1_public_key_free,
180 silc_pkcs1_import_private_key,
181 silc_pkcs1_export_private_key,
182 silc_pkcs1_private_key_bitlen,
183 silc_pkcs1_private_key_free,
190 /* DSS, SSH2 style public keys */
195 silc_dsa_generate_key,
196 silc_ssh_dsa_import_public_key,
197 silc_ssh_dsa_export_public_key,
198 silc_dsa_public_key_bitlen,
199 silc_dsa_public_key_copy,
200 silc_dsa_public_key_compare,
201 silc_dsa_public_key_free,
202 silc_dsa_import_private_key,
203 silc_dsa_export_private_key,
204 silc_dsa_private_key_bitlen,
205 silc_dsa_private_key_free,
211 #endif /* SILC_DIST_SSH */
214 NULL, NULL, NULL, NULL,
215 NULL, NULL, NULL, NULL,
216 NULL, NULL, NULL, NULL,
221 /* Register a new PKCS */
223 SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
226 SilcPKCSObject *newpkcs;
228 SILC_LOG_DEBUG(("Registering new PKCS"));
230 /* Check if exists already */
231 if (silc_pkcs_list) {
232 SilcPKCSObject *entry;
233 silc_dlist_start(silc_pkcs_list);
234 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
235 if (entry->type == pkcs->type)
240 newpkcs = silc_calloc(1, sizeof(*newpkcs));
246 if (silc_pkcs_list == NULL)
247 silc_pkcs_list = silc_dlist_init();
248 silc_dlist_add(silc_pkcs_list, newpkcs);
250 #endif /* SILC_SYMBIAN */
254 /* Unregister a PKCS */
256 SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs)
259 SilcPKCSObject *entry;
261 SILC_LOG_DEBUG(("Unregistering PKCS"));
266 silc_dlist_start(silc_pkcs_list);
267 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
268 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
269 silc_dlist_del(silc_pkcs_list, entry);
272 if (silc_dlist_count(silc_pkcs_list) == 0) {
273 silc_dlist_uninit(silc_pkcs_list);
274 silc_pkcs_list = NULL;
281 #endif /* SILC_SYMBIAN */
285 /* Register algorithm */
287 SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs)
290 SilcPKCSAlgorithm *newalg;
292 SILC_LOG_DEBUG(("Registering new PKCS algorithm %s",
295 /* Check if exists already */
296 if (silc_pkcs_alg_list) {
297 SilcPKCSAlgorithm *entry;
298 silc_dlist_start(silc_pkcs_alg_list);
299 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
300 if (!strcmp(entry->name, pkcs->name) &&
301 entry->scheme && pkcs->scheme &&
302 !strcmp(entry->scheme, pkcs->scheme))
307 newalg = silc_calloc(1, sizeof(*newalg));
312 newalg->name = strdup(pkcs->name);
316 newalg->scheme = strdup(pkcs->scheme);
320 newalg->hash = strdup(pkcs->hash);
325 if (silc_pkcs_alg_list == NULL)
326 silc_pkcs_alg_list = silc_dlist_init();
327 silc_dlist_add(silc_pkcs_alg_list, newalg);
329 #endif /* SILC_SYMBIAN */
333 /* Unregister algorithm */
335 SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs)
338 SilcPKCSAlgorithm*entry;
340 SILC_LOG_DEBUG(("Unregistering PKCS algorithm"));
342 if (!silc_pkcs_alg_list)
345 silc_dlist_start(silc_pkcs_alg_list);
346 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
347 if (pkcs == SILC_ALL_PKCS_ALG || entry == pkcs) {
348 silc_dlist_del(silc_pkcs_alg_list, entry);
349 silc_free(entry->name);
350 silc_free(entry->scheme);
351 silc_free(entry->hash);
354 if (silc_dlist_count(silc_pkcs_alg_list) == 0) {
355 silc_dlist_uninit(silc_pkcs_alg_list);
356 silc_pkcs_alg_list = NULL;
363 #endif /* SILC_SYMBIAN */
367 /* Function that registers all the default PKCS and PKCS algorithms. */
369 SilcBool silc_pkcs_register_default(void)
371 /* We use builtin PKCS and algorithms */
375 /* Unregister all PKCS and algorithms */
377 SilcBool silc_pkcs_unregister_all(void)
380 SilcPKCSObject *entry;
381 SilcPKCSAlgorithm *alg;
383 if (silc_pkcs_list) {
384 silc_dlist_start(silc_pkcs_list);
385 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
386 silc_pkcs_unregister(entry);
392 if (silc_pkcs_alg_list) {
393 silc_dlist_start(silc_pkcs_alg_list);
394 while ((alg = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
395 silc_pkcs_algorithm_unregister(alg);
396 if (!silc_pkcs_alg_list)
401 #endif /* SILC_SYMBIAN */
405 /* Returns comma separated list of supported PKCS algorithms */
407 char *silc_pkcs_get_supported(void)
409 SilcPKCSAlgorithm *entry, *entry2;
414 if (silc_pkcs_alg_list) {
415 silc_dlist_start(silc_pkcs_alg_list);
416 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
417 len += strlen(entry->name);
418 list = silc_realloc(list, len + 1);
422 memcpy(list + (len - strlen(entry->name)),
423 entry->name, strlen(entry->name));
424 memcpy(list + len, ",", 1);
428 #endif /* SILC_SYMBIAN */
430 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
431 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
433 if (silc_pkcs_alg_list) {
434 silc_dlist_start(silc_pkcs_alg_list);
435 while ((entry2 = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
436 if (!strcmp(entry2->name, entry->name))
443 len += strlen(entry->name);
444 list = silc_realloc(list, len + 1);
448 memcpy(list + (len - strlen(entry->name)),
449 entry->name, strlen(entry->name));
450 memcpy(list + len, ",", 1);
459 /* Finds PKCS object */
461 const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type)
463 SilcPKCSObject *entry;
467 if (silc_pkcs_list) {
468 silc_dlist_start(silc_pkcs_list);
469 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
470 if (entry->type == type)
471 return (const SilcPKCSObject *)entry;
474 #endif /* SILC_SYMBIAN */
476 for (i = 0; silc_default_pkcs[i].type; i++) {
477 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
478 if (entry->type == type)
479 return (const SilcPKCSObject *)entry;
485 /* Finds PKCS algorithms object */
487 const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
490 SilcPKCSAlgorithm *entry;
494 if (silc_pkcs_alg_list) {
495 silc_dlist_start(silc_pkcs_alg_list);
496 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
497 if (!strcmp(entry->name, algorithm) &&
498 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
499 return (const SilcPKCSAlgorithm *)entry;
502 #endif /* SILC_SYMBIAN */
504 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
505 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
506 if (!strcmp(entry->name, algorithm) &&
507 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
508 return (const SilcPKCSAlgorithm *)entry;
514 /* Returns PKCS context */
516 const SilcPKCSObject *silc_pkcs_get_pkcs(void *key)
518 SilcPublicKey public_key = key;
519 return public_key->pkcs;
522 /* Returns PKCS algorithm context */
524 const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(void *key)
526 SilcPublicKey public_key = key;
527 return public_key->alg;
530 /* Return algorithm name */
532 const char *silc_pkcs_get_name(void *key)
534 const SilcPKCSAlgorithm *pkcs = silc_pkcs_get_algorithm(key);
538 /* Returns PKCS type */
540 SilcPKCSType silc_pkcs_get_type(void *key)
542 SilcPublicKey public_key = key;
543 return public_key->pkcs->type;
546 /* Allocates new public key from the key data */
548 SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
551 SilcPublicKey *ret_public_key)
553 const SilcPKCSObject *pkcs;
554 SilcPublicKey public_key;
559 /* Allocate public key context */
560 public_key = silc_calloc(1, sizeof(*public_key));
564 pkcs = silc_pkcs_find_pkcs(type);
565 public_key->pkcs = (SilcPKCSObject *)pkcs;
566 if (!public_key->pkcs) {
567 silc_free(public_key);
571 /* Import the PKCS public key */
572 if (!pkcs->import_public_key(pkcs, NULL, key, key_len,
573 &public_key->public_key,
575 silc_free(public_key);
579 *ret_public_key = public_key;
584 /* Frees the public key */
586 void silc_pkcs_public_key_free(SilcPublicKey public_key)
588 public_key->pkcs->public_key_free(public_key->pkcs, public_key->public_key);
589 silc_free(public_key);
592 /* Exports public key */
594 unsigned char *silc_pkcs_public_key_encode(SilcStack stack,
595 SilcPublicKey public_key,
598 return public_key->pkcs->export_public_key(public_key->pkcs, stack,
599 public_key->public_key, ret_len);
602 /* Return key length */
604 SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key)
606 return public_key->pkcs->public_key_bitlen(public_key->pkcs,
607 public_key->public_key);
610 /* Returns internal PKCS public key context */
612 void *silc_pkcs_public_key_get_pkcs(SilcPKCSType type,
613 SilcPublicKey public_key)
615 if (public_key->pkcs->type != type)
617 return public_key->public_key;
620 /* Returns internal PKCS private key context */
622 void *silc_pkcs_private_key_get_pkcs(SilcPKCSType type,
623 SilcPrivateKey private_key)
625 if (private_key->pkcs->type != type)
627 return private_key->private_key;
630 /* Allocates new private key from key data */
632 SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
635 SilcPrivateKey *ret_private_key)
637 const SilcPKCSObject *pkcs;
638 SilcPrivateKey private_key;
640 if (!ret_private_key)
643 /* Allocate private key context */
644 private_key = silc_calloc(1, sizeof(*private_key));
648 pkcs = silc_pkcs_find_pkcs(type);
649 private_key->pkcs = (SilcPKCSObject *)pkcs;
650 if (!private_key->pkcs) {
651 silc_free(private_key);
655 /* Import the PKCS private key */
656 if (!pkcs->import_private_key(pkcs, NULL, key, key_len,
657 &private_key->private_key,
658 &private_key->alg)) {
659 silc_free(private_key);
663 *ret_private_key = private_key;
668 /* Return key length */
670 SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key)
672 return private_key->pkcs->private_key_bitlen(private_key->pkcs,
673 private_key->private_key);
676 /* Frees the private key */
678 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
680 private_key->pkcs->private_key_free(private_key->pkcs,
681 private_key->private_key);
682 silc_free(private_key);
687 SilcAsyncOperation silc_pkcs_encrypt(SilcPublicKey public_key,
688 unsigned char *src, SilcUInt32 src_len,
690 SilcPKCSEncryptCb encrypt_cb,
693 return public_key->pkcs->encrypt(public_key->pkcs,
694 public_key->public_key, src, src_len,
695 rng, encrypt_cb, context);
700 SilcAsyncOperation silc_pkcs_decrypt(SilcPrivateKey private_key,
701 unsigned char *src, SilcUInt32 src_len,
702 SilcPKCSDecryptCb decrypt_cb,
705 return private_key->pkcs->decrypt(private_key->pkcs,
706 private_key->private_key, src, src_len,
707 decrypt_cb, context);
710 /* Generates signature */
712 SilcAsyncOperation silc_pkcs_sign(SilcPrivateKey private_key,
715 SilcBool compute_hash,
718 SilcPKCSSignCb sign_cb,
721 return private_key->pkcs->sign(private_key->pkcs,
722 private_key->private_key, src, src_len,
723 compute_hash, hash, rng, sign_cb, context);
726 /* Verifies signature */
728 SilcAsyncOperation silc_pkcs_verify(SilcPublicKey public_key,
729 unsigned char *signature,
730 SilcUInt32 signature_len,
734 SilcPKCSVerifyCb verify_cb,
737 return public_key->pkcs->verify(public_key->pkcs,
738 public_key->public_key, signature,
739 signature_len, data, data_len, hash, NULL,
743 /* Compares two public keys and returns TRUE if they are same key, and
744 FALSE if they are not same. */
746 SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
748 if (key1->pkcs->type != key2->pkcs->type)
751 return key1->pkcs->public_key_compare(key1->pkcs,
752 key1->public_key, key2->public_key);
755 /* Copies the public key indicated by `public_key' and returns new allocated
756 public key which is indentical to the `public_key'. */
758 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
760 SilcPublicKey key = silc_calloc(1, sizeof(*key));
764 key->pkcs = public_key->pkcs;
765 key->public_key = public_key->pkcs->public_key_copy(public_key->pkcs,
766 public_key->public_key);
767 if (!key->public_key) {
775 /* Loads any kind of public key */
777 SilcBool silc_pkcs_load_public_key(const char *filename,
779 SilcPublicKey *ret_public_key)
783 SilcPublicKey public_key;
785 SILC_LOG_DEBUG(("Loading public key file '%s'", filename));
790 data = silc_file_readfile(filename, &data_len, NULL);
792 SILC_LOG_ERROR(("No such file: %s", filename));
796 /* Allocate public key context */
797 *ret_public_key = public_key = silc_calloc(1, sizeof(*public_key));
803 if (type == SILC_PKCS_ANY) {
804 /* Try loading all types until one succeeds. */
805 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
806 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
807 if (!public_key->pkcs)
810 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
812 SILC_PKCS_FILE_BASE64,
813 &public_key->public_key,
819 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
822 &public_key->public_key,
829 /* Load specific type */
830 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
831 if (!public_key->pkcs) {
833 silc_free(public_key);
834 *ret_public_key = NULL;
835 SILC_LOG_ERROR(("Unsupported public key type"));
839 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
841 SILC_PKCS_FILE_BASE64,
842 &public_key->public_key,
848 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
851 &public_key->public_key,
859 silc_free(public_key);
860 *ret_public_key = NULL;
861 SILC_LOG_ERROR(("Unsupported public key type"));
865 /* Saves public key into a file */
867 SilcBool silc_pkcs_save_public_key(const char *filename,
868 SilcPublicKey public_key,
869 SilcPKCSFileEncoding encoding)
875 stack = silc_stack_alloc(2048, silc_crypto_stack());
877 /* Export the public key file */
878 data = public_key->pkcs->export_public_key_file(public_key->pkcs,
880 public_key->public_key,
881 encoding, &data_len);
883 silc_stack_free(stack);
888 if (silc_file_writefile(filename, data, data_len)) {
889 silc_sfree(stack, data);
890 silc_stack_free(stack);
894 silc_sfree(stack, data);
895 silc_stack_free(stack);
899 /* Loads any kind of private key */
901 SilcBool silc_pkcs_load_private_key(const char *filename,
902 const unsigned char *passphrase,
903 SilcUInt32 passphrase_len,
905 SilcPrivateKey *ret_private_key)
909 SilcPrivateKey private_key;
911 SILC_LOG_DEBUG(("Loading private key file '%s'", filename));
913 if (!ret_private_key)
916 data = silc_file_readfile(filename, &data_len, NULL);
918 SILC_LOG_ERROR(("No such file: %s", filename));
922 /* Allocate private key context */
923 *ret_private_key = private_key = silc_calloc(1, sizeof(*private_key));
929 if (type == SILC_PKCS_ANY) {
930 /* Try loading all types until one succeeds. */
931 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
932 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
933 if (!private_key->pkcs)
936 if (private_key->pkcs->import_private_key_file(
942 &private_key->private_key,
943 &private_key->alg)) {
948 if (private_key->pkcs->import_private_key_file(
953 SILC_PKCS_FILE_BASE64,
954 &private_key->private_key,
955 &private_key->alg)) {
961 /* Load specific type */
962 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
963 if (!private_key->pkcs) {
965 silc_free(private_key);
966 *ret_private_key = NULL;
967 SILC_LOG_ERROR(("Unsupported private key type"));
971 if (private_key->pkcs->import_private_key_file(
977 &private_key->private_key,
978 &private_key->alg)) {
983 if (private_key->pkcs->import_private_key_file(
988 SILC_PKCS_FILE_BASE64,
989 &private_key->private_key,
990 &private_key->alg)) {
997 silc_free(private_key);
998 *ret_private_key = NULL;
1002 /* Saves private key into a file */
1004 SilcBool silc_pkcs_save_private_key(const char *filename,
1005 SilcPrivateKey private_key,
1006 const unsigned char *passphrase,
1007 SilcUInt32 passphrase_len,
1008 SilcPKCSFileEncoding encoding,
1011 unsigned char *data;
1012 SilcUInt32 data_len;
1015 stack = silc_stack_alloc(2048, silc_crypto_stack());
1017 /* Export the private key file */
1018 data = private_key->pkcs->export_private_key_file(private_key->pkcs, stack,
1019 private_key->private_key,
1022 encoding, rng, &data_len);
1024 silc_stack_free(stack);
1029 if (silc_file_writefile(filename, data, data_len)) {
1030 silc_sfree(stack, data);
1031 silc_stack_free(stack);
1035 silc_sfree(stack, data);
1036 silc_stack_free(stack);
1040 /* Hash public key of any type. */
1042 SilcUInt32 silc_hash_public_key(void *key, void *user_context)
1044 SilcPublicKey public_key = key;
1047 SilcUInt32 hash = 0;
1048 SilcStack stack = NULL;
1050 if (silc_crypto_stack())
1051 stack = silc_stack_alloc(2048, silc_crypto_stack());
1053 pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len);
1055 silc_stack_free(stack);
1059 hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len));
1061 silc_sfree(stack, pk);
1062 silc_stack_free(stack);
1067 /* Compares two SILC Public keys. It may be used as SilcHashTable
1068 comparison function. */
1070 SilcBool silc_hash_public_key_compare(void *key1, void *key2,
1073 return silc_pkcs_public_key_compare(key1, key2);