5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 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.
23 #include "silcpkcs1_i.h"
26 #include "silcssh_pkcs.h"
27 #endif /* SILC_DIST_SSH */
30 /* Dynamically registered list of PKCS. */
31 SilcDList silc_pkcs_list = NULL;
32 SilcDList silc_pkcs_alg_list = NULL;
33 #define SILC_PKCS_LIST silc_pkcs_list
34 #define SILC_PKCS_ALG_LIST silc_pkcs_alg_list
36 #define SILC_PKCS_LIST TRUE
37 #define SILC_PKCS_ALG_LIST TRUE
38 #endif /* SILC_SYMBIAN */
40 /* Static list of PKCS for silc_pkcs_register_default(). */
41 const SilcPKCSObject silc_default_pkcs[] =
46 silc_pkcs_silc_get_algorithm,
47 silc_pkcs_silc_import_public_key_file,
48 silc_pkcs_silc_import_public_key,
49 silc_pkcs_silc_export_public_key_file,
50 silc_pkcs_silc_export_public_key,
51 silc_pkcs_silc_public_key_bitlen,
52 silc_pkcs_silc_public_key_copy,
53 silc_pkcs_silc_public_key_compare,
54 silc_pkcs_silc_public_key_free,
55 silc_pkcs_silc_import_private_key_file,
56 silc_pkcs_silc_import_private_key,
57 silc_pkcs_silc_export_private_key_file,
58 silc_pkcs_silc_export_private_key,
59 silc_pkcs_silc_private_key_bitlen,
60 silc_pkcs_silc_private_key_free,
61 silc_pkcs_silc_encrypt,
62 silc_pkcs_silc_decrypt,
64 silc_pkcs_silc_verify,
71 silc_pkcs_ssh_get_algorithm,
72 silc_pkcs_ssh_import_public_key_file,
73 silc_pkcs_ssh_import_public_key,
74 silc_pkcs_ssh_export_public_key_file,
75 silc_pkcs_ssh_export_public_key,
76 silc_pkcs_ssh_public_key_bitlen,
77 silc_pkcs_ssh_public_key_copy,
78 silc_pkcs_ssh_public_key_compare,
79 silc_pkcs_ssh_public_key_free,
80 silc_pkcs_ssh_import_private_key_file,
81 silc_pkcs_ssh_import_private_key,
82 silc_pkcs_ssh_export_private_key_file,
83 silc_pkcs_ssh_export_private_key,
84 silc_pkcs_ssh_private_key_bitlen,
85 silc_pkcs_ssh_private_key_free,
86 silc_pkcs_ssh_encrypt,
87 silc_pkcs_ssh_decrypt,
91 #endif /* SILC_DIST_SSH */
94 0, NULL, NULL, NULL, NULL, NULL,
95 NULL, NULL, NULL, NULL, NULL
99 /* Builtin PKCS algorithms */
100 const SilcPKCSAlgorithm silc_default_pkcs_alg[] =
102 /* PKCS #1, Version 1.5 without hash OIDs */
107 silc_pkcs1_generate_key,
108 silc_pkcs1_import_public_key,
109 silc_pkcs1_export_public_key,
110 silc_pkcs1_public_key_bitlen,
111 silc_pkcs1_public_key_copy,
112 silc_pkcs1_public_key_compare,
113 silc_pkcs1_public_key_free,
114 silc_pkcs1_import_private_key,
115 silc_pkcs1_export_private_key,
116 silc_pkcs1_private_key_bitlen,
117 silc_pkcs1_private_key_free,
120 silc_pkcs1_sign_no_oid,
121 silc_pkcs1_verify_no_oid
124 /* PKCS #1, Version 1.5 */
129 silc_pkcs1_generate_key,
130 silc_pkcs1_import_public_key,
131 silc_pkcs1_export_public_key,
132 silc_pkcs1_public_key_bitlen,
133 silc_pkcs1_public_key_copy,
134 silc_pkcs1_public_key_compare,
135 silc_pkcs1_public_key_free,
136 silc_pkcs1_import_private_key,
137 silc_pkcs1_export_private_key,
138 silc_pkcs1_private_key_bitlen,
139 silc_pkcs1_private_key_free,
151 silc_dsa_generate_key,
152 silc_dsa_import_public_key,
153 silc_dsa_export_public_key,
154 silc_dsa_public_key_bitlen,
155 silc_dsa_public_key_copy,
156 silc_dsa_public_key_compare,
157 silc_dsa_public_key_free,
158 silc_dsa_import_private_key,
159 silc_dsa_export_private_key,
160 silc_dsa_private_key_bitlen,
161 silc_dsa_private_key_free,
169 /* PKCS #1, Version 1.5 without hash OIDs, SSH2 style public keys */
174 silc_pkcs1_generate_key,
175 silc_ssh_rsa_import_public_key,
176 silc_ssh_rsa_export_public_key,
177 silc_pkcs1_public_key_bitlen,
178 silc_pkcs1_public_key_copy,
179 silc_pkcs1_public_key_compare,
180 silc_pkcs1_public_key_free,
181 silc_pkcs1_import_private_key,
182 silc_pkcs1_export_private_key,
183 silc_pkcs1_private_key_bitlen,
184 silc_pkcs1_private_key_free,
191 /* DSS, SSH2 style public keys */
196 silc_dsa_generate_key,
197 silc_ssh_dsa_import_public_key,
198 silc_ssh_dsa_export_public_key,
199 silc_dsa_public_key_bitlen,
200 silc_dsa_public_key_copy,
201 silc_dsa_public_key_compare,
202 silc_dsa_public_key_free,
203 silc_dsa_import_private_key,
204 silc_dsa_export_private_key,
205 silc_dsa_private_key_bitlen,
206 silc_dsa_private_key_free,
212 #endif /* SILC_DIST_SSH */
215 NULL, NULL, NULL, NULL,
216 NULL, NULL, NULL, NULL,
217 NULL, NULL, NULL, NULL,
222 /* Register a new PKCS */
224 SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
227 SilcPKCSObject *newpkcs;
229 SILC_LOG_DEBUG(("Registering new PKCS"));
231 /* Check if exists already */
232 if (silc_pkcs_list) {
233 SilcPKCSObject *entry;
234 silc_dlist_start(silc_pkcs_list);
235 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
236 if (entry->type == pkcs->type)
241 newpkcs = silc_calloc(1, sizeof(*newpkcs));
247 if (silc_pkcs_list == NULL)
248 silc_pkcs_list = silc_dlist_init();
249 silc_dlist_add(silc_pkcs_list, newpkcs);
251 #endif /* SILC_SYMBIAN */
255 /* Unregister a PKCS */
257 SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs)
260 SilcPKCSObject *entry;
262 SILC_LOG_DEBUG(("Unregistering PKCS"));
267 silc_dlist_start(silc_pkcs_list);
268 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
269 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
270 silc_dlist_del(silc_pkcs_list, entry);
273 if (silc_dlist_count(silc_pkcs_list) == 0) {
274 silc_dlist_uninit(silc_pkcs_list);
275 silc_pkcs_list = NULL;
282 #endif /* SILC_SYMBIAN */
286 /* Register algorithm */
288 SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs)
291 SilcPKCSAlgorithm *newalg;
293 SILC_LOG_DEBUG(("Registering new PKCS algorithm %s",
296 /* Check if exists already */
297 if (silc_pkcs_alg_list) {
298 SilcPKCSAlgorithm *entry;
299 silc_dlist_start(silc_pkcs_alg_list);
300 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
301 if (!strcmp(entry->name, pkcs->name) &&
302 entry->scheme && pkcs->scheme &&
303 !strcmp(entry->scheme, pkcs->scheme))
308 newalg = silc_calloc(1, sizeof(*newalg));
313 newalg->name = strdup(pkcs->name);
317 newalg->scheme = strdup(pkcs->scheme);
321 newalg->hash = strdup(pkcs->hash);
326 if (silc_pkcs_alg_list == NULL)
327 silc_pkcs_alg_list = silc_dlist_init();
328 silc_dlist_add(silc_pkcs_alg_list, newalg);
330 #endif /* SILC_SYMBIAN */
334 /* Unregister algorithm */
336 SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs)
339 SilcPKCSAlgorithm*entry;
341 SILC_LOG_DEBUG(("Unregistering PKCS algorithm"));
343 if (!silc_pkcs_alg_list)
346 silc_dlist_start(silc_pkcs_alg_list);
347 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
348 if (pkcs == SILC_ALL_PKCS_ALG || entry == pkcs) {
349 silc_dlist_del(silc_pkcs_alg_list, entry);
350 silc_free(entry->name);
351 silc_free(entry->scheme);
352 silc_free(entry->hash);
355 if (silc_dlist_count(silc_pkcs_alg_list) == 0) {
356 silc_dlist_uninit(silc_pkcs_alg_list);
357 silc_pkcs_alg_list = NULL;
364 #endif /* SILC_SYMBIAN */
368 /* Function that registers all the default PKCS and PKCS algorithms. */
370 SilcBool silc_pkcs_register_default(void)
372 /* We use builtin PKCS and algorithms */
376 /* Unregister all PKCS and algorithms */
378 SilcBool silc_pkcs_unregister_all(void)
381 SilcPKCSObject *entry;
382 SilcPKCSAlgorithm *alg;
384 if (silc_pkcs_list) {
385 silc_dlist_start(silc_pkcs_list);
386 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
387 silc_pkcs_unregister(entry);
393 if (silc_pkcs_alg_list) {
394 silc_dlist_start(silc_pkcs_alg_list);
395 while ((alg = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
396 silc_pkcs_algorithm_unregister(alg);
397 if (!silc_pkcs_alg_list)
402 #endif /* SILC_SYMBIAN */
406 /* Returns comma separated list of supported PKCS algorithms */
408 char *silc_pkcs_get_supported(void)
410 SilcPKCSAlgorithm *entry, *entry2;
415 if (silc_pkcs_alg_list) {
416 silc_dlist_start(silc_pkcs_alg_list);
417 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
418 len += strlen(entry->name);
419 list = silc_realloc(list, len + 1);
423 memcpy(list + (len - strlen(entry->name)),
424 entry->name, strlen(entry->name));
425 memcpy(list + len, ",", 1);
429 #endif /* SILC_SYMBIAN */
431 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
432 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
434 if (silc_pkcs_alg_list) {
435 silc_dlist_start(silc_pkcs_alg_list);
436 while ((entry2 = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
437 if (!strcmp(entry2->name, entry->name))
444 len += strlen(entry->name);
445 list = silc_realloc(list, len + 1);
449 memcpy(list + (len - strlen(entry->name)),
450 entry->name, strlen(entry->name));
451 memcpy(list + len, ",", 1);
460 /* Finds PKCS object */
462 const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type)
464 SilcPKCSObject *entry;
468 if (silc_pkcs_list) {
469 silc_dlist_start(silc_pkcs_list);
470 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
471 if (entry->type == type)
472 return (const SilcPKCSObject *)entry;
475 #endif /* SILC_SYMBIAN */
477 for (i = 0; silc_default_pkcs[i].type; i++) {
478 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
479 if (entry->type == type)
480 return (const SilcPKCSObject *)entry;
486 /* Finds PKCS algorithms object */
488 const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
491 SilcPKCSAlgorithm *entry;
495 if (silc_pkcs_alg_list) {
496 silc_dlist_start(silc_pkcs_alg_list);
497 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
498 if (!strcmp(entry->name, algorithm) &&
499 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
500 return (const SilcPKCSAlgorithm *)entry;
503 #endif /* SILC_SYMBIAN */
505 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
506 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
507 if (!strcmp(entry->name, algorithm) &&
508 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
509 return (const SilcPKCSAlgorithm *)entry;
515 /* Returns PKCS context */
517 const SilcPKCSObject *silc_pkcs_get_pkcs(void *key)
519 SilcPublicKey public_key = key;
520 return public_key->pkcs;
523 /* Returns PKCS algorithm context */
525 const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(void *key)
527 SilcPublicKey public_key = key;
528 return public_key->alg;
531 /* Return algorithm name */
533 const char *silc_pkcs_get_name(void *key)
535 const SilcPKCSAlgorithm *pkcs = silc_pkcs_get_algorithm(key);
539 /* Returns PKCS type */
541 SilcPKCSType silc_pkcs_get_type(void *key)
543 SilcPublicKey public_key = key;
544 return public_key->pkcs->type;
547 /* Allocates new public key from the key data */
549 SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
552 SilcPublicKey *ret_public_key)
554 const SilcPKCSObject *pkcs;
555 SilcPublicKey public_key;
560 /* Allocate public key context */
561 public_key = silc_calloc(1, sizeof(*public_key));
565 pkcs = silc_pkcs_find_pkcs(type);
566 public_key->pkcs = (SilcPKCSObject *)pkcs;
567 if (!public_key->pkcs) {
568 silc_free(public_key);
572 /* Import the PKCS public key */
573 if (!pkcs->import_public_key(pkcs, NULL, key, key_len,
574 &public_key->public_key,
576 silc_free(public_key);
580 *ret_public_key = public_key;
585 /* Frees the public key */
587 void silc_pkcs_public_key_free(SilcPublicKey public_key)
589 public_key->pkcs->public_key_free(public_key->pkcs, public_key->public_key);
590 silc_free(public_key);
593 /* Exports public key */
595 unsigned char *silc_pkcs_public_key_encode(SilcStack stack,
596 SilcPublicKey public_key,
599 return public_key->pkcs->export_public_key(public_key->pkcs, stack,
600 public_key->public_key, ret_len);
603 /* Return key length */
605 SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key)
607 return public_key->pkcs->public_key_bitlen(public_key->pkcs,
608 public_key->public_key);
611 /* Returns internal PKCS public key context */
613 void *silc_pkcs_public_key_get_pkcs(SilcPKCSType type,
614 SilcPublicKey public_key)
616 if (public_key->pkcs->type != type)
618 return public_key->public_key;
621 /* Returns internal PKCS private key context */
623 void *silc_pkcs_private_key_get_pkcs(SilcPKCSType type,
624 SilcPrivateKey private_key)
626 if (private_key->pkcs->type != type)
628 return private_key->private_key;
631 /* Allocates new private key from key data */
633 SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
636 SilcPrivateKey *ret_private_key)
638 const SilcPKCSObject *pkcs;
639 SilcPrivateKey private_key;
641 if (!ret_private_key)
644 /* Allocate private key context */
645 private_key = silc_calloc(1, sizeof(*private_key));
649 pkcs = silc_pkcs_find_pkcs(type);
650 private_key->pkcs = (SilcPKCSObject *)pkcs;
651 if (!private_key->pkcs) {
652 silc_free(private_key);
656 /* Import the PKCS private key */
657 if (!pkcs->import_private_key(pkcs, NULL, key, key_len,
658 &private_key->private_key,
659 &private_key->alg)) {
660 silc_free(private_key);
664 *ret_private_key = private_key;
669 /* Return key length */
671 SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key)
673 return private_key->pkcs->private_key_bitlen(private_key->pkcs,
674 private_key->private_key);
677 /* Frees the private key */
679 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
681 private_key->pkcs->private_key_free(private_key->pkcs,
682 private_key->private_key);
683 silc_free(private_key);
688 SilcAsyncOperation silc_pkcs_encrypt(SilcPublicKey public_key,
689 unsigned char *src, SilcUInt32 src_len,
691 SilcPKCSEncryptCb encrypt_cb,
694 return public_key->pkcs->encrypt(public_key->pkcs,
695 public_key->public_key, src, src_len,
696 rng, encrypt_cb, context);
701 SilcAsyncOperation silc_pkcs_decrypt(SilcPrivateKey private_key,
702 unsigned char *src, SilcUInt32 src_len,
703 SilcPKCSDecryptCb decrypt_cb,
706 return private_key->pkcs->decrypt(private_key->pkcs,
707 private_key->private_key, src, src_len,
708 decrypt_cb, context);
711 /* Generates signature */
713 SilcAsyncOperation silc_pkcs_sign(SilcPrivateKey private_key,
716 SilcBool compute_hash,
719 SilcPKCSSignCb sign_cb,
722 return private_key->pkcs->sign(private_key->pkcs,
723 private_key->private_key, src, src_len,
724 compute_hash, hash, rng, sign_cb, context);
727 /* Verifies signature */
729 SilcAsyncOperation silc_pkcs_verify(SilcPublicKey public_key,
730 unsigned char *signature,
731 SilcUInt32 signature_len,
735 SilcPKCSVerifyCb verify_cb,
738 return public_key->pkcs->verify(public_key->pkcs,
739 public_key->public_key, signature,
740 signature_len, data, data_len, hash, NULL,
744 /* Compares two public keys and returns TRUE if they are same key, and
745 FALSE if they are not same. */
747 SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
749 if (key1->pkcs->type != key2->pkcs->type)
752 return key1->pkcs->public_key_compare(key1->pkcs,
753 key1->public_key, key2->public_key);
756 /* Copies the public key indicated by `public_key' and returns new allocated
757 public key which is indentical to the `public_key'. */
759 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
761 SilcPublicKey key = silc_calloc(1, sizeof(*key));
765 key->pkcs = public_key->pkcs;
766 key->public_key = public_key->pkcs->public_key_copy(public_key->pkcs,
767 public_key->public_key);
768 if (!key->public_key) {
776 /* Loads any kind of public key */
778 SilcBool silc_pkcs_load_public_key(const char *filename,
780 SilcPublicKey *ret_public_key)
784 SilcPublicKey public_key;
786 SILC_LOG_DEBUG(("Loading public key file '%s'", filename));
791 data = silc_file_readfile(filename, &data_len, NULL);
793 SILC_LOG_ERROR(("No such file: %s", filename));
797 /* Allocate public key context */
798 *ret_public_key = public_key = silc_calloc(1, sizeof(*public_key));
804 if (type == SILC_PKCS_ANY) {
805 /* Try loading all types until one succeeds. */
806 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
807 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
808 if (!public_key->pkcs)
811 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
813 SILC_PKCS_FILE_BASE64,
814 &public_key->public_key,
820 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
823 &public_key->public_key,
830 /* Load specific type */
831 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
832 if (!public_key->pkcs) {
834 silc_free(public_key);
835 *ret_public_key = NULL;
836 SILC_LOG_ERROR(("Unsupported public key type"));
840 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
842 SILC_PKCS_FILE_BASE64,
843 &public_key->public_key,
849 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
852 &public_key->public_key,
860 silc_free(public_key);
861 *ret_public_key = NULL;
862 SILC_LOG_ERROR(("Unsupported public key type"));
866 /* Saves public key into a file */
868 SilcBool silc_pkcs_save_public_key(const char *filename,
869 SilcPublicKey public_key,
870 SilcPKCSFileEncoding encoding)
876 stack = silc_stack_alloc(2048, silc_crypto_stack());
878 /* Export the public key file */
879 data = public_key->pkcs->export_public_key_file(public_key->pkcs,
881 public_key->public_key,
882 encoding, &data_len);
884 silc_stack_free(stack);
889 if (silc_file_writefile(filename, data, data_len)) {
890 silc_sfree(stack, data);
891 silc_stack_free(stack);
895 silc_sfree(stack, data);
896 silc_stack_free(stack);
900 /* Loads any kind of private key */
902 SilcBool silc_pkcs_load_private_key(const char *filename,
903 const unsigned char *passphrase,
904 SilcUInt32 passphrase_len,
906 SilcPrivateKey *ret_private_key)
910 SilcPrivateKey private_key;
912 SILC_LOG_DEBUG(("Loading private key file '%s'", filename));
914 if (!ret_private_key)
917 data = silc_file_readfile(filename, &data_len, NULL);
919 SILC_LOG_ERROR(("No such file: %s", filename));
923 /* Allocate private key context */
924 *ret_private_key = private_key = silc_calloc(1, sizeof(*private_key));
930 if (type == SILC_PKCS_ANY) {
931 /* Try loading all types until one succeeds. */
932 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
933 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
934 if (!private_key->pkcs)
937 if (private_key->pkcs->import_private_key_file(
943 &private_key->private_key,
944 &private_key->alg)) {
949 if (private_key->pkcs->import_private_key_file(
954 SILC_PKCS_FILE_BASE64,
955 &private_key->private_key,
956 &private_key->alg)) {
962 /* Load specific type */
963 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
964 if (!private_key->pkcs) {
966 silc_free(private_key);
967 *ret_private_key = NULL;
968 SILC_LOG_ERROR(("Unsupported private key type"));
972 if (private_key->pkcs->import_private_key_file(
978 &private_key->private_key,
979 &private_key->alg)) {
984 if (private_key->pkcs->import_private_key_file(
989 SILC_PKCS_FILE_BASE64,
990 &private_key->private_key,
991 &private_key->alg)) {
998 silc_free(private_key);
999 *ret_private_key = NULL;
1003 /* Saves private key into a file */
1005 SilcBool silc_pkcs_save_private_key(const char *filename,
1006 SilcPrivateKey private_key,
1007 const unsigned char *passphrase,
1008 SilcUInt32 passphrase_len,
1009 SilcPKCSFileEncoding encoding,
1012 unsigned char *data;
1013 SilcUInt32 data_len;
1016 stack = silc_stack_alloc(2048, silc_crypto_stack());
1018 /* Export the private key file */
1019 data = private_key->pkcs->export_private_key_file(private_key->pkcs, stack,
1020 private_key->private_key,
1023 encoding, rng, &data_len);
1025 silc_stack_free(stack);
1030 if (silc_file_writefile(filename, data, data_len)) {
1031 silc_sfree(stack, data);
1032 silc_stack_free(stack);
1036 silc_sfree(stack, data);
1037 silc_stack_free(stack);
1041 /* Hash public key of any type. */
1043 SilcUInt32 silc_hash_public_key(void *key, void *user_context)
1045 SilcPublicKey public_key = key;
1048 SilcUInt32 hash = 0;
1049 SilcStack stack = NULL;
1051 if (silc_crypto_stack())
1052 stack = silc_stack_alloc(2048, silc_crypto_stack());
1054 pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len);
1056 silc_stack_free(stack);
1060 hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len));
1062 silc_sfree(stack, pk);
1063 silc_stack_free(stack);
1068 /* Compares two SILC Public keys. It may be used as SilcHashTable
1069 comparison function. */
1071 SilcBool silc_hash_public_key_compare(void *key1, void *key2,
1074 return silc_pkcs_public_key_compare(key1, key2);