aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_ecc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r--src/util/crypto_ecc.c401
1 files changed, 0 insertions, 401 deletions
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index e6d6bc133..87c787185 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -658,407 +658,6 @@ GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
658 658
659 659
660/** 660/**
661 * Wait for a short time (we're trying to lock a file or want
662 * to give another process a shot at finishing a disk write, etc.).
663 * Sleeps for 100ms (as that should be long enough for virtually all
664 * modern systems to context switch and allow another process to do
665 * some 'real' work).
666 */
667static void
668short_wait ()
669{
670 struct GNUNET_TIME_Relative timeout;
671
672 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
673 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
674}
675
676
677/**
678 * Create a new private key by reading it from a file. If the
679 * files does not exist, create a new key and write it to the
680 * file. Caller must free return value. Note that this function
681 * can not guarantee that another process might not be trying
682 * the same operation on the same file at the same time.
683 * If the contents of the file
684 * are invalid the old file is deleted and a fresh key is
685 * created.
686 *
687 * @param filename name of file to use to store the key
688 * @return new private key, NULL on error (for example,
689 * permission denied)
690 */
691struct GNUNET_CRYPTO_EddsaPrivateKey *
692GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename)
693{
694 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
695 struct GNUNET_DISK_FileHandle *fd;
696 unsigned int cnt;
697 int ec;
698 uint64_t fs;
699
700 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
701 return NULL;
702 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
703 {
704 fd = GNUNET_DISK_file_open (filename,
705 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
706 | GNUNET_DISK_OPEN_FAILIFEXISTS,
707 GNUNET_DISK_PERM_USER_READ |
708 GNUNET_DISK_PERM_USER_WRITE);
709 if (NULL == fd)
710 {
711 if (EEXIST == errno)
712 {
713 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
714 {
715 /* must exist but not be accessible, fail for good! */
716 if (0 != ACCESS (filename, R_OK))
717 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
718 else
719 GNUNET_break (0); /* what is going on!? */
720 return NULL;
721 }
722 continue;
723 }
724 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
725 return NULL;
726 }
727 cnt = 0;
728 while (GNUNET_YES !=
729 GNUNET_DISK_file_lock (fd, 0,
730 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
731 GNUNET_YES))
732 {
733 short_wait ();
734 if (0 == ++cnt % 10)
735 {
736 ec = errno;
737 LOG (GNUNET_ERROR_TYPE_ERROR,
738 _("Could not acquire lock on file `%s': %s...\n"), filename,
739 STRERROR (ec));
740 }
741 }
742 LOG (GNUNET_ERROR_TYPE_INFO,
743 _("Creating a new private key. This may take a while.\n"));
744 priv = GNUNET_CRYPTO_eddsa_key_create ();
745 GNUNET_assert (NULL != priv);
746 GNUNET_assert (sizeof (*priv) ==
747 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
748 GNUNET_DISK_file_sync (fd);
749 if (GNUNET_YES !=
750 GNUNET_DISK_file_unlock (fd, 0,
751 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
752 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
753 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
754 return priv;
755 }
756 /* key file exists already, read it! */
757 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
758 GNUNET_DISK_PERM_NONE);
759 if (NULL == fd)
760 {
761 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
762 return NULL;
763 }
764 cnt = 0;
765 while (1)
766 {
767 if (GNUNET_YES !=
768 GNUNET_DISK_file_lock (fd, 0,
769 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
770 GNUNET_NO))
771 {
772 if (0 == ++cnt % 60)
773 {
774 ec = errno;
775 LOG (GNUNET_ERROR_TYPE_ERROR,
776 _("Could not acquire lock on file `%s': %s...\n"), filename,
777 STRERROR (ec));
778 LOG (GNUNET_ERROR_TYPE_ERROR,
779 _
780 ("This may be ok if someone is currently generating a private key.\n"));
781 }
782 short_wait ();
783 continue;
784 }
785 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
786 {
787 /* eh, what!? File we opened is now gone!? */
788 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
789 if (GNUNET_YES !=
790 GNUNET_DISK_file_unlock (fd, 0,
791 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
792 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
793 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
794
795 return NULL;
796 }
797 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
798 fs = 0;
799 if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
800 {
801 /* maybe we got the read lock before the key generating
802 * process had a chance to get the write lock; give it up! */
803 if (GNUNET_YES !=
804 GNUNET_DISK_file_unlock (fd, 0,
805 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
806 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
807 if (0 == ++cnt % 10)
808 {
809 LOG (GNUNET_ERROR_TYPE_ERROR,
810 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
811 filename, (unsigned int) fs,
812 (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
813 LOG (GNUNET_ERROR_TYPE_ERROR,
814 _("This may be ok if someone is currently generating a key.\n"));
815 }
816 short_wait (); /* wait a bit longer! */
817 continue;
818 }
819 break;
820 }
821 fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
822 priv = GNUNET_malloc (fs);
823 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
824 if (GNUNET_YES !=
825 GNUNET_DISK_file_unlock (fd, 0,
826 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
827 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
828 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
829 return priv;
830}
831
832
833/**
834 * Create a new private key by reading it from a file. If the
835 * files does not exist, create a new key and write it to the
836 * file. Caller must free return value. Note that this function
837 * can not guarantee that another process might not be trying
838 * the same operation on the same file at the same time.
839 * If the contents of the file
840 * are invalid the old file is deleted and a fresh key is
841 * created.
842 *
843 * @param filename name of file to use to store the key
844 * @return new private key, NULL on error (for example,
845 * permission denied)
846 */
847struct GNUNET_CRYPTO_EcdsaPrivateKey *
848GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
849{
850 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
851 struct GNUNET_DISK_FileHandle *fd;
852 unsigned int cnt;
853 int ec;
854 uint64_t fs;
855
856 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
857 return NULL;
858 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
859 {
860 fd = GNUNET_DISK_file_open (filename,
861 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
862 | GNUNET_DISK_OPEN_FAILIFEXISTS,
863 GNUNET_DISK_PERM_USER_READ |
864 GNUNET_DISK_PERM_USER_WRITE);
865 if (NULL == fd)
866 {
867 if (EEXIST == errno)
868 {
869 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
870 {
871 /* must exist but not be accessible, fail for good! */
872 if (0 != ACCESS (filename, R_OK))
873 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
874 else
875 GNUNET_break (0); /* what is going on!? */
876 return NULL;
877 }
878 continue;
879 }
880 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
881 return NULL;
882 }
883 cnt = 0;
884 while (GNUNET_YES !=
885 GNUNET_DISK_file_lock (fd, 0,
886 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
887 GNUNET_YES))
888 {
889 short_wait ();
890 if (0 == ++cnt % 10)
891 {
892 ec = errno;
893 LOG (GNUNET_ERROR_TYPE_ERROR,
894 _("Could not acquire lock on file `%s': %s...\n"), filename,
895 STRERROR (ec));
896 }
897 }
898 LOG (GNUNET_ERROR_TYPE_INFO,
899 _("Creating a new private key. This may take a while.\n"));
900 priv = GNUNET_CRYPTO_ecdsa_key_create ();
901 GNUNET_assert (NULL != priv);
902 GNUNET_assert (sizeof (*priv) ==
903 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
904 GNUNET_DISK_file_sync (fd);
905 if (GNUNET_YES !=
906 GNUNET_DISK_file_unlock (fd, 0,
907 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
908 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
909 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
910 return priv;
911 }
912 /* key file exists already, read it! */
913 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
914 GNUNET_DISK_PERM_NONE);
915 if (NULL == fd)
916 {
917 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
918 return NULL;
919 }
920 cnt = 0;
921 while (1)
922 {
923 if (GNUNET_YES !=
924 GNUNET_DISK_file_lock (fd, 0,
925 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
926 GNUNET_NO))
927 {
928 if (0 == ++cnt % 60)
929 {
930 ec = errno;
931 LOG (GNUNET_ERROR_TYPE_ERROR,
932 _("Could not acquire lock on file `%s': %s...\n"), filename,
933 STRERROR (ec));
934 LOG (GNUNET_ERROR_TYPE_ERROR,
935 _
936 ("This may be ok if someone is currently generating a private key.\n"));
937 }
938 short_wait ();
939 continue;
940 }
941 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
942 {
943 /* eh, what!? File we opened is now gone!? */
944 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
945 if (GNUNET_YES !=
946 GNUNET_DISK_file_unlock (fd, 0,
947 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
948 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
949 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
950
951 return NULL;
952 }
953 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
954 fs = 0;
955 if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
956 {
957 /* maybe we got the read lock before the key generating
958 * process had a chance to get the write lock; give it up! */
959 if (GNUNET_YES !=
960 GNUNET_DISK_file_unlock (fd, 0,
961 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
962 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
963 if (0 == ++cnt % 10)
964 {
965 LOG (GNUNET_ERROR_TYPE_ERROR,
966 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
967 filename, (unsigned int) fs,
968 (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
969 LOG (GNUNET_ERROR_TYPE_ERROR,
970 _("This may be ok if someone is currently generating a key.\n"));
971 }
972 short_wait (); /* wait a bit longer! */
973 continue;
974 }
975 break;
976 }
977 fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
978 priv = GNUNET_malloc (fs);
979 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
980 if (GNUNET_YES !=
981 GNUNET_DISK_file_unlock (fd, 0,
982 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
983 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
984 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
985 return priv;
986}
987
988
989/**
990 * Create a new private key by reading our peer's key from
991 * the file specified in the configuration.
992 *
993 * @param cfg the configuration to use
994 * @return new private key, NULL on error (for example,
995 * permission denied)
996 */
997struct GNUNET_CRYPTO_EddsaPrivateKey *
998GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
999{
1000 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1001 char *fn;
1002
1003 if (GNUNET_OK !=
1004 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
1005 return NULL;
1006 priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn);
1007 GNUNET_free (fn);
1008 return priv;
1009}
1010
1011
1012/**
1013 * Setup a key file for a peer given the name of the
1014 * configuration file (!). This function is used so that
1015 * at a later point code can be certain that reading a
1016 * key is fast (for example in time-dependent testcases).
1017 *
1018 * @param cfg_name name of the configuration file to use
1019 */
1020void
1021GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
1022{
1023 struct GNUNET_CONFIGURATION_Handle *cfg;
1024 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1025
1026 cfg = GNUNET_CONFIGURATION_create ();
1027 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1028 priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1029 if (NULL != priv)
1030 GNUNET_free (priv);
1031 GNUNET_CONFIGURATION_destroy (cfg);
1032}
1033
1034
1035/**
1036 * Retrieve the identity of the host's peer.
1037 *
1038 * @param cfg configuration to use
1039 * @param dst pointer to where to write the peer identity
1040 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
1041 * could not be retrieved
1042 */
1043int
1044GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
1045 struct GNUNET_PeerIdentity *dst)
1046{
1047 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1048
1049 if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
1050 {
1051 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1052 _("Could not load peer's private key\n"));
1053 return GNUNET_SYSERR;
1054 }
1055 GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key);
1056 GNUNET_free (priv);
1057 return GNUNET_OK;
1058}
1059
1060
1061/**
1062 * Compare two Peer Identities. 661 * Compare two Peer Identities.
1063 * 662 *
1064 * @param first first peer identity 663 * @param first first peer identity