diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-03-07 12:30:28 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-03-07 12:30:28 +0000 |
commit | 1a17d075effa5fbc3b3521ab0d15b2d035599969 (patch) | |
tree | fa15da4e9b0f6cf4316330d7e03deb1e661236e2 /src/util | |
parent | 2fa116568befd7d9ca3d81ad1d73a785b1fb9532 (diff) | |
download | gnunet-1a17d075effa5fbc3b3521ab0d15b2d035599969.tar.gz gnunet-1a17d075effa5fbc3b3521ab0d15b2d035599969.zip |
-towards pseudonym crypto
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/pseudonym.c | 439 |
1 files changed, 412 insertions, 27 deletions
diff --git a/src/util/pseudonym.c b/src/util/pseudonym.c index b17abd6e7..47fe36ddc 100644 --- a/src/util/pseudonym.c +++ b/src/util/pseudonym.c | |||
@@ -36,9 +36,18 @@ | |||
36 | 36 | ||
37 | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) | 37 | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) |
38 | 38 | ||
39 | #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) | ||
40 | |||
39 | #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) | 41 | #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) |
40 | 42 | ||
41 | /** | 43 | /** |
44 | * Log an error message at log-level 'level' that indicates | ||
45 | * a failure of the command 'cmd' with the message given | ||
46 | * by gcry_strerror(rc). | ||
47 | */ | ||
48 | #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0); | ||
49 | |||
50 | /** | ||
42 | * Name of the directory which stores meta data for pseudonym | 51 | * Name of the directory which stores meta data for pseudonym |
43 | */ | 52 | */ |
44 | #define PS_METADATA_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "metadata" DIR_SEPARATOR_STR | 53 | #define PS_METADATA_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "metadata" DIR_SEPARATOR_STR |
@@ -762,13 +771,94 @@ GNUNET_PSEUDONYM_add (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
762 | struct GNUNET_PseudonymHandle | 771 | struct GNUNET_PseudonymHandle |
763 | { | 772 | { |
764 | /** | 773 | /** |
765 | * FIXME. | 774 | * 256-bit 'd' secret value (mod 'n', where n is 256-bit for NIST P-256). |
766 | */ | 775 | */ |
767 | char data[42]; | 776 | unsigned char d[256 / 8]; |
777 | |||
778 | /** | ||
779 | * Public key corresponding to the private key. | ||
780 | */ | ||
781 | struct GNUNET_PseudonymIdentifier public_key; | ||
768 | }; | 782 | }; |
769 | 783 | ||
770 | 784 | ||
771 | /** | 785 | /** |
786 | * If target != size, move target bytes to the end of the size-sized | ||
787 | * buffer and zero out the first target-size bytes. | ||
788 | * | ||
789 | * @param buf original buffer | ||
790 | * @param size number of bytes in the buffer | ||
791 | * @param target target size of the buffer | ||
792 | */ | ||
793 | static void | ||
794 | adjust (unsigned char *buf, size_t size, size_t target) | ||
795 | { | ||
796 | if (size < target) | ||
797 | { | ||
798 | memmove (&buf[target - size], buf, size); | ||
799 | memset (buf, 0, target - size); | ||
800 | } | ||
801 | } | ||
802 | |||
803 | |||
804 | /** | ||
805 | * Extract values from an S-expression. | ||
806 | * | ||
807 | * @param array where to store the result(s) | ||
808 | * @param sexp S-expression to parse | ||
809 | * @param topname top-level name in the S-expression that is of interest | ||
810 | * @param elems names of the elements to extract | ||
811 | * @return 0 on success | ||
812 | */ | ||
813 | static int | ||
814 | key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, | ||
815 | const char *elems) | ||
816 | { | ||
817 | gcry_sexp_t list; | ||
818 | gcry_sexp_t l2; | ||
819 | const char *s; | ||
820 | unsigned int i; | ||
821 | unsigned int idx; | ||
822 | |||
823 | if (! (list = gcry_sexp_find_token (sexp, topname, 0))) | ||
824 | return 1; | ||
825 | l2 = gcry_sexp_cadr (list); | ||
826 | gcry_sexp_release (list); | ||
827 | list = l2; | ||
828 | if (! list) | ||
829 | return 2; | ||
830 | idx = 0; | ||
831 | for (s = elems; *s; s++, idx++) | ||
832 | { | ||
833 | if (! (l2 = gcry_sexp_find_token (list, s, 1))) | ||
834 | { | ||
835 | for (i = 0; i < idx; i++) | ||
836 | { | ||
837 | gcry_free (array[i]); | ||
838 | array[i] = NULL; | ||
839 | } | ||
840 | gcry_sexp_release (list); | ||
841 | return 3; /* required parameter not found */ | ||
842 | } | ||
843 | array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); | ||
844 | gcry_sexp_release (l2); | ||
845 | if (! array[idx]) | ||
846 | { | ||
847 | for (i = 0; i < idx; i++) | ||
848 | { | ||
849 | gcry_free (array[i]); | ||
850 | array[i] = NULL; | ||
851 | } | ||
852 | gcry_sexp_release (list); | ||
853 | return 4; /* required parameter is invalid */ | ||
854 | } | ||
855 | } | ||
856 | gcry_sexp_release (list); | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | |||
861 | /** | ||
772 | * Create a pseudonym. | 862 | * Create a pseudonym. |
773 | * | 863 | * |
774 | * @param filename name of the file to use for storage, NULL for in-memory only | 864 | * @param filename name of the file to use for storage, NULL for in-memory only |
@@ -779,6 +869,11 @@ GNUNET_PSEUDONYM_create (const char *filename) | |||
779 | { | 869 | { |
780 | struct GNUNET_PseudonymHandle *ph; | 870 | struct GNUNET_PseudonymHandle *ph; |
781 | ssize_t ret; | 871 | ssize_t ret; |
872 | gcry_sexp_t r_key; | ||
873 | gcry_sexp_t params; | ||
874 | gcry_error_t rc; | ||
875 | gcry_mpi_t skey[2]; | ||
876 | size_t size; | ||
782 | 877 | ||
783 | ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle)); | 878 | ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle)); |
784 | if ( (NULL != filename) && | 879 | if ( (NULL != filename) && |
@@ -786,12 +881,40 @@ GNUNET_PSEUDONYM_create (const char *filename) | |||
786 | { | 881 | { |
787 | ret = GNUNET_DISK_fn_read (filename, ph, | 882 | ret = GNUNET_DISK_fn_read (filename, ph, |
788 | sizeof (struct GNUNET_PseudonymHandle)); | 883 | sizeof (struct GNUNET_PseudonymHandle)); |
884 | /* Note: we don't do any validation here, maybe we should? */ | ||
789 | if (sizeof (struct GNUNET_PseudonymHandle) == ret) | 885 | if (sizeof (struct GNUNET_PseudonymHandle) == ret) |
790 | return ph; | 886 | return ph; |
887 | } | ||
888 | if (0 != (rc = gcry_sexp_build (¶ms, NULL, | ||
889 | "(genkey(ecdsa(curve \"NIST P-256\")))"))) | ||
890 | { | ||
891 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
892 | return NULL; | ||
791 | } | 893 | } |
792 | GNUNET_break (0); // not implemented... | 894 | if (0 != (rc = gcry_pk_genkey (&r_key, params))) |
793 | gcry_randomize (ph, sizeof (struct GNUNET_PseudonymHandle), | 895 | { |
794 | GCRY_STRONG_RANDOM); | 896 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); |
897 | return NULL; | ||
898 | } | ||
899 | /* NOTE: treating a point as a normal MPI value; hopefully that works... */ | ||
900 | rc = key_from_sexp (skey, r_key, "private-key", "dq"); | ||
901 | if (0 != rc) | ||
902 | rc = key_from_sexp (skey, r_key, "private-key", "dq"); | ||
903 | if (0 != rc) | ||
904 | rc = key_from_sexp (skey, r_key, "ecc", "dq"); | ||
905 | gcry_sexp_release (r_key); | ||
906 | size = sizeof (ph->d); | ||
907 | GNUNET_assert (0 == | ||
908 | gcry_mpi_print (GCRYMPI_FMT_USG, ph->d, size, &size, | ||
909 | skey[0])); | ||
910 | adjust (ph->d, size, sizeof (ph->d)); | ||
911 | size = sizeof (ph->public_key.q); | ||
912 | GNUNET_assert (0 == | ||
913 | gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q, size, &size, | ||
914 | skey[1])); | ||
915 | adjust (ph->public_key.q, size, sizeof (ph->public_key.q)); | ||
916 | gcry_mpi_release (skey[0]); | ||
917 | gcry_mpi_release (skey[1]); | ||
795 | if (NULL != filename) | 918 | if (NULL != filename) |
796 | { | 919 | { |
797 | ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_PseudonymHandle), | 920 | ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_PseudonymHandle), |
@@ -821,10 +944,13 @@ GNUNET_PSEUDONYM_create_from_existing_file (const char *filename) | |||
821 | ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle)); | 944 | ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle)); |
822 | ret = GNUNET_DISK_fn_read (filename, ph, | 945 | ret = GNUNET_DISK_fn_read (filename, ph, |
823 | sizeof (struct GNUNET_PseudonymHandle)); | 946 | sizeof (struct GNUNET_PseudonymHandle)); |
824 | if (sizeof (struct GNUNET_PseudonymHandle) == ret) | 947 | if (sizeof (struct GNUNET_PseudonymHandle) != ret) |
825 | return ph; | 948 | { |
826 | GNUNET_free (ph); | 949 | GNUNET_free (ph); |
827 | return NULL; | 950 | return NULL; |
951 | } | ||
952 | /* Note: we don't do any validation here; maybe we should? */ | ||
953 | return ph; | ||
828 | } | 954 | } |
829 | 955 | ||
830 | 956 | ||
@@ -842,6 +968,13 @@ GNUNET_PSEUDONYM_get_anonymous_pseudonym_handle () | |||
842 | struct GNUNET_PseudonymHandle *ph; | 968 | struct GNUNET_PseudonymHandle *ph; |
843 | 969 | ||
844 | ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle)); | 970 | ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle)); |
971 | /* FIXME: if we use 'd=0' for the anonymous handle (as per#2564), | ||
972 | then I believe the public key should be also zero, as Q=0P=0. | ||
973 | However, libgcrypt's point representation is completely internal, | ||
974 | and treats a z-coordinate of zero as infinity, so we likely need | ||
975 | to set it to (0,0,1) internally --- or actually calculate Q=qP | ||
976 | explicitly. Either way, we don't have an API to do so yet :-(. | ||
977 | */ | ||
845 | GNUNET_break (0); | 978 | GNUNET_break (0); |
846 | return ph; | 979 | return ph; |
847 | } | 980 | } |
@@ -861,6 +994,39 @@ GNUNET_PSEUDONYM_destroy (struct GNUNET_PseudonymHandle *ph) | |||
861 | 994 | ||
862 | 995 | ||
863 | /** | 996 | /** |
997 | * Convert the data specified in the given purpose argument to an | ||
998 | * S-expression suitable for signature operations. | ||
999 | * | ||
1000 | * @param purpose data to convert | ||
1001 | * @return converted s-expression | ||
1002 | */ | ||
1003 | static gcry_sexp_t | ||
1004 | data_to_pkcs1 (const struct GNUNET_PseudonymSignaturePurpose *purpose) | ||
1005 | { | ||
1006 | struct GNUNET_CRYPTO_ShortHashCode hc; | ||
1007 | size_t bufSize; | ||
1008 | gcry_sexp_t data; | ||
1009 | |||
1010 | GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc); | ||
1011 | #define FORMATSTRING "(4:data(5:flags3:raw)(5:value32:01234567890123456789012345678901))" | ||
1012 | bufSize = strlen (FORMATSTRING) + 1; | ||
1013 | { | ||
1014 | char buff[bufSize]; | ||
1015 | |||
1016 | memcpy (buff, FORMATSTRING, bufSize); | ||
1017 | memcpy (&buff | ||
1018 | [bufSize - | ||
1019 | strlen | ||
1020 | ("01234567890123456789012345678901))") | ||
1021 | - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); | ||
1022 | GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); | ||
1023 | } | ||
1024 | #undef FORMATSTRING | ||
1025 | return data; | ||
1026 | } | ||
1027 | |||
1028 | |||
1029 | /** | ||
864 | * Cryptographically sign some data with the pseudonym. | 1030 | * Cryptographically sign some data with the pseudonym. |
865 | * | 1031 | * |
866 | * @param ph private key used for signing (corresponds to 'x' in #2564) | 1032 | * @param ph private key used for signing (corresponds to 'x' in #2564) |
@@ -871,16 +1037,144 @@ GNUNET_PSEUDONYM_destroy (struct GNUNET_PseudonymHandle *ph) | |||
871 | * @param signing_key modifier to apply to the private key for signing; | 1037 | * @param signing_key modifier to apply to the private key for signing; |
872 | * corresponds to 'h' in section 2.3 of #2564. | 1038 | * corresponds to 'h' in section 2.3 of #2564. |
873 | * @param signature where to store the signature | 1039 | * @param signature where to store the signature |
1040 | * @return GNUNET_SYSERR on failure | ||
874 | */ | 1041 | */ |
875 | void | 1042 | int |
876 | GNUNET_PSEUDONYM_sign (struct GNUNET_PseudonymHandle *ph, | 1043 | GNUNET_PSEUDONYM_sign (struct GNUNET_PseudonymHandle *ph, |
877 | const struct GNUNET_PseudonymSignaturePurpose *purpose, | 1044 | const struct GNUNET_PseudonymSignaturePurpose *purpose, |
878 | const struct GNUNET_HashCode *seed, | 1045 | const struct GNUNET_HashCode *seed, |
879 | const struct GNUNET_HashCode *signing_key, | 1046 | const struct GNUNET_HashCode *signing_key, |
880 | struct GNUNET_PseudonymSignature *signature) | 1047 | struct GNUNET_PseudonymSignature *signature) |
881 | { | 1048 | { |
882 | memset (signature, 0, sizeof (struct GNUNET_PseudonymSignature)); | 1049 | size_t size; |
883 | GNUNET_break (0); | 1050 | size_t erroff; |
1051 | gcry_mpi_t x; | ||
1052 | gcry_mpi_t k; | ||
1053 | gcry_mpi_t h; | ||
1054 | gcry_mpi_t d; | ||
1055 | gcry_mpi_t n; /* n from P-256 */ | ||
1056 | gcry_sexp_t spriv; | ||
1057 | gcry_sexp_t data; | ||
1058 | gcry_sexp_t result; | ||
1059 | gcry_mpi_t rs[2]; | ||
1060 | int rc; | ||
1061 | |||
1062 | /* get private key 'x' from pseudonym */ | ||
1063 | size = sizeof (ph->d); | ||
1064 | if (0 != (rc = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, | ||
1065 | &ph->d, | ||
1066 | size, &size))) | ||
1067 | { | ||
1068 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1069 | return GNUNET_SYSERR; | ||
1070 | } | ||
1071 | /* get 'h' value from signing key */ | ||
1072 | size = sizeof (struct GNUNET_HashCode); | ||
1073 | if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG, | ||
1074 | signing_key, | ||
1075 | size, &size))) | ||
1076 | { | ||
1077 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1078 | gcry_mpi_release (x); | ||
1079 | return GNUNET_SYSERR; | ||
1080 | } | ||
1081 | |||
1082 | /* initialize 'n' from P-256; hex copied from libgcrypt code */ | ||
1083 | if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, | ||
1084 | "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL))) | ||
1085 | { | ||
1086 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1087 | gcry_mpi_release (x); | ||
1088 | gcry_mpi_release (h); | ||
1089 | return GNUNET_SYSERR; | ||
1090 | } | ||
1091 | |||
1092 | /* calculate d = x + h mod n */ | ||
1093 | d = gcry_mpi_new (256); | ||
1094 | gcry_mpi_addm (d, x, h, n); | ||
1095 | gcry_mpi_release (x); | ||
1096 | gcry_mpi_release (h); | ||
1097 | gcry_mpi_release (n); | ||
1098 | |||
1099 | /* now build sexpression with the signing key; | ||
1100 | NOTE: libgcrypt docs say that we should specify 'Q', but | ||
1101 | with the current API we cannot calculate Q=dP, so hopefully | ||
1102 | libgcrypt will derive it from 'd' for us... */ | ||
1103 | if (0 != (rc = gcry_sexp_build (&spriv, &erroff, | ||
1104 | "(private-key(ecc(curve \"NIST P-256\")(d %m)))", | ||
1105 | d))) | ||
1106 | { | ||
1107 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
1108 | gcry_mpi_release (d); | ||
1109 | return GNUNET_SYSERR; | ||
1110 | } | ||
1111 | gcry_mpi_release (d); | ||
1112 | /* prepare data for signing */ | ||
1113 | data = data_to_pkcs1 (purpose); | ||
1114 | |||
1115 | /* get 'k' value from seed, if available */ | ||
1116 | if (NULL != seed) | ||
1117 | { | ||
1118 | size = sizeof (struct GNUNET_HashCode); | ||
1119 | if (0 != (rc = gcry_mpi_scan (&k, GCRYMPI_FMT_USG, | ||
1120 | seed, | ||
1121 | size, &size))) | ||
1122 | { | ||
1123 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1124 | gcry_mpi_release (x); | ||
1125 | return GNUNET_SYSERR; | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | /* actually create signature */ | ||
1130 | /* FIXME: need API to pass 'k' if 'seed' was non-NULL! */ | ||
1131 | if (0 != (rc = gcry_pk_sign (&result, data, spriv))) | ||
1132 | { | ||
1133 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1134 | _("ECC signing failed at %s:%d: %s\n"), __FILE__, | ||
1135 | __LINE__, gcry_strerror (rc)); | ||
1136 | gcry_sexp_release (data); | ||
1137 | gcry_sexp_release (spriv); | ||
1138 | if (NULL != seed) | ||
1139 | gcry_mpi_release (k); | ||
1140 | memset (signature, 0, sizeof (struct GNUNET_PseudonymSignature)); | ||
1141 | return GNUNET_SYSERR; | ||
1142 | } | ||
1143 | if (NULL != seed) | ||
1144 | gcry_mpi_release (k); | ||
1145 | gcry_sexp_release (data); | ||
1146 | gcry_sexp_release (spriv); | ||
1147 | |||
1148 | /* extract 'r' and 's' values from sexpression 'result' and store in 'signature'; | ||
1149 | FIXME: libgcrypt does not document format of s-expression returned for ECC | ||
1150 | signatures; so "ecc" here is just a guess. */ | ||
1151 | if (0 != (rc = key_from_sexp (rs, result, "ecc", "rs"))) | ||
1152 | { | ||
1153 | GNUNET_break (0); | ||
1154 | gcry_sexp_release (result); | ||
1155 | return GNUNET_SYSERR; | ||
1156 | } | ||
1157 | gcry_sexp_release (result); | ||
1158 | size = sizeof (signature->sig_r); | ||
1159 | if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) signature->sig_r, size, | ||
1160 | &size, rs[0]))) | ||
1161 | { | ||
1162 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1163 | gcry_mpi_release (rs[0]); | ||
1164 | gcry_mpi_release (rs[1]); | ||
1165 | return GNUNET_SYSERR; | ||
1166 | } | ||
1167 | gcry_mpi_release (rs[0]); | ||
1168 | size = sizeof (signature->sig_s); | ||
1169 | if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) signature->sig_s, size, | ||
1170 | &size, rs[1]))) | ||
1171 | { | ||
1172 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1173 | gcry_mpi_release (rs[1]); | ||
1174 | return GNUNET_SYSERR; | ||
1175 | } | ||
1176 | gcry_mpi_release (rs[1]); | ||
1177 | return GNUNET_OK; | ||
884 | } | 1178 | } |
885 | 1179 | ||
886 | 1180 | ||
@@ -888,25 +1182,43 @@ GNUNET_PSEUDONYM_sign (struct GNUNET_PseudonymHandle *ph, | |||
888 | * Given a pseudonym and a signing key, derive the corresponding public | 1182 | * Given a pseudonym and a signing key, derive the corresponding public |
889 | * key that would be used to verify the resulting signature. | 1183 | * key that would be used to verify the resulting signature. |
890 | * | 1184 | * |
891 | * @param pseudonym the public key (g^x) | 1185 | * @param pseudonym the public key (g^x in DSA, dQ in ECDSA) |
892 | * @param signing_key input to derive 'h' (see section 2.4 of #2564) | 1186 | * @param signing_key input to derive 'h' (see section 2.4 of #2564) |
893 | * @param verification_key resulting public key to verify the signature | 1187 | * @param verification_key resulting public key to verify the signature |
894 | * created from the 'ph' of 'pseudonym' and the 'signing_key'; | 1188 | * created from the 'ph' of 'pseudonym' and the 'signing_key'; |
895 | * the value stored here can then be given to GNUNET_PSEUDONYM_verify. | 1189 | * the value stored here can then be given to GNUNET_PSEUDONYM_verify. |
1190 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
896 | */ | 1191 | */ |
897 | void | 1192 | int |
898 | GNUNET_PSEUDONYM_derive_verification_key (struct GNUNET_PseudonymIdentifier *pseudonym, | 1193 | GNUNET_PSEUDONYM_derive_verification_key (struct GNUNET_PseudonymIdentifier *pseudonym, |
899 | const struct GNUNET_HashCode *signing_key, | 1194 | const struct GNUNET_HashCode *signing_key, |
900 | struct GNUNET_PseudonymIdentifier *verification_key) | 1195 | struct GNUNET_PseudonymIdentifier *verification_key) |
901 | { | 1196 | { |
902 | struct GNUNET_HashCode hc; | 1197 | struct GNUNET_HashCode hc; |
903 | struct GNUNET_HashCode x; | 1198 | struct GNUNET_HashCode x; |
904 | 1199 | gcry_mpi_t h; | |
1200 | size_t size; | ||
1201 | int rc; | ||
1202 | |||
1203 | /* get 'h' value from signing key */ | ||
1204 | size = sizeof (struct GNUNET_HashCode); | ||
1205 | if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG, | ||
1206 | signing_key, | ||
1207 | size, &size))) | ||
1208 | { | ||
1209 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1210 | return GNUNET_SYSERR; | ||
1211 | } | ||
1212 | /* FIXME: calculate hQ --- need point multiplication API! */ | ||
1213 | gcry_mpi_release (h); | ||
1214 | /* FIXME: calculate V = dQ + hQ --- need point addition API! */ | ||
1215 | |||
905 | GNUNET_break (0); | 1216 | GNUNET_break (0); |
906 | GNUNET_CRYPTO_hash (pseudonym, sizeof (*pseudonym), &hc); | 1217 | GNUNET_CRYPTO_hash (pseudonym, sizeof (*pseudonym), &hc); |
907 | GNUNET_CRYPTO_hash_xor (&hc, signing_key, &x); | 1218 | GNUNET_CRYPTO_hash_xor (&hc, signing_key, &x); |
908 | memset (verification_key, 0, sizeof (struct GNUNET_PseudonymIdentifier)); | 1219 | memset (verification_key, 0, sizeof (struct GNUNET_PseudonymIdentifier)); |
909 | memcpy (verification_key, &x, GNUNET_MIN (sizeof (x), sizeof (*verification_key))); | 1220 | memcpy (verification_key, &x, GNUNET_MIN (sizeof (x), sizeof (*verification_key))); |
1221 | return GNUNET_OK; | ||
910 | } | 1222 | } |
911 | 1223 | ||
912 | 1224 | ||
@@ -925,7 +1237,84 @@ GNUNET_PSEUDONYM_verify (const struct GNUNET_PseudonymSignaturePurpose *purpose, | |||
925 | const struct GNUNET_PseudonymSignature *signature, | 1237 | const struct GNUNET_PseudonymSignature *signature, |
926 | const struct GNUNET_PseudonymIdentifier *verification_key) | 1238 | const struct GNUNET_PseudonymIdentifier *verification_key) |
927 | { | 1239 | { |
1240 | #if FUTURE | ||
1241 | gcry_sexp_t data; | ||
1242 | gcry_sexp_t sig_sexpr; | ||
1243 | gcry_sexp_t pk_sexpr; | ||
1244 | size_t size; | ||
1245 | gcry_mpi_t r; | ||
1246 | gcry_mpi_t s; | ||
1247 | gcry_mpi_t q; | ||
1248 | size_t erroff; | ||
1249 | int rc; | ||
1250 | |||
1251 | /* build s-expression for signature */ | ||
1252 | size = sizeof (signature->sig_r); | ||
1253 | if (0 != (rc = gcry_mpi_scan (&r, GCRYMPI_FMT_USG, | ||
1254 | signature->sig_r, size, &size))) | ||
1255 | { | ||
1256 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1257 | return GNUNET_SYSERR; | ||
1258 | } | ||
1259 | size = sizeof (signature->sig_s); | ||
1260 | if (0 != (rc = gcry_mpi_scan (&s, GCRYMPI_FMT_USG, | ||
1261 | signature->sig_s, size, &size))) | ||
1262 | { | ||
1263 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1264 | gcry_mpi_release (r); | ||
1265 | return GNUNET_SYSERR; | ||
1266 | } | ||
1267 | if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecc(r %m)(s %m)))", | ||
1268 | r, s))) | ||
1269 | { | ||
1270 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
1271 | gcry_mpi_release (r); | ||
1272 | gcry_mpi_release (s); | ||
1273 | return GNUNET_SYSERR; | ||
1274 | } | ||
1275 | gcry_mpi_release (r); | ||
1276 | gcry_mpi_release (s); | ||
1277 | |||
1278 | /* build s-expression for data that was signed */ | ||
1279 | data = data_to_pkcs1 (purpose); | ||
1280 | |||
1281 | /* build s-expression for public key */ | ||
1282 | /* NOTE: treating a point as a normal MPI value; hopefully that works... */ | ||
1283 | size = sizeof (verification_key->q); | ||
1284 | if (0 != (rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG, | ||
1285 | verification_key->q, size, &size))) | ||
1286 | { | ||
1287 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1288 | gcry_sexp_release (data); | ||
1289 | gcry_sexp_release (sig_sexpr); | ||
1290 | return GNUNET_SYSERR; | ||
1291 | } | ||
1292 | if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(public-key(ecc(curve \"NIST P-256\")(q %m)))", | ||
1293 | q))) | ||
1294 | { | ||
1295 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
1296 | gcry_mpi_release (q); | ||
1297 | gcry_sexp_release (data); | ||
1298 | gcry_sexp_release (sig_sexpr); | ||
1299 | return GNUNET_SYSERR; | ||
1300 | } | ||
1301 | gcry_mpi_release (q); | ||
1302 | |||
1303 | /* finally, verify the signature */ | ||
1304 | rc = gcry_pk_verify (sig_sexpr, data, pk_sexpr); | ||
1305 | gcry_sexp_release (sig_sexpr); | ||
1306 | gcry_sexp_release (data); | ||
1307 | gcry_sexp_release (pk_sexpr); | ||
1308 | if (rc) | ||
1309 | { | ||
1310 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1311 | _("RSA signature verification failed at %s:%d: %s\n"), __FILE__, | ||
1312 | __LINE__, gcry_strerror (rc)); | ||
1313 | return GNUNET_SYSERR; | ||
1314 | } | ||
1315 | #else | ||
928 | GNUNET_break (0); | 1316 | GNUNET_break (0); |
1317 | #endif | ||
929 | return GNUNET_OK; | 1318 | return GNUNET_OK; |
930 | } | 1319 | } |
931 | 1320 | ||
@@ -940,10 +1329,8 @@ void | |||
940 | GNUNET_PSEUDONYM_get_identifier (struct GNUNET_PseudonymHandle *ph, | 1329 | GNUNET_PSEUDONYM_get_identifier (struct GNUNET_PseudonymHandle *ph, |
941 | struct GNUNET_PseudonymIdentifier *pseudonym) | 1330 | struct GNUNET_PseudonymIdentifier *pseudonym) |
942 | { | 1331 | { |
943 | GNUNET_break (0); | 1332 | memcpy (pseudonym, &ph->public_key, |
944 | memcpy (pseudonym, ph, | 1333 | sizeof (struct GNUNET_PseudonymIdentifier)); |
945 | GNUNET_MIN (sizeof (struct GNUNET_PseudonymIdentifier), | ||
946 | sizeof (*ph))); | ||
947 | } | 1334 | } |
948 | 1335 | ||
949 | 1336 | ||
@@ -956,19 +1343,17 @@ GNUNET_PSEUDONYM_get_identifier (struct GNUNET_PseudonymHandle *ph, | |||
956 | */ | 1343 | */ |
957 | int | 1344 | int |
958 | GNUNET_PSEUDONYM_remove (const struct GNUNET_CONFIGURATION_Handle *cfg, | 1345 | GNUNET_PSEUDONYM_remove (const struct GNUNET_CONFIGURATION_Handle *cfg, |
959 | const struct GNUNET_PseudonymIdentifier *id) | 1346 | const struct GNUNET_PseudonymIdentifier *id) |
960 | { | 1347 | { |
961 | char *fn; | 1348 | char *fn; |
962 | int result; | 1349 | int result; |
963 | 1350 | ||
964 | result = GNUNET_SYSERR; | ||
965 | fn = get_data_filename (cfg, PS_METADATA_DIR, id); | 1351 | fn = get_data_filename (cfg, PS_METADATA_DIR, id); |
966 | if (NULL != fn) | 1352 | if (NULL == fn) |
967 | { | 1353 | return GNUNET_SYSERR; |
968 | result = UNLINK (fn); | 1354 | result = UNLINK (fn); |
969 | GNUNET_free (fn); | 1355 | GNUNET_free (fn); |
970 | } | 1356 | return (0 == result) ? GNUNET_OK : GNUNET_SYSERR; |
971 | return (GNUNET_OK == result ? GNUNET_OK : GNUNET_SYSERR); | ||
972 | } | 1357 | } |
973 | 1358 | ||
974 | /* end of pseudonym.c */ | 1359 | /* end of pseudonym.c */ |