diff options
author | LRN <lrn1986@gmail.com> | 2013-03-03 01:57:14 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2013-03-03 01:57:14 +0000 |
commit | 27d46ea3f6ceaef7f089d674f5634eeafa5e133a (patch) | |
tree | 76264fa77efa0ef27eae56705b3cb130ba0374a2 /src/util | |
parent | 058c49560ff702057bd8799c2d21b1fd70cb7134 (diff) | |
download | gnunet-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.c | 177 |
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 | */ |
721 | struct GNUNET_CRYPTO_RsaPrivateKey * | 718 | struct GNUNET_CRYPTO_RsaPrivateKey * |
722 | GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) | 719 | GNUNET_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 | */ | ||
836 | struct GNUNET_CRYPTO_RsaPrivateKey * | ||
837 | GNUNET_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 |