aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorLRN <lrn1986@gmail.com>2013-03-03 01:57:14 +0000
committerLRN <lrn1986@gmail.com>2013-03-03 01:57:14 +0000
commit27d46ea3f6ceaef7f089d674f5634eeafa5e133a (patch)
tree76264fa77efa0ef27eae56705b3cb130ba0374a2 /src/util
parent058c49560ff702057bd8799c2d21b1fd70cb7134 (diff)
downloadgnunet-27d46ea3f6ceaef7f089d674f5634eeafa5e133a.tar.gz
gnunet-27d46ea3f6ceaef7f089d674f5634eeafa5e133a.zip
Be able to only-read-not-create RSA keys
Diffstat (limited to 'src/util')
-rw-r--r--src/util/crypto_rsa.c177
1 files changed, 102 insertions, 75 deletions
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index 07eff6696..cde4f247b 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -706,20 +706,17 @@ short_wait ()
706 706
707 707
708/** 708/**
709 * Create a new private key by reading it from a file. If the 709 * Open existing private key file and read it. If the
710 * files does not exist, create a new key and write it to the 710 * file does not exist, or the contents of the file are
711 * file. Caller must free return value. Note that this function 711 * invalid, the function fails
712 * can not guarantee that another process might not be trying 712 * Caller must free returned value.
713 * the same operation on the same file at the same time.
714 * If the contents of the file
715 * are invalid the old file is deleted and a fresh key is
716 * created.
717 * 713 *
718 * @return new private key, NULL on error (for example, 714 * @return a private key, NULL on error (for example,
719 * permission denied) 715 * permission denied) or when file does not exist or contains invalid
716 * data.
720 */ 717 */
721struct GNUNET_CRYPTO_RsaPrivateKey * 718struct GNUNET_CRYPTO_RsaPrivateKey *
722GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) 719GNUNET_CRYPTO_rsa_key_create_from_existing_file (const char *filename)
723{ 720{
724 struct GNUNET_CRYPTO_RsaPrivateKey *ret; 721 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
725 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc; 722 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
@@ -731,70 +728,6 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
731 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; 728 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
732 struct GNUNET_PeerIdentity pid; 729 struct GNUNET_PeerIdentity pid;
733 730
734 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
735 return NULL;
736 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
737 {
738 fd = GNUNET_DISK_file_open (filename,
739 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
740 | GNUNET_DISK_OPEN_FAILIFEXISTS,
741 GNUNET_DISK_PERM_USER_READ |
742 GNUNET_DISK_PERM_USER_WRITE);
743 if (NULL == fd)
744 {
745 if (EEXIST == errno)
746 {
747 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
748 {
749 /* must exist but not be accessible, fail for good! */
750 if (0 != ACCESS (filename, R_OK))
751 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
752 else
753 GNUNET_break (0); /* what is going on!? */
754 return NULL;
755 }
756 continue;
757 }
758 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
759 return NULL;
760 }
761 cnt = 0;
762
763 while (GNUNET_YES !=
764 GNUNET_DISK_file_lock (fd, 0,
765 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded),
766 GNUNET_YES))
767 {
768 short_wait ();
769 if (0 == ++cnt % 10)
770 {
771 ec = errno;
772 LOG (GNUNET_ERROR_TYPE_ERROR,
773 _("Could not acquire lock on file `%s': %s...\n"), filename,
774 STRERROR (ec));
775 }
776 }
777 LOG (GNUNET_ERROR_TYPE_INFO,
778 _("Creating a new private key. This may take a while.\n"));
779 ret = rsa_key_create ();
780 GNUNET_assert (ret != NULL);
781 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
782 GNUNET_assert (enc != NULL);
783 GNUNET_assert (ntohs (enc->len) ==
784 GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
785 GNUNET_free (enc);
786
787 GNUNET_DISK_file_sync (fd);
788 if (GNUNET_YES !=
789 GNUNET_DISK_file_unlock (fd, 0,
790 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
791 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
792 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
793 GNUNET_CRYPTO_rsa_key_get_public (ret, &pub);
794 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
795 return ret;
796 }
797 /* hostkey file exists already, read it! */
798 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, 731 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
799 GNUNET_DISK_PERM_NONE); 732 GNUNET_DISK_PERM_NONE);
800 if (NULL == fd) 733 if (NULL == fd)
@@ -887,6 +820,100 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
887 return ret; 820 return ret;
888} 821}
889 822
823/**
824 * Create a new private key by reading it from a file. If the
825 * files does not exist, create a new key and write it to the
826 * file. Caller must free return value. Note that this function
827 * can not guarantee that another process might not be trying
828 * the same operation on the same file at the same time.
829 * If the contents of the file
830 * are invalid the old file is deleted and a fresh key is
831 * created.
832 *
833 * @return new private key, NULL on error (for example,
834 * permission denied)
835 */
836struct GNUNET_CRYPTO_RsaPrivateKey *
837GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
838{
839 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
840 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
841 uint16_t len;
842 struct GNUNET_DISK_FileHandle *fd;
843 unsigned int cnt;
844 int ec;
845 uint64_t fs;
846 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
847 struct GNUNET_PeerIdentity pid;
848
849 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
850 return NULL;
851
852 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
853 {
854 fd = GNUNET_DISK_file_open (filename,
855 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
856 | GNUNET_DISK_OPEN_FAILIFEXISTS,
857 GNUNET_DISK_PERM_USER_READ |
858 GNUNET_DISK_PERM_USER_WRITE);
859 if (NULL == fd)
860 {
861 if (EEXIST == errno)
862 {
863 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
864 {
865 /* must exist but not be accessible, fail for good! */
866 if (0 != ACCESS (filename, R_OK))
867 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
868 else
869 GNUNET_break (0); /* what is going on!? */
870 return NULL;
871 }
872 continue;
873 }
874 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
875 return NULL;
876 }
877 cnt = 0;
878
879 while (GNUNET_YES !=
880 GNUNET_DISK_file_lock (fd, 0,
881 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded),
882 GNUNET_YES))
883 {
884 short_wait ();
885 if (0 == ++cnt % 10)
886 {
887 ec = errno;
888 LOG (GNUNET_ERROR_TYPE_ERROR,
889 _("Could not acquire lock on file `%s': %s...\n"), filename,
890 STRERROR (ec));
891 }
892 }
893 LOG (GNUNET_ERROR_TYPE_INFO,
894 _("Creating a new private key. This may take a while.\n"));
895 ret = rsa_key_create ();
896 GNUNET_assert (ret != NULL);
897 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
898 GNUNET_assert (enc != NULL);
899 GNUNET_assert (ntohs (enc->len) ==
900 GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
901 GNUNET_free (enc);
902
903 GNUNET_DISK_file_sync (fd);
904 if (GNUNET_YES !=
905 GNUNET_DISK_file_unlock (fd, 0,
906 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
907 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
908 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
909 GNUNET_CRYPTO_rsa_key_get_public (ret, &pub);
910 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
911 return ret;
912 }
913 /* hostkey file exists already, read it! */
914 return GNUNET_CRYPTO_rsa_key_create_from_existing_file (filename);
915}
916
890 917
891/** 918/**
892 * Handle to cancel private key generation and state for the 919 * Handle to cancel private key generation and state for the