aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-07-14 21:19:22 +0000
committerChristian Grothoff <christian@grothoff.org>2012-07-14 21:19:22 +0000
commita299afa8af5593c2114ca8242099d8f7971c428e (patch)
treed6474062280de16f92cb7f2239393094dcf472cd /src
parent7958f822ccba4fe2dc372c62aaaa2b2d8fe56acf (diff)
downloadgnunet-a299afa8af5593c2114ca8242099d8f7971c428e.tar.gz
gnunet-a299afa8af5593c2114ca8242099d8f7971c428e.zip
-new API for asyncronous generation of private RSA keys
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_crypto_lib.h54
-rw-r--r--src/util/crypto_rsa.c358
-rw-r--r--src/util/gnunet-config.c2
-rw-r--r--src/util/gnunet-rsa.c42
-rw-r--r--src/util/test_crypto_rsa.c83
5 files changed, 464 insertions, 75 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 33842fc27..b73d26d1e 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -860,15 +860,6 @@ GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts,
860 860
861 861
862/** 862/**
863 * Create a new private key. Caller must free return value.
864 *
865 * @return fresh private key
866 */
867struct GNUNET_CRYPTO_RsaPrivateKey *
868GNUNET_CRYPTO_rsa_key_create (void);
869
870
871/**
872 * Convert a public key to a string. 863 * Convert a public key to a string.
873 * 864 *
874 * @param pub key to convert 865 * @param pub key to convert
@@ -925,12 +916,57 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len);
925 * @param filename name of file to use for storage 916 * @param filename name of file to use for storage
926 * @return new private key, NULL on error (for example, 917 * @return new private key, NULL on error (for example,
927 * permission denied) 918 * permission denied)
919 * @deprecated use 'GNUNET_CRYPTO_rsa_key_create_start' instead
928 */ 920 */
929struct GNUNET_CRYPTO_RsaPrivateKey * 921struct GNUNET_CRYPTO_RsaPrivateKey *
930GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename); 922GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename);
931 923
932 924
933/** 925/**
926 * Handle to cancel private key generation.
927 */
928struct GNUNET_CRYPTO_RsaKeyGenerationContext;
929
930
931/**
932 * Function called upon completion of 'GNUNET_CRYPTO_rsa_key_create_async'.
933 *
934 * @param cls closure
935 * @param pk NULL on error, otherwise the private key (which must be free'd by the callee)
936 * @param emsg NULL on success, otherwise an error message
937 */
938typedef void (*GNUNET_CRYPTO_RsaKeyCallback)(void *cls,
939 struct GNUNET_CRYPTO_RsaPrivateKey *pk,
940 const char *emsg);
941
942
943/**
944 * Create a new private key by reading it from a file. If the files
945 * does not exist, create a new key and write it to the file. If the
946 * contents of the file are invalid the old file is deleted and a
947 * fresh key is created.
948 *
949 * @param filename name of file to use for storage
950 * @param cont function to call when done (or on errors)
951 * @param cont_cls closure for 'cont'
952 * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned)
953 */
954struct GNUNET_CRYPTO_RsaKeyGenerationContext *
955GNUNET_CRYPTO_rsa_key_create_start (const char *filename,
956 GNUNET_CRYPTO_RsaKeyCallback cont,
957 void *cont_cls);
958
959
960/**
961 * Abort RSA key generation.
962 *
963 * @param gc key generation context to abort
964 */
965void
966GNUNET_CRYPTO_rsa_key_create_stop (struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc);
967
968
969/**
934 * Setup a hostkey file for a peer given the name of the 970 * Setup a hostkey file for a peer given the name of the
935 * configuration file (!). This function is used so that 971 * configuration file (!). This function is used so that
936 * at a later point code can be certain that reading a 972 * at a later point code can be certain that reading a
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index bbd73083d..6e92f0753 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -34,9 +34,7 @@
34#include "platform.h" 34#include "platform.h"
35#include <gcrypt.h> 35#include <gcrypt.h>
36#include "gnunet_common.h" 36#include "gnunet_common.h"
37#include "gnunet_crypto_lib.h" 37#include "gnunet_util_lib.h"
38#include "gnunet_disk_lib.h"
39#include "gnunet_strings_lib.h"
40 38
41#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) 39#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
42 40
@@ -44,9 +42,10 @@
44 42
45#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) 43#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
46 44
45
47/** 46/**
48 * The private information of an RSA key pair. 47 * The private information of an RSA key pair.
49 * NOTE: this must match the definition in crypto_ksk.c 48 * NOTE: this must match the definition in crypto_ksk.c and gnunet-rsa.c!
50 */ 49 */
51struct GNUNET_CRYPTO_RsaPrivateKey 50struct GNUNET_CRYPTO_RsaPrivateKey
52{ 51{
@@ -81,31 +80,6 @@ adjust (unsigned char *buf, size_t size, size_t target)
81 } 80 }
82} 81}
83 82
84/**
85 * Create a new private key. Caller must free return value.
86 *
87 * @return fresh private key
88 */
89struct GNUNET_CRYPTO_RsaPrivateKey *
90GNUNET_CRYPTO_rsa_key_create ()
91{
92 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
93 gcry_sexp_t s_key;
94 gcry_sexp_t s_keyparam;
95
96 GNUNET_assert (0 ==
97 gcry_sexp_build (&s_keyparam, NULL,
98 "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
99 HOSTKEY_LEN));
100 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
101 gcry_sexp_release (s_keyparam);
102#if EXTRA_CHECKS
103 GNUNET_assert (0 == gcry_pk_testkey (s_key));
104#endif
105 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
106 ret->sexp = s_key;
107 return ret;
108}
109 83
110/** 84/**
111 * Free memory occupied by hostkey 85 * Free memory occupied by hostkey
@@ -118,6 +92,10 @@ GNUNET_CRYPTO_rsa_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *hostkey)
118 GNUNET_free (hostkey); 92 GNUNET_free (hostkey);
119} 93}
120 94
95
96/**
97 * FIXME: document!
98 */
121static int 99static int
122key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, 100key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
123 const char *elems) 101 const char *elems)
@@ -594,6 +572,98 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len)
594 572
595 573
596/** 574/**
575 * Create a new private key. Caller must free return value.
576 *
577 * @return fresh private key
578 */
579static struct GNUNET_CRYPTO_RsaPrivateKey *
580rsa_key_create ()
581{
582 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
583 gcry_sexp_t s_key;
584 gcry_sexp_t s_keyparam;
585
586 GNUNET_assert (0 ==
587 gcry_sexp_build (&s_keyparam, NULL,
588 "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
589 HOSTKEY_LEN));
590 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
591 gcry_sexp_release (s_keyparam);
592#if EXTRA_CHECKS
593 GNUNET_assert (0 == gcry_pk_testkey (s_key));
594#endif
595 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
596 ret->sexp = s_key;
597 return ret;
598}
599
600
601/**
602 * Try to read the private key from the given file.
603 *
604 * @param filename file to read the key from
605 * @return NULL on error
606 */
607static struct GNUNET_CRYPTO_RsaPrivateKey *
608try_read_key (const char *filename)
609{
610 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
611 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
612 struct GNUNET_DISK_FileHandle *fd;
613 OFF_T fs;
614 uint16_t len;
615
616 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
617 return NULL;
618
619 /* hostkey file exists already, read it! */
620 if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
621 GNUNET_DISK_PERM_NONE)))
622 {
623 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
624 return NULL;
625 }
626 if (GNUNET_OK != (GNUNET_DISK_file_handle_size (fd, &fs)))
627 {
628 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "stat", filename);
629 (void) GNUNET_DISK_file_close (fd);
630 return NULL;
631 }
632 if (fs > UINT16_MAX)
633 {
634 LOG (GNUNET_ERROR_TYPE_ERROR,
635 _("File `%s' does not contain a valid private key. Deleting it.\n"),
636 filename);
637 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
638 if (0 != UNLINK (filename))
639 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
640 return NULL;
641 }
642
643 enc = GNUNET_malloc (fs);
644 GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
645 len = ntohs (enc->len);
646 ret = NULL;
647 if ((len != fs) ||
648 (NULL == (ret = GNUNET_CRYPTO_rsa_decode_key ((char *) enc, len))))
649 {
650 LOG (GNUNET_ERROR_TYPE_ERROR,
651 _("File `%s' does not contain a valid private key. Deleting it.\n"),
652 filename);
653 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
654 if (0 != UNLINK (filename))
655 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
656 GNUNET_free (enc);
657 return NULL;
658 }
659 GNUNET_free (enc);
660
661 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
662 return ret;
663}
664
665
666/**
597 * Create a new private key by reading it from a file. If the 667 * Create a new private key by reading it from a file. If the
598 * files does not exist, create a new key and write it to the 668 * files does not exist, create a new key and write it to the
599 * file. Caller must free return value. Note that this function 669 * file. Caller must free return value. Note that this function
@@ -658,13 +728,13 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
658 { 728 {
659 ec = errno; 729 ec = errno;
660 LOG (GNUNET_ERROR_TYPE_ERROR, 730 LOG (GNUNET_ERROR_TYPE_ERROR,
661 _("Could not aquire lock on file `%s': %s...\n"), filename, 731 _("Could not acquire lock on file `%s': %s...\n"), filename,
662 STRERROR (ec)); 732 STRERROR (ec));
663 } 733 }
664 } 734 }
665 LOG (GNUNET_ERROR_TYPE_INFO, 735 LOG (GNUNET_ERROR_TYPE_INFO,
666 _("Creating a new private key. This may take a while.\n")); 736 _("Creating a new private key. This may take a while.\n"));
667 ret = GNUNET_CRYPTO_rsa_key_create (); 737 ret = rsa_key_create ();
668 GNUNET_assert (ret != NULL); 738 GNUNET_assert (ret != NULL);
669 enc = GNUNET_CRYPTO_rsa_encode_key (ret); 739 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
670 GNUNET_assert (enc != NULL); 740 GNUNET_assert (enc != NULL);
@@ -705,7 +775,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
705 { 775 {
706 ec = errno; 776 ec = errno;
707 LOG (GNUNET_ERROR_TYPE_ERROR, 777 LOG (GNUNET_ERROR_TYPE_ERROR,
708 _("Could not aquire lock on file `%s': %s...\n"), filename, 778 _("Could not acquire lock on file `%s': %s...\n"), filename,
709 STRERROR (ec)); 779 STRERROR (ec));
710 LOG (GNUNET_ERROR_TYPE_ERROR, 780 LOG (GNUNET_ERROR_TYPE_ERROR,
711 _ 781 _
@@ -786,6 +856,230 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
786 856
787 857
788/** 858/**
859 * Handle to cancel private key generation and state for the
860 * key generation operation.
861 */
862struct GNUNET_CRYPTO_RsaKeyGenerationContext
863{
864
865 /**
866 * Continuation to call upon completion.
867 */
868 GNUNET_CRYPTO_RsaKeyCallback cont;
869
870 /**
871 * Closure for 'cont'.
872 */
873 void *cont_cls;
874
875 /**
876 * Name of the file.
877 */
878 char *filename;
879
880 /**
881 * Handle to the helper process which does the key generation.
882 */
883 struct GNUNET_OS_Process *gnunet_rsa;
884
885 /**
886 * Handle to 'stdout' of gnunet-rsa. We 'read' on stdout to detect
887 * process termination (instead of messing with SIGCHLD).
888 */
889 struct GNUNET_DISK_PipeHandle *gnunet_rsa_out;
890
891 /**
892 * Location where we store the private key if it already existed.
893 * (if this is used, 'filename', 'gnunet_rsa' and 'gnunet_rsa_out' will
894 * not be used).
895 */
896 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
897
898 /**
899 * Task reading from 'gnunet_rsa_out' to wait for process termination.
900 */
901 GNUNET_SCHEDULER_TaskIdentifier read_task;
902
903};
904
905
906/**
907 * Task called upon shutdown or process termination of 'gnunet-rsa' during
908 * RSA key generation. Check where we are and perform the appropriate
909 * action.
910 *
911 * @param cls the 'struct GNUNET_CRYPTO_RsaKeyGenerationContext'
912 * @param tc scheduler context
913 */
914static void
915check_key_generation_completion (void *cls,
916 const struct GNUNET_SCHEDULER_TaskContext *tc)
917{
918 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc = cls;
919 enum GNUNET_OS_ProcessStatusType type;
920 unsigned long code;
921 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
922
923 gc->read_task = GNUNET_SCHEDULER_NO_TASK;
924 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
925 {
926 gc->cont (gc->cont_cls, NULL, _("interrupted by shutdown"));
927 GNUNET_CRYPTO_rsa_key_create_stop (gc);
928 return;
929 }
930 if (GNUNET_OK !=
931 GNUNET_OS_process_status (gc->gnunet_rsa,
932 &type, &code))
933 {
934 GNUNET_break (0);
935 gc->cont (gc->cont_cls, NULL, _("internal error"));
936 GNUNET_CRYPTO_rsa_key_create_stop (gc);
937 return;
938 }
939 GNUNET_OS_process_destroy (gc->gnunet_rsa);
940 gc->gnunet_rsa = NULL;
941 if ( (GNUNET_OS_PROCESS_EXITED != type) ||
942 (0 != code) )
943 {
944 gc->cont (gc->cont_cls, NULL, _("gnunet-rsa failed"));
945 GNUNET_CRYPTO_rsa_key_create_stop (gc);
946 return;
947 }
948 if (NULL == (pk = try_read_key (gc->filename)))
949 {
950 GNUNET_break (0);
951 gc->cont (gc->cont_cls, NULL, _("gnunet-rsa failed"));
952 GNUNET_CRYPTO_rsa_key_create_stop (gc);
953 return;
954 }
955 gc->cont (gc->cont_cls, pk, NULL);
956 GNUNET_free (gc->filename);
957 GNUNET_free (gc);
958}
959
960
961/**
962 * Return the private RSA key which already existed on disk
963 * (asynchronously) to the caller.
964 *
965 * @param cls the 'struct GNUNET_CRYPTO_RsaKeyGenerationContext'
966 * @param tc scheduler context (unused)
967 */
968static void
969async_return_key (void *cls,
970 const struct GNUNET_SCHEDULER_TaskContext *tc)
971{
972 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc = cls;
973
974 gc->cont (gc->cont_cls,
975 gc->pk,
976 NULL);
977 GNUNET_free (gc);
978}
979
980
981/**
982 * Create a new private key by reading it from a file. If the files
983 * does not exist, create a new key and write it to the file. If the
984 * contents of the file are invalid the old file is deleted and a
985 * fresh key is created.
986 *
987 * @param filename name of file to use for storage
988 * @param cont function to call when done (or on errors)
989 * @param cont_cls closure for 'cont'
990 * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned)
991 */
992struct GNUNET_CRYPTO_RsaKeyGenerationContext *
993GNUNET_CRYPTO_rsa_key_create_start (const char *filename,
994 GNUNET_CRYPTO_RsaKeyCallback cont,
995 void *cont_cls)
996{
997 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc;
998 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
999
1000 if (NULL != (pk = try_read_key (filename)))
1001 {
1002 /* quick happy ending: key already exists! */
1003 gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaKeyGenerationContext));
1004 gc->pk = pk;
1005 gc->cont = cont;
1006 gc->cont_cls = cont_cls;
1007 gc->read_task = GNUNET_SCHEDULER_add_now (&async_return_key,
1008 gc);
1009 return gc;
1010 }
1011 gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaKeyGenerationContext));
1012 gc->filename = GNUNET_strdup (filename);
1013 gc->cont = cont;
1014 gc->cont_cls = cont_cls;
1015 gc->gnunet_rsa_out = GNUNET_DISK_pipe (GNUNET_NO,
1016 GNUNET_NO,
1017 GNUNET_NO,
1018 GNUNET_YES);
1019 if (NULL == gc->gnunet_rsa_out)
1020 {
1021 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pipe");
1022 GNUNET_free (gc->filename);
1023 GNUNET_free (gc);
1024 return NULL;
1025 }
1026 gc->gnunet_rsa = GNUNET_OS_start_process (GNUNET_YES,
1027 GNUNET_OS_INHERIT_STD_ERR,
1028 NULL,
1029 gc->gnunet_rsa_out,
1030 "gnunet-rsa",
1031 "gnunet-rsa",
1032 gc->filename,
1033 NULL);
1034 if (NULL == gc->gnunet_rsa)
1035 {
1036 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fork");
1037 GNUNET_DISK_pipe_close (gc->gnunet_rsa_out);
1038 GNUNET_free (gc->filename);
1039 GNUNET_free (gc);
1040 return NULL;
1041 }
1042 GNUNET_assert (GNUNET_OK ==
1043 GNUNET_DISK_pipe_close_end (gc->gnunet_rsa_out,
1044 GNUNET_DISK_PIPE_END_WRITE));
1045 gc->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1046 GNUNET_DISK_pipe_handle (gc->gnunet_rsa_out,
1047 GNUNET_DISK_PIPE_END_READ),
1048 &check_key_generation_completion,
1049 gc);
1050 return gc;
1051}
1052
1053
1054/**
1055 * Abort RSA key generation.
1056 *
1057 * @param gc key generation context to abort
1058 */
1059void
1060GNUNET_CRYPTO_rsa_key_create_stop (struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc)
1061{
1062 GNUNET_SCHEDULER_cancel (gc->read_task);
1063 if (NULL != gc->gnunet_rsa)
1064 {
1065 (void) GNUNET_OS_process_kill (gc->gnunet_rsa, SIGKILL);
1066 GNUNET_break (GNUNET_OK ==
1067 GNUNET_OS_process_wait (gc->gnunet_rsa));
1068 GNUNET_OS_process_destroy (gc->gnunet_rsa);
1069 }
1070 if (NULL != gc->filename)
1071 {
1072 if (0 != UNLINK (gc->filename))
1073 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", gc->filename);
1074 GNUNET_free (gc->filename);
1075 }
1076 if (NULL != gc->pk)
1077 GNUNET_CRYPTO_rsa_key_free (gc->pk);
1078 GNUNET_free (gc);
1079}
1080
1081
1082/**
789 * Setup a hostkey file for a peer given the name of the 1083 * Setup a hostkey file for a peer given the name of the
790 * configuration file (!). This function is used so that 1084 * configuration file (!). This function is used so that
791 * at a later point code can be certain that reading a 1085 * at a later point code can be certain that reading a
diff --git a/src/util/gnunet-config.c b/src/util/gnunet-config.c
index 5c8a715de..c91153f69 100644
--- a/src/util/gnunet-config.c
+++ b/src/util/gnunet-config.c
@@ -146,7 +146,7 @@ run (void *cls, char *const *args, const char *cfgfile,
146 146
147 147
148/** 148/**
149 * The main function to obtain statistics in GNUnet. 149 * Program to manipulate configuration files.
150 * 150 *
151 * @param argc number of arguments from the command line 151 * @param argc number of arguments from the command line
152 * @param argv command line arguments 152 * @param argv command line arguments
diff --git a/src/util/gnunet-rsa.c b/src/util/gnunet-rsa.c
index 8fc79565a..61e1b66df 100644
--- a/src/util/gnunet-rsa.c
+++ b/src/util/gnunet-rsa.c
@@ -25,6 +25,7 @@
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include <gcrypt.h>
28 29
29 30
30/** 31/**
@@ -44,6 +45,45 @@ static int print_short_identity;
44 45
45 46
46/** 47/**
48 * The private information of an RSA key pair.
49 * NOTE: this must match the definition in crypto_ksk.c and crypto_rsa.c!
50 */
51struct GNUNET_CRYPTO_RsaPrivateKey
52{
53 gcry_sexp_t sexp;
54};
55
56
57#if 0
58/**
59 * Create a new private key. Caller must free return value.
60 *
61 * @return fresh private key
62 */
63struct GNUNET_CRYPTO_RsaPrivateKey *
64GNUNET_CRYPTO_rsa_key_create ()
65{
66 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
67 gcry_sexp_t s_key;
68 gcry_sexp_t s_keyparam;
69
70 GNUNET_assert (0 ==
71 gcry_sexp_build (&s_keyparam, NULL,
72 "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
73 HOSTKEY_LEN));
74 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
75 gcry_sexp_release (s_keyparam);
76#if EXTRA_CHECKS
77 GNUNET_assert (0 == gcry_pk_testkey (s_key));
78#endif
79 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
80 ret->sexp = s_key;
81 return ret;
82}
83#endif
84
85
86/**
47 * Main function that will be run by the scheduler. 87 * Main function that will be run by the scheduler.
48 * 88 *
49 * @param cls closure 89 * @param cls closure
@@ -100,7 +140,7 @@ run (void *cls, char *const *args, const char *cfgfile,
100 140
101 141
102/** 142/**
103 * The main function to obtain statistics in GNUnet. 143 * Program to manipulate RSA key files.
104 * 144 *
105 * @param argc number of arguments from the command line 145 * @param argc number of arguments from the command line
106 * @param argv command line arguments 146 * @param argv command line arguments
diff --git a/src/util/test_crypto_rsa.c b/src/util/test_crypto_rsa.c
index f6800afcd..0113b7ad0 100644
--- a/src/util/test_crypto_rsa.c
+++ b/src/util/test_crypto_rsa.c
@@ -36,10 +36,12 @@
36 36
37#define PERF GNUNET_YES 37#define PERF GNUNET_YES
38 38
39static struct GNUNET_CRYPTO_RsaPrivateKey *key;
40
41
39static int 42static int
40testEncryptDecrypt () 43testEncryptDecrypt ()
41{ 44{
42 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
43 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; 45 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
44 struct GNUNET_CRYPTO_RsaEncryptedData target; 46 struct GNUNET_CRYPTO_RsaEncryptedData target;
45 char result[MAX_TESTVAL]; 47 char result[MAX_TESTVAL];
@@ -48,9 +50,7 @@ testEncryptDecrypt ()
48 int ok; 50 int ok;
49 51
50 FPRINTF (stderr, "%s", "W"); 52 FPRINTF (stderr, "%s", "W");
51 hostkey = GNUNET_CRYPTO_rsa_key_create (); 53 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
52 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
53
54 ok = 0; 54 ok = 0;
55 start = GNUNET_TIME_absolute_get (); 55 start = GNUNET_TIME_absolute_get ();
56 for (i = 0; i < ITER; i++) 56 for (i = 0; i < ITER; i++)
@@ -65,7 +65,7 @@ testEncryptDecrypt ()
65 continue; 65 continue;
66 } 66 }
67 if (-1 == 67 if (-1 ==
68 GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, result, 68 GNUNET_CRYPTO_rsa_decrypt (key, &target, result,
69 strlen (TESTSTRING) + 1)) 69 strlen (TESTSTRING) + 1))
70 { 70 {
71 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n"); 71 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
@@ -84,18 +84,16 @@ testEncryptDecrypt ()
84 printf ("%d RSA encrypt/decrypt operations %llums (%d failures)\n", ITER, 84 printf ("%d RSA encrypt/decrypt operations %llums (%d failures)\n", ITER,
85 (unsigned long long) 85 (unsigned long long)
86 GNUNET_TIME_absolute_get_duration (start).rel_value, ok); 86 GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
87 GNUNET_CRYPTO_rsa_key_free (hostkey);
88 if (ok == 0) 87 if (ok == 0)
89 return GNUNET_OK; 88 return GNUNET_OK;
90 else 89 return GNUNET_SYSERR;
91 return GNUNET_SYSERR;
92} 90}
93 91
92
94#if PERF 93#if PERF
95static int 94static int
96testEncryptPerformance () 95testEncryptPerformance ()
97{ 96{
98 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
99 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; 97 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
100 struct GNUNET_CRYPTO_RsaEncryptedData target; 98 struct GNUNET_CRYPTO_RsaEncryptedData target;
101 int i; 99 int i;
@@ -103,9 +101,7 @@ testEncryptPerformance ()
103 int ok; 101 int ok;
104 102
105 FPRINTF (stderr, "%s", "W"); 103 FPRINTF (stderr, "%s", "W");
106 hostkey = GNUNET_CRYPTO_rsa_key_create (); 104 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
107 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
108
109 ok = 0; 105 ok = 0;
110 start = GNUNET_TIME_absolute_get (); 106 start = GNUNET_TIME_absolute_get ();
111 for (i = 0; i < ITER; i++) 107 for (i = 0; i < ITER; i++)
@@ -123,7 +119,6 @@ testEncryptPerformance ()
123 printf ("%d RSA encrypt operations %llu ms (%d failures)\n", ITER, 119 printf ("%d RSA encrypt operations %llu ms (%d failures)\n", ITER,
124 (unsigned long long) 120 (unsigned long long)
125 GNUNET_TIME_absolute_get_duration (start).rel_value, ok); 121 GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
126 GNUNET_CRYPTO_rsa_key_free (hostkey);
127 if (ok != 0) 122 if (ok != 0)
128 return GNUNET_SYSERR; 123 return GNUNET_SYSERR;
129 return GNUNET_OK; 124 return GNUNET_OK;
@@ -133,7 +128,6 @@ testEncryptPerformance ()
133static int 128static int
134testEncryptDecryptSK () 129testEncryptDecryptSK ()
135{ 130{
136 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
137 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; 131 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
138 struct GNUNET_CRYPTO_RsaEncryptedData target; 132 struct GNUNET_CRYPTO_RsaEncryptedData target;
139 struct GNUNET_CRYPTO_AesSessionKey insk; 133 struct GNUNET_CRYPTO_AesSessionKey insk;
@@ -143,9 +137,7 @@ testEncryptDecryptSK ()
143 int ok; 137 int ok;
144 138
145 FPRINTF (stderr, "%s", "W"); 139 FPRINTF (stderr, "%s", "W");
146 hostkey = GNUNET_CRYPTO_rsa_key_create (); 140 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
147 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
148
149 ok = 0; 141 ok = 0;
150 start = GNUNET_TIME_absolute_get (); 142 start = GNUNET_TIME_absolute_get ();
151 for (i = 0; i < ITER; i++) 143 for (i = 0; i < ITER; i++)
@@ -162,7 +154,7 @@ testEncryptDecryptSK ()
162 continue; 154 continue;
163 } 155 }
164 if (-1 == 156 if (-1 ==
165 GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, &outsk, 157 GNUNET_CRYPTO_rsa_decrypt (key, &target, &outsk,
166 sizeof (struct GNUNET_CRYPTO_AesSessionKey))) 158 sizeof (struct GNUNET_CRYPTO_AesSessionKey)))
167 { 159 {
168 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n"); 160 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
@@ -180,7 +172,6 @@ testEncryptDecryptSK ()
180 printf ("%d RSA encrypt/decrypt SK operations %llums (%d failures)\n", ITER, 172 printf ("%d RSA encrypt/decrypt SK operations %llums (%d failures)\n", ITER,
181 (unsigned long long) 173 (unsigned long long)
182 GNUNET_TIME_absolute_get_duration (start).rel_value, ok); 174 GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
183 GNUNET_CRYPTO_rsa_key_free (hostkey);
184 if (ok != 0) 175 if (ok != 0)
185 return GNUNET_SYSERR; 176 return GNUNET_SYSERR;
186 return GNUNET_OK; 177 return GNUNET_OK;
@@ -190,7 +181,6 @@ testEncryptDecryptSK ()
190static int 181static int
191testSignVerify () 182testSignVerify ()
192{ 183{
193 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
194 struct GNUNET_CRYPTO_RsaSignature sig; 184 struct GNUNET_CRYPTO_RsaSignature sig;
195 struct GNUNET_CRYPTO_RsaSignaturePurpose purp; 185 struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
196 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; 186 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
@@ -199,8 +189,7 @@ testSignVerify ()
199 int ok = GNUNET_OK; 189 int ok = GNUNET_OK;
200 190
201 FPRINTF (stderr, "%s", "W"); 191 FPRINTF (stderr, "%s", "W");
202 hostkey = GNUNET_CRYPTO_rsa_key_create (); 192 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
203 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
204 start = GNUNET_TIME_absolute_get (); 193 start = GNUNET_TIME_absolute_get ();
205 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)); 194 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
206 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); 195 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
@@ -208,7 +197,7 @@ testSignVerify ()
208 for (i = 0; i < ITER; i++) 197 for (i = 0; i < ITER; i++)
209 { 198 {
210 FPRINTF (stderr, "%s", "."); 199 FPRINTF (stderr, "%s", ".");
211 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig)) 200 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig))
212 { 201 {
213 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n"); 202 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
214 ok = GNUNET_SYSERR; 203 ok = GNUNET_SYSERR;
@@ -234,7 +223,6 @@ testSignVerify ()
234 printf ("%d RSA sign/verify operations %llums\n", ITER, 223 printf ("%d RSA sign/verify operations %llums\n", ITER,
235 (unsigned long long) 224 (unsigned long long)
236 GNUNET_TIME_absolute_get_duration (start).rel_value); 225 GNUNET_TIME_absolute_get_duration (start).rel_value);
237 GNUNET_CRYPTO_rsa_key_free (hostkey);
238 return ok; 226 return ok;
239} 227}
240 228
@@ -243,7 +231,6 @@ testSignVerify ()
243static int 231static int
244testSignPerformance () 232testSignPerformance ()
245{ 233{
246 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
247 struct GNUNET_CRYPTO_RsaSignaturePurpose purp; 234 struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
248 struct GNUNET_CRYPTO_RsaSignature sig; 235 struct GNUNET_CRYPTO_RsaSignature sig;
249 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; 236 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
@@ -254,13 +241,12 @@ testSignPerformance ()
254 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)); 241 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
255 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); 242 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
256 FPRINTF (stderr, "%s", "W"); 243 FPRINTF (stderr, "%s", "W");
257 hostkey = GNUNET_CRYPTO_rsa_key_create (); 244 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
258 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
259 start = GNUNET_TIME_absolute_get (); 245 start = GNUNET_TIME_absolute_get ();
260 for (i = 0; i < ITER; i++) 246 for (i = 0; i < ITER; i++)
261 { 247 {
262 FPRINTF (stderr, "%s", "."); 248 FPRINTF (stderr, "%s", ".");
263 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig)) 249 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig))
264 { 250 {
265 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n"); 251 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
266 ok = GNUNET_SYSERR; 252 ok = GNUNET_SYSERR;
@@ -270,7 +256,6 @@ testSignPerformance ()
270 printf ("%d RSA sign operations %llu ms\n", ITER, 256 printf ("%d RSA sign operations %llu ms\n", ITER,
271 (unsigned long long) 257 (unsigned long long)
272 GNUNET_TIME_absolute_get_duration (start).rel_value); 258 GNUNET_TIME_absolute_get_duration (start).rel_value);
273 GNUNET_CRYPTO_rsa_key_free (hostkey);
274 return ok; 259 return ok;
275} 260}
276#endif 261#endif
@@ -279,7 +264,6 @@ testSignPerformance ()
279static int 264static int
280testCreateFromFile () 265testCreateFromFile ()
281{ 266{
282 struct GNUNET_CRYPTO_RsaPrivateKey *key;
283 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p1; 267 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p1;
284 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p2; 268 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p2;
285 269
@@ -297,12 +281,44 @@ testCreateFromFile ()
297 GNUNET_assert (NULL != key); 281 GNUNET_assert (NULL != key);
298 GNUNET_CRYPTO_rsa_key_get_public (key, &p2); 282 GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
299 GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1))); 283 GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1)));
300 GNUNET_CRYPTO_rsa_key_free (key);
301 GNUNET_assert (0 == UNLINK (KEYFILE));
302 return GNUNET_OK; 284 return GNUNET_OK;
303} 285}
304 286
305 287
288static void
289key_cont (void *cls,
290 struct GNUNET_CRYPTO_RsaPrivateKey *pk,
291 const char *emsg)
292{
293 const char *txt = cls;
294 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub1;
295 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub2;
296
297 GNUNET_assert (0 == strcmp ("ok", txt));
298 GNUNET_CRYPTO_rsa_key_get_public (pk, &pub1);
299 GNUNET_CRYPTO_rsa_key_get_public (key, &pub2);
300 GNUNET_assert (0 == memcmp (&pub1, &pub2,
301 sizeof (pub1)));
302 GNUNET_CRYPTO_rsa_key_free (pk);
303}
304
305
306static void
307test_async_creation (void *cls,
308 const struct GNUNET_SCHEDULER_TaskContext *tc)
309{
310 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc;
311
312 gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE,
313 &key_cont,
314 (void*) "bug");
315 GNUNET_CRYPTO_rsa_key_create_stop (gc);
316 gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE,
317 &key_cont,
318 (void*) "ok");
319}
320
321
306int 322int
307main (int argc, char *argv[]) 323main (int argc, char *argv[])
308{ 324{
@@ -312,6 +328,7 @@ main (int argc, char *argv[])
312 GNUNET_CRYPTO_random_disable_entropy_gathering (); 328 GNUNET_CRYPTO_random_disable_entropy_gathering ();
313 if (GNUNET_OK != testCreateFromFile ()) 329 if (GNUNET_OK != testCreateFromFile ())
314 failureCount++; 330 failureCount++;
331 GNUNET_SCHEDULER_run (&test_async_creation, NULL);
315#if PERF 332#if PERF
316 if (GNUNET_OK != testEncryptPerformance ()) 333 if (GNUNET_OK != testEncryptPerformance ())
317 failureCount++; 334 failureCount++;
@@ -324,6 +341,8 @@ main (int argc, char *argv[])
324 failureCount++; 341 failureCount++;
325 if (GNUNET_OK != testSignVerify ()) 342 if (GNUNET_OK != testSignVerify ())
326 failureCount++; 343 failureCount++;
344 GNUNET_CRYPTO_rsa_key_free (key);
345 GNUNET_assert (0 == UNLINK (KEYFILE));
327 346
328 if (failureCount != 0) 347 if (failureCount != 0)
329 { 348 {