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,
201 silc_dsa_generate_key,
202 silc_dsa_import_public_key,
203 silc_dsa_export_public_key,
204 silc_dsa_public_key_bitlen,
205 silc_dsa_public_key_copy,
206 silc_dsa_public_key_compare,
207 silc_dsa_public_key_free,
208 silc_dsa_import_private_key,
209 silc_dsa_export_private_key,
210 silc_dsa_private_key_bitlen,
211 silc_dsa_private_key_free,
219 /* PKCS #1, SSH2 style public keys */
224 silc_pkcs1_generate_key,
225 silc_ssh_rsa_import_public_key,
226 silc_ssh_rsa_export_public_key,
227 silc_pkcs1_public_key_bitlen,
228 silc_pkcs1_public_key_copy,
229 silc_pkcs1_public_key_compare,
230 silc_pkcs1_public_key_free,
231 silc_pkcs1_import_private_key,
232 silc_pkcs1_export_private_key,
233 silc_pkcs1_private_key_bitlen,
234 silc_pkcs1_private_key_free,
241 /* DSS FIPS186-2, SSH2 style public keys */
245 "sha1,sha224,sha256,sha384,sha512",
246 silc_dsa_fips186_2_generate_key,
247 silc_ssh_dsa_import_public_key,
248 silc_ssh_dsa_export_public_key,
249 silc_dsa_public_key_bitlen,
250 silc_dsa_public_key_copy,
251 silc_dsa_public_key_compare,
252 silc_dsa_public_key_free,
253 silc_dsa_import_private_key,
254 silc_dsa_export_private_key,
255 silc_dsa_private_key_bitlen,
256 silc_dsa_private_key_free,
262 #endif /* SILC_DIST_SSH */
265 /* PKCS #1, OpenPGP style public keys */
270 silc_pkcs1_generate_key,
271 silc_pgp_rsa_import_public_key,
272 silc_pgp_rsa_export_public_key,
273 silc_pkcs1_public_key_bitlen,
274 silc_pkcs1_public_key_copy,
275 silc_pkcs1_public_key_compare,
276 silc_pkcs1_public_key_free,
277 silc_pgp_rsa_import_private_key,
278 silc_pgp_rsa_export_private_key,
279 silc_pkcs1_private_key_bitlen,
280 silc_pkcs1_private_key_free,
287 /* DSS, OpenPGP style public keys */
291 "sha1,sha224,sha256,sha384,sha512",
292 silc_dsa_generate_key,
293 silc_pgp_dsa_import_public_key,
294 silc_pgp_dsa_export_public_key,
295 silc_dsa_public_key_bitlen,
296 silc_dsa_public_key_copy,
297 silc_dsa_public_key_compare,
298 silc_dsa_public_key_free,
299 silc_pgp_dsa_import_private_key,
300 silc_pgp_dsa_export_private_key,
301 silc_dsa_private_key_bitlen,
302 silc_dsa_private_key_free,
308 #endif /* SILC_DIST_PGP */
311 NULL, NULL, NULL, NULL,
312 NULL, NULL, NULL, NULL,
313 NULL, NULL, NULL, NULL,
318 /* Register a new PKCS */
320 SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
323 SilcPKCSObject *newpkcs;
325 SILC_LOG_DEBUG(("Registering new PKCS"));
327 /* Check if exists already */
328 if (silc_pkcs_list) {
329 SilcPKCSObject *entry;
330 silc_dlist_start(silc_pkcs_list);
331 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
332 if (entry->type == pkcs->type)
337 newpkcs = silc_calloc(1, sizeof(*newpkcs));
343 if (silc_pkcs_list == NULL)
344 silc_pkcs_list = silc_dlist_init();
345 silc_dlist_add(silc_pkcs_list, newpkcs);
347 #endif /* SILC_SYMBIAN */
351 /* Unregister a PKCS */
353 SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs)
356 SilcPKCSObject *entry;
358 SILC_LOG_DEBUG(("Unregistering PKCS"));
363 silc_dlist_start(silc_pkcs_list);
364 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
365 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
366 silc_dlist_del(silc_pkcs_list, entry);
369 if (silc_dlist_count(silc_pkcs_list) == 0) {
370 silc_dlist_uninit(silc_pkcs_list);
371 silc_pkcs_list = NULL;
378 #endif /* SILC_SYMBIAN */
382 /* Register algorithm */
384 SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs)
387 SilcPKCSAlgorithm *newalg;
389 SILC_LOG_DEBUG(("Registering new PKCS algorithm %s",
392 /* Check if exists already */
393 if (silc_pkcs_alg_list) {
394 SilcPKCSAlgorithm *entry;
395 silc_dlist_start(silc_pkcs_alg_list);
396 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
397 if (!strcmp(entry->name, pkcs->name) &&
398 entry->scheme && pkcs->scheme &&
399 !strcmp(entry->scheme, pkcs->scheme))
404 newalg = silc_calloc(1, sizeof(*newalg));
409 newalg->name = strdup(pkcs->name);
413 newalg->scheme = strdup(pkcs->scheme);
417 newalg->hash = strdup(pkcs->hash);
422 if (silc_pkcs_alg_list == NULL)
423 silc_pkcs_alg_list = silc_dlist_init();
424 silc_dlist_add(silc_pkcs_alg_list, newalg);
426 #endif /* SILC_SYMBIAN */
430 /* Unregister algorithm */
432 SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs)
435 SilcPKCSAlgorithm*entry;
437 SILC_LOG_DEBUG(("Unregistering PKCS algorithm"));
439 if (!silc_pkcs_alg_list)
442 silc_dlist_start(silc_pkcs_alg_list);
443 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
444 if (pkcs == SILC_ALL_PKCS_ALG || entry == pkcs) {
445 silc_dlist_del(silc_pkcs_alg_list, entry);
446 silc_free(entry->name);
447 silc_free(entry->scheme);
448 silc_free(entry->hash);
451 if (silc_dlist_count(silc_pkcs_alg_list) == 0) {
452 silc_dlist_uninit(silc_pkcs_alg_list);
453 silc_pkcs_alg_list = NULL;
460 #endif /* SILC_SYMBIAN */
464 /* Function that registers all the default PKCS and PKCS algorithms. */
466 SilcBool silc_pkcs_register_default(void)
468 /* We use builtin PKCS and algorithms */
472 /* Unregister all PKCS and algorithms */
474 SilcBool silc_pkcs_unregister_all(void)
477 SilcPKCSObject *entry;
478 SilcPKCSAlgorithm *alg;
480 if (silc_pkcs_list) {
481 silc_dlist_start(silc_pkcs_list);
482 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
483 silc_pkcs_unregister(entry);
489 if (silc_pkcs_alg_list) {
490 silc_dlist_start(silc_pkcs_alg_list);
491 while ((alg = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
492 silc_pkcs_algorithm_unregister(alg);
493 if (!silc_pkcs_alg_list)
498 #endif /* SILC_SYMBIAN */
502 /* Returns comma separated list of supported PKCS algorithms */
504 char *silc_pkcs_get_supported(void)
506 SilcPKCSAlgorithm *entry, *entry2;
511 if (silc_pkcs_alg_list) {
512 silc_dlist_start(silc_pkcs_alg_list);
513 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
514 len += strlen(entry->name);
515 list = silc_realloc(list, len + 1);
519 memcpy(list + (len - strlen(entry->name)),
520 entry->name, strlen(entry->name));
521 memcpy(list + len, ",", 1);
525 #endif /* SILC_SYMBIAN */
527 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
528 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
530 if (silc_pkcs_alg_list) {
531 silc_dlist_start(silc_pkcs_alg_list);
532 while ((entry2 = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
533 if (!strcmp(entry2->name, entry->name))
540 len += strlen(entry->name);
541 list = silc_realloc(list, len + 1);
545 memcpy(list + (len - strlen(entry->name)),
546 entry->name, strlen(entry->name));
547 memcpy(list + len, ",", 1);
556 /* Finds PKCS object */
558 const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type)
560 SilcPKCSObject *entry;
564 if (silc_pkcs_list) {
565 silc_dlist_start(silc_pkcs_list);
566 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
567 if (entry->type == type)
568 return (const SilcPKCSObject *)entry;
571 #endif /* SILC_SYMBIAN */
573 for (i = 0; silc_default_pkcs[i].type; i++) {
574 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
575 if (entry->type == type)
576 return (const SilcPKCSObject *)entry;
582 /* Finds PKCS algorithms object */
584 const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
587 SilcPKCSAlgorithm *entry;
591 if (silc_pkcs_alg_list) {
592 silc_dlist_start(silc_pkcs_alg_list);
593 while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
594 if (!strcmp(entry->name, algorithm) &&
595 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
596 return (const SilcPKCSAlgorithm *)entry;
599 #endif /* SILC_SYMBIAN */
601 for (i = 0; silc_default_pkcs_alg[i].name; i++) {
602 entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
603 if (!strcmp(entry->name, algorithm) &&
604 (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
605 return (const SilcPKCSAlgorithm *)entry;
611 /* Returns PKCS context */
613 const SilcPKCSObject *silc_pkcs_get_pkcs(void *key)
615 SilcPublicKey public_key = key;
616 return public_key->pkcs;
619 /* Returns PKCS algorithm context */
621 const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(void *key)
623 SilcPublicKey public_key = key;
624 return public_key->alg;
627 /* Return algorithm name */
629 const char *silc_pkcs_get_name(void *key)
631 const SilcPKCSAlgorithm *pkcs = silc_pkcs_get_algorithm(key);
635 /* Returns PKCS type */
637 SilcPKCSType silc_pkcs_get_type(void *key)
639 SilcPublicKey public_key = key;
640 return public_key->pkcs->type;
643 /* Allocates new public key from the key data */
645 SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
648 SilcPublicKey *ret_public_key)
650 const SilcPKCSObject *pkcs;
651 SilcPublicKey public_key;
656 /* Allocate public key context */
657 public_key = silc_calloc(1, sizeof(*public_key));
661 if (type == SILC_PKCS_ANY) {
662 /* Try loading all types until one succeeds. */
663 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
664 pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
668 /* Import the PKCS public key */
669 if (pkcs->import_public_key(pkcs, NULL, key, key_len,
670 &public_key->public_key,
672 public_key->pkcs = (SilcPKCSObject *)pkcs;
673 *ret_public_key = public_key;
678 pkcs = silc_pkcs_find_pkcs(type);
679 public_key->pkcs = (SilcPKCSObject *)pkcs;
680 if (!public_key->pkcs) {
681 silc_free(public_key);
685 /* Import the PKCS public key */
686 if (pkcs->import_public_key(pkcs, NULL, key, key_len,
687 &public_key->public_key,
689 *ret_public_key = public_key;
694 silc_free(public_key);
698 /* Frees the public key */
700 void silc_pkcs_public_key_free(SilcPublicKey public_key)
702 public_key->pkcs->public_key_free(public_key->pkcs, public_key->public_key);
703 silc_free(public_key);
706 /* Exports public key */
708 unsigned char *silc_pkcs_public_key_encode(SilcStack stack,
709 SilcPublicKey public_key,
712 return public_key->pkcs->export_public_key(public_key->pkcs, stack,
713 public_key->public_key, ret_len);
716 /* Return key length */
718 SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key)
720 return public_key->pkcs->public_key_bitlen(public_key->pkcs,
721 public_key->public_key);
724 /* Returns internal PKCS public key context */
726 void *silc_pkcs_public_key_get_pkcs(SilcPKCSType type,
727 SilcPublicKey public_key)
729 if (public_key->pkcs->type != type)
731 return public_key->public_key;
734 /* Returns internal PKCS private key context */
736 void *silc_pkcs_private_key_get_pkcs(SilcPKCSType type,
737 SilcPrivateKey private_key)
739 if (private_key->pkcs->type != type)
741 return private_key->private_key;
744 /* Allocates new private key from key data */
746 SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
749 SilcPrivateKey *ret_private_key)
751 const SilcPKCSObject *pkcs;
752 SilcPrivateKey private_key;
754 if (!ret_private_key)
757 /* Allocate private key context */
758 private_key = silc_calloc(1, sizeof(*private_key));
762 pkcs = silc_pkcs_find_pkcs(type);
763 private_key->pkcs = (SilcPKCSObject *)pkcs;
764 if (!private_key->pkcs) {
765 silc_free(private_key);
769 /* Import the PKCS private key */
770 if (!pkcs->import_private_key(pkcs, NULL, NULL, 0, key, key_len,
771 &private_key->private_key,
772 &private_key->alg)) {
773 silc_free(private_key);
777 *ret_private_key = private_key;
782 /* Return key length */
784 SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key)
786 return private_key->pkcs->private_key_bitlen(private_key->pkcs,
787 private_key->private_key);
790 /* Frees the private key */
792 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
794 private_key->pkcs->private_key_free(private_key->pkcs,
795 private_key->private_key);
796 silc_free(private_key);
799 /* PKCS operation context */
807 /* Encrypt, decrypt, sign callback */
809 static void silc_pkcs_op_cb(SilcBool success,
810 const unsigned char *data,
811 SilcUInt32 data_len, void *context)
813 SilcPKCSOperation *ctx = context;
815 ctx->result = success;
820 if (data_len > ctx->dst_size) {
825 memcpy(ctx->dst, data, data_len);
827 *ctx->dst_len = data_len;
830 /* Verify callback */
832 static void silc_pkcs_verify_cb(SilcBool success, void *context)
834 SilcPKCSOperation *ctx = context;
835 ctx->result = success;
840 SilcBool silc_pkcs_encrypt(SilcPublicKey public_key,
841 unsigned char *src, SilcUInt32 src_len,
842 unsigned char *dst, SilcUInt32 dst_size,
843 SilcUInt32 *dst_len, SilcRng rng)
845 SilcPKCSOperation ctx;
848 ctx.dst_size = dst_size;
849 ctx.dst_len = dst_len;
851 public_key->pkcs->encrypt(public_key->pkcs,
852 public_key->public_key, src, src_len,
853 rng, silc_pkcs_op_cb, &ctx);
858 /* Encrypts, async */
861 silc_pkcs_encrypt_async(SilcPublicKey public_key,
862 unsigned char *src, SilcUInt32 src_len,
864 SilcPKCSEncryptCb encrypt_cb,
867 return public_key->pkcs->encrypt(public_key->pkcs,
868 public_key->public_key, src, src_len,
869 rng, encrypt_cb, context);
874 SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key,
875 unsigned char *src, SilcUInt32 src_len,
876 unsigned char *dst, SilcUInt32 dst_size,
879 SilcPKCSOperation ctx;
882 ctx.dst_size = dst_size;
883 ctx.dst_len = dst_len;
885 private_key->pkcs->decrypt(private_key->pkcs,
886 private_key->private_key, src, src_len,
887 silc_pkcs_op_cb, &ctx);
892 /* Decrypts, async */
895 silc_pkcs_decrypt_async(SilcPrivateKey private_key,
896 unsigned char *src, SilcUInt32 src_len,
897 SilcPKCSDecryptCb decrypt_cb,
900 return private_key->pkcs->decrypt(private_key->pkcs,
901 private_key->private_key, src, src_len,
902 decrypt_cb, context);
905 /* Generates signature */
907 SilcBool silc_pkcs_sign(SilcPrivateKey private_key,
908 unsigned char *src, SilcUInt32 src_len,
909 unsigned char *dst, SilcUInt32 dst_size,
910 SilcUInt32 *dst_len, SilcBool compute_hash,
911 SilcHash hash, SilcRng rng)
913 SilcPKCSOperation ctx;
916 ctx.dst_size = dst_size;
917 ctx.dst_len = dst_len;
919 private_key->pkcs->sign(private_key->pkcs,
920 private_key->private_key, src, src_len,
921 compute_hash, hash, rng,
922 silc_pkcs_op_cb, &ctx);
927 /* Generates signature, async */
929 SilcAsyncOperation silc_pkcs_sign_async(SilcPrivateKey private_key,
932 SilcBool compute_hash,
935 SilcPKCSSignCb sign_cb,
938 return private_key->pkcs->sign(private_key->pkcs,
939 private_key->private_key, src, src_len,
940 compute_hash, hash, rng, sign_cb, context);
943 /* Verifies signature */
945 SilcBool silc_pkcs_verify(SilcPublicKey public_key,
946 unsigned char *signature,
947 SilcUInt32 signature_len,
950 SilcBool compute_hash,
953 SilcPKCSOperation ctx;
955 public_key->pkcs->verify(public_key->pkcs,
956 public_key->public_key, signature,
957 signature_len, data, data_len,
958 compute_hash, hash, NULL,
959 silc_pkcs_verify_cb, &ctx);
964 /* Verifies signature, async */
966 SilcAsyncOperation silc_pkcs_verify_async(SilcPublicKey public_key,
967 unsigned char *signature,
968 SilcUInt32 signature_len,
971 SilcBool compute_hash,
973 SilcPKCSVerifyCb verify_cb,
976 return public_key->pkcs->verify(public_key->pkcs,
977 public_key->public_key, signature,
978 signature_len, data, data_len,
979 compute_hash, hash, NULL,
983 /* Compares two public keys and returns TRUE if they are same key, and
984 FALSE if they are not same. */
986 SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
988 if (key1->pkcs->type != key2->pkcs->type)
991 return key1->pkcs->public_key_compare(key1->pkcs,
992 key1->public_key, key2->public_key);
995 /* Copies the public key indicated by `public_key' and returns new allocated
996 public key which is indentical to the `public_key'. */
998 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
1000 SilcPublicKey key = silc_calloc(1, sizeof(*key));
1004 key->pkcs = public_key->pkcs;
1005 key->public_key = public_key->pkcs->public_key_copy(public_key->pkcs,
1006 public_key->public_key);
1007 if (!key->public_key) {
1015 /* Loads any kind of public key */
1017 SilcBool silc_pkcs_load_public_key(const char *filename,
1019 SilcPublicKey *ret_public_key)
1021 unsigned char *data;
1022 SilcUInt32 data_len;
1023 SilcPublicKey public_key;
1025 SILC_LOG_DEBUG(("Loading public key file '%s'", filename));
1027 if (!ret_public_key)
1030 data = silc_file_readfile(filename, &data_len, NULL);
1032 SILC_LOG_ERROR(("No such file: %s", filename));
1036 /* Allocate public key context */
1037 *ret_public_key = public_key = silc_calloc(1, sizeof(*public_key));
1043 if (type == SILC_PKCS_ANY) {
1044 /* Try loading all types until one succeeds. */
1045 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
1046 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
1047 if (!public_key->pkcs)
1050 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
1052 SILC_PKCS_FILE_BASE64,
1053 &public_key->public_key,
1054 &public_key->alg)) {
1059 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
1062 &public_key->public_key,
1063 &public_key->alg)) {
1069 /* Load specific type */
1070 public_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
1071 if (!public_key->pkcs) {
1073 silc_free(public_key);
1074 *ret_public_key = NULL;
1075 SILC_LOG_ERROR(("Unsupported public key type"));
1079 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
1081 SILC_PKCS_FILE_BASE64,
1082 &public_key->public_key,
1083 &public_key->alg)) {
1088 if (public_key->pkcs->import_public_key_file(public_key->pkcs,
1091 &public_key->public_key,
1092 &public_key->alg)) {
1099 silc_free(public_key);
1100 *ret_public_key = NULL;
1101 SILC_LOG_ERROR(("Unsupported public key type"));
1105 /* Saves public key into a file */
1107 SilcBool silc_pkcs_save_public_key(const char *filename,
1108 SilcPublicKey public_key,
1109 SilcPKCSFileEncoding encoding)
1111 unsigned char *data;
1112 SilcUInt32 data_len;
1115 stack = silc_stack_alloc(2048, silc_crypto_stack());
1117 /* Export the public key file */
1118 data = public_key->pkcs->export_public_key_file(public_key->pkcs,
1120 public_key->public_key,
1121 encoding, &data_len);
1123 silc_stack_free(stack);
1128 if (silc_file_writefile(filename, data, data_len)) {
1129 silc_sfree(stack, data);
1130 silc_stack_free(stack);
1134 silc_sfree(stack, data);
1135 silc_stack_free(stack);
1139 /* Loads any kind of private key */
1141 SilcBool silc_pkcs_load_private_key(const char *filename,
1142 const unsigned char *passphrase,
1143 SilcUInt32 passphrase_len,
1145 SilcPrivateKey *ret_private_key)
1147 unsigned char *data;
1148 SilcUInt32 data_len;
1149 SilcPrivateKey private_key;
1151 SILC_LOG_DEBUG(("Loading private key file '%s'", filename));
1153 if (!ret_private_key)
1156 data = silc_file_readfile(filename, &data_len, NULL);
1158 SILC_LOG_ERROR(("No such file: %s", filename));
1162 /* Allocate private key context */
1163 *ret_private_key = private_key = silc_calloc(1, sizeof(*private_key));
1169 if (type == SILC_PKCS_ANY) {
1170 /* Try loading all types until one succeeds. */
1171 for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
1172 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
1173 if (!private_key->pkcs)
1176 if (private_key->pkcs->import_private_key_file(
1182 &private_key->private_key,
1183 &private_key->alg)) {
1188 if (private_key->pkcs->import_private_key_file(
1193 SILC_PKCS_FILE_BASE64,
1194 &private_key->private_key,
1195 &private_key->alg)) {
1201 /* Load specific type */
1202 private_key->pkcs = (SilcPKCSObject *)silc_pkcs_find_pkcs(type);
1203 if (!private_key->pkcs) {
1205 silc_free(private_key);
1206 *ret_private_key = NULL;
1207 SILC_LOG_ERROR(("Unsupported private key type"));
1211 if (private_key->pkcs->import_private_key_file(
1217 &private_key->private_key,
1218 &private_key->alg)) {
1223 if (private_key->pkcs->import_private_key_file(
1228 SILC_PKCS_FILE_BASE64,
1229 &private_key->private_key,
1230 &private_key->alg)) {
1237 silc_free(private_key);
1238 *ret_private_key = NULL;
1242 /* Saves private key into a file */
1244 SilcBool silc_pkcs_save_private_key(const char *filename,
1245 SilcPrivateKey private_key,
1246 const unsigned char *passphrase,
1247 SilcUInt32 passphrase_len,
1248 SilcPKCSFileEncoding encoding,
1251 unsigned char *data;
1252 SilcUInt32 data_len;
1255 stack = silc_stack_alloc(2048, silc_crypto_stack());
1257 /* Export the private key file */
1258 data = private_key->pkcs->export_private_key_file(private_key->pkcs, stack,
1259 private_key->private_key,
1262 encoding, rng, &data_len);
1264 silc_stack_free(stack);
1269 if (silc_file_writefile(filename, data, data_len)) {
1270 silc_sfree(stack, data);
1271 silc_stack_free(stack);
1275 silc_sfree(stack, data);
1276 silc_stack_free(stack);
1280 /* Hash public key of any type. */
1282 SilcUInt32 silc_hash_public_key(void *key, void *user_context)
1284 SilcPublicKey public_key = key;
1287 SilcUInt32 hash = 0;
1288 SilcStack stack = NULL;
1290 if (silc_crypto_stack())
1291 stack = silc_stack_alloc(2048, silc_crypto_stack());
1293 pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len);
1295 silc_stack_free(stack);
1299 hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len));
1301 silc_sfree(stack, pk);
1302 silc_stack_free(stack);
1307 /* Compares two SILC Public keys. It may be used as SilcHashTable
1308 comparison function. */
1310 SilcBool silc_hash_public_key_compare(void *key1, void *key2,
1313 return silc_pkcs_public_key_compare(key1, key2);