aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-02 13:10:25 +0100
committerChristian Grothoff <christian@grothoff.org>2022-01-02 13:10:25 +0100
commitbb686c48354853aa725e493e85edce0602ed85e2 (patch)
tree6b0aeea58a7aebe0e3108da5302eaeae2c996ceb /src
parent2cbb614f694701c4afdab88f58ef7626629e1bc3 (diff)
downloadgnunet-bb686c48354853aa725e493e85edce0602ed85e2.tar.gz
gnunet-bb686c48354853aa725e493e85edce0602ed85e2.zip
revise DHT hashing functions, add test logic
Diffstat (limited to 'src')
-rw-r--r--src/dht/gnunet-service-dht_datacache.c7
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c96
-rw-r--r--src/include/gnunet_crypto_lib.h68
-rw-r--r--src/nse/gnunet-service-nse.c29
-rw-r--r--src/revocation/revocation_api.c19
-rw-r--r--src/util/crypto_hash.c143
-rw-r--r--src/util/gnunet-scrypt.c21
-rw-r--r--src/util/test_crypto_hash.c227
8 files changed, 358 insertions, 252 deletions
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
index 8645ea069..a81cc9993 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -65,6 +65,7 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
65 size_t data_size, 65 size_t data_size,
66 const void *data) 66 const void *data)
67{ 67{
68 struct GNUNET_HashCode xor;
68 int r; 69 int r;
69 70
70 if (NULL == datacache) 71 if (NULL == datacache)
@@ -83,10 +84,12 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
83 gettext_noop ("# ITEMS stored in datacache"), 84 gettext_noop ("# ITEMS stored in datacache"),
84 1, 85 1,
85 GNUNET_NO); 86 GNUNET_NO);
87 GNUNET_CRYPTO_hash_xor (key,
88 &my_identity_hash,
89 &xor);
86 r = GNUNET_DATACACHE_put (datacache, 90 r = GNUNET_DATACACHE_put (datacache,
87 key, 91 key,
88 GNUNET_CRYPTO_hash_matching_bits (key, 92 GNUNET_CRYPTO_hash_count_leading_zeros (&xor),
89 &my_identity_hash),
90 data_size, 93 data_size,
91 data, 94 data,
92 type, 95 type,
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index d48d2a5df..3cb788a06 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -430,9 +430,13 @@ static struct GNUNET_ATS_ConnectivityHandle *ats_ch;
430static int 430static int
431find_bucket (const struct GNUNET_HashCode *hc) 431find_bucket (const struct GNUNET_HashCode *hc)
432{ 432{
433 struct GNUNET_HashCode xor;
433 unsigned int bits; 434 unsigned int bits;
434 435
435 bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, hc); 436 GNUNET_CRYPTO_hash_xor (hc,
437 &my_identity_hash,
438 &xor);
439 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
436 if (bits == MAX_BUCKETS) 440 if (bits == MAX_BUCKETS)
437 { 441 {
438 /* How can all bits match? Got my own ID? */ 442 /* How can all bits match? Got my own ID? */
@@ -889,40 +893,6 @@ get_forward_count (uint32_t hop_count,
889 893
890 894
891/** 895/**
892 * Compute the distance between have and target as a 64-bit value.
893 * Differences in the lower bits must count stronger than differences
894 * in the higher bits.
895 *
896 * @param target
897 * @param have
898 * @param bucket up to which offset are @a target and @a have identical and thus those bits should not be considered
899 * @return 0 if have==target, otherwise a number
900 * that is larger as the distance between
901 * the two hash codes increases
902 */
903static uint64_t
904get_distance (const struct GNUNET_HashCode *target,
905 const struct GNUNET_HashCode *have,
906 unsigned int bucket)
907{
908 uint64_t lsb = 0;
909
910 for (unsigned int i = bucket + 1;
911 (i < sizeof(struct GNUNET_HashCode) * 8) &&
912 (i < bucket + 1 + 64);
913 i++)
914 {
915 if (GNUNET_CRYPTO_hash_get_bit_rtl (target, i) !=
916 GNUNET_CRYPTO_hash_get_bit_rtl (have, i))
917 lsb |= (1LLU << (bucket + 64 - i)); /* first bit set will be 1,
918 * last bit set will be 63 -- if
919 * i does not reach 512 first... */
920 }
921 return lsb;
922}
923
924
925/**
926 * Check whether my identity is closer than any known peers. If a 896 * Check whether my identity is closer than any known peers. If a
927 * non-null bloomfilter is given, check if this is the closest peer 897 * non-null bloomfilter is given, check if this is the closest peer
928 * that hasn't already been routed to. 898 * that hasn't already been routed to.
@@ -936,7 +906,7 @@ enum GNUNET_GenericReturnValue
936GDS_am_closest_peer (const struct GNUNET_HashCode *key, 906GDS_am_closest_peer (const struct GNUNET_HashCode *key,
937 const struct GNUNET_CONTAINER_BloomFilter *bloom) 907 const struct GNUNET_CONTAINER_BloomFilter *bloom)
938{ 908{
939 int bits; 909 struct GNUNET_HashCode xor;
940 int other_bits; 910 int other_bits;
941 int bucket_num; 911 int bucket_num;
942 struct PeerInfo *pos; 912 struct PeerInfo *pos;
@@ -946,8 +916,6 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
946 return GNUNET_YES; 916 return GNUNET_YES;
947 bucket_num = find_bucket (key); 917 bucket_num = find_bucket (key);
948 GNUNET_assert (bucket_num >= 0); 918 GNUNET_assert (bucket_num >= 0);
949 bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
950 key);
951 pos = k_buckets[bucket_num].head; 919 pos = k_buckets[bucket_num].head;
952 while (NULL != pos) 920 while (NULL != pos)
953 { 921 {
@@ -959,9 +927,11 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
959 pos = pos->next; 927 pos = pos->next;
960 continue; /* Skip already checked entries */ 928 continue; /* Skip already checked entries */
961 } 929 }
962 other_bits = GNUNET_CRYPTO_hash_matching_bits (&pos->phash, 930 GNUNET_CRYPTO_hash_xor (&pos->phash,
963 key); 931 key,
964 if (other_bits > bits) 932 &xor);
933 other_bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
934 if (other_bits > bucket_num)
965 return GNUNET_NO; 935 return GNUNET_NO;
966 pos = pos->next; 936 pos = pos->next;
967 } 937 }
@@ -1013,14 +983,16 @@ select_peer (const struct GNUNET_HashCode *key,
1013 (count < bucket_size); 983 (count < bucket_size);
1014 pos = pos->next) 984 pos = pos->next)
1015 { 985 {
986 struct GNUNET_HashCode xor;
1016 unsigned int bucket; 987 unsigned int bucket;
1017 uint64_t dist; 988 uint64_t dist;
1018 989
1019 bucket = GNUNET_CRYPTO_hash_matching_bits (key, 990 GNUNET_CRYPTO_hash_xor (key,
1020 &pos->phash); 991 &pos->phash,
1021 dist = get_distance (key, 992 &xor);
1022 &pos->phash, 993 bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
1023 bucket); 994 dist = GNUNET_CRYPTO_hash_bucket_distance (&xor,
995 bucket);
1024 if (bucket < best_bucket) 996 if (bucket < best_bucket)
1025 continue; 997 continue;
1026 if (dist > best_in_bucket) 998 if (dist > best_in_bucket)
@@ -1691,7 +1663,15 @@ handle_dht_p2p_put (void *cls,
1691 { 1663 {
1692 char *tmp; 1664 char *tmp;
1693 char *pp; 1665 char *pp;
1694 1666 struct GNUNET_HashCode mxor;
1667 struct GNUNET_HashCode pxor;
1668
1669 GNUNET_CRYPTO_hash_xor (&my_identity_hash,
1670 &put->key,
1671 &mxor);
1672 GNUNET_CRYPTO_hash_xor (&peer->phash,
1673 &put->key,
1674 &pxor);
1695 pp = GNUNET_STRINGS_pp2s (put_path, 1675 pp = GNUNET_STRINGS_pp2s (put_path,
1696 putlen); 1676 putlen);
1697 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); 1677 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
@@ -1701,10 +1681,8 @@ handle_dht_p2p_put (void *cls,
1701 GNUNET_i2s (peer->id), 1681 GNUNET_i2s (peer->id),
1702 tmp, 1682 tmp,
1703 ntohl (put->hop_count), 1683 ntohl (put->hop_count),
1704 GNUNET_CRYPTO_hash_matching_bits (&peer->phash, 1684 GNUNET_CRYPTO_hash_count_leading_zeros (&pxor),
1705 &put->key), 1685 GNUNET_CRYPTO_hash_count_leading_zeros (&mxor),
1706 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
1707 &put->key),
1708 pp); 1686 pp);
1709 GNUNET_free (pp); 1687 GNUNET_free (pp);
1710 GNUNET_free (tmp); 1688 GNUNET_free (tmp);
@@ -2070,7 +2048,15 @@ handle_dht_p2p_get (void *cls,
2070 if (GNUNET_YES == log_route_details_stderr) 2048 if (GNUNET_YES == log_route_details_stderr)
2071 { 2049 {
2072 char *tmp; 2050 char *tmp;
2073 2051 struct GNUNET_HashCode mxor;
2052 struct GNUNET_HashCode pxor;
2053
2054 GNUNET_CRYPTO_hash_xor (&my_identity_hash,
2055 &get->key,
2056 &mxor);
2057 GNUNET_CRYPTO_hash_xor (&peer->phash,
2058 &get->key,
2059 &pxor);
2074 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); 2060 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
2075 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 2061 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
2076 "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n", 2062 "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n",
@@ -2078,10 +2064,8 @@ handle_dht_p2p_get (void *cls,
2078 GNUNET_i2s (peer->id), 2064 GNUNET_i2s (peer->id),
2079 tmp, 2065 tmp,
2080 ntohl (get->hop_count), 2066 ntohl (get->hop_count),
2081 GNUNET_CRYPTO_hash_matching_bits (&peer->phash, 2067 GNUNET_CRYPTO_hash_count_leading_zeros (&pxor),
2082 &get->key), 2068 GNUNET_CRYPTO_hash_count_leading_zeros (&mxor),
2083 GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash,
2084 &get->key),
2085 ntohl (get->xquery_size), 2069 ntohl (get->xquery_size),
2086 (const char *) xquery); 2070 (const char *) xquery);
2087 GNUNET_free (tmp); 2071 GNUNET_free (tmp);
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index bd318ab84..4e26429c9 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -1038,61 +1038,53 @@ GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a,
1038 1038
1039 1039
1040/** 1040/**
1041 * @ingroup hash 1041 * Count the number of leading 0 bits in @a h.
1042 * Convert a hashcode into a key.
1043 * 1042 *
1044 * @param hc hash code that serves to generate the key 1043 * @param h a hash
1045 * @param skey set to a valid session key 1044 * @return number of leading 0 bits in @a h
1046 * @param iv set to a valid initialization vector
1047 */ 1045 */
1048void 1046unsigned int
1049GNUNET_CRYPTO_hash_to_aes_key ( 1047GNUNET_CRYPTO_hash_count_leading_zeros (const struct GNUNET_HashCode *h);
1050 const struct GNUNET_HashCode *hc,
1051 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
1052 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv);
1053 1048
1054 1049
1055/** 1050/**
1056 * @ingroup hash 1051 * Count the number of tailing 0 bits in @a h.
1057 * Obtain a bit from a hashcode.
1058 * 1052 *
1059 * @param code the `struct GNUNET_HashCode` to index bit-wise 1053 * @param h a hash
1060 * @param bit index into the hashcode, [0...159] where 0 is the leftmost bit 1054 * @return number of tailing 0 bits in @a h
1061 * (bytes in code interpreted big endian)
1062 * @return Bit \a bit from hashcode \a code, -1 for invalid index
1063 */ 1055 */
1064int 1056unsigned int
1065GNUNET_CRYPTO_hash_get_bit_ltr (const struct GNUNET_HashCode *code, 1057GNUNET_CRYPTO_hash_count_tailing_zeros (const struct GNUNET_HashCode *h);
1066 unsigned int bit);
1067 1058
1068 1059
1069/** 1060/**
1070 * Obtain a bit from a hashcode. 1061 * Compute the distance between have and target as a 64-bit value.
1071 * @param code the GNUNET_CRYPTO_hash to index bit-wise 1062 * Differences in the lower bits must count stronger than differences
1072 * @param bit index into the hashcode, [0...511] where 0 is the rightmost bit 1063 * in the higher bits.
1073 * (bytes in code interpreted little endian) 1064 *
1074 * @return Bit \a bit from hashcode \a code, -1 for invalid index 1065 * @param xor input hash
1066 * @param bucket up to which offset we are to ignore @a xor
1067 * @return the subsequent 64 bits after @a bucket from @a xor, in
1068 * host byte order.
1075 */ 1069 */
1076int 1070uint64_t
1077GNUNET_CRYPTO_hash_get_bit_rtl (const struct GNUNET_HashCode *code, 1071GNUNET_CRYPTO_hash_bucket_distance (const struct GNUNET_HashCode *xor,
1078 unsigned int bit); 1072 unsigned int bucket);
1079 1073
1080 1074
1081/** 1075/**
1082 * @ingroup hash 1076 * @ingroup hash
1083 * Determine how many low order bits match in two 1077 * Convert a hashcode into a key.
1084 * `struct GNUNET_HashCodes`. e.g. - 010011 and 011111 share
1085 * the first two lowest order bits, and therefore the
1086 * return value is two (NOT XOR distance, nor how many
1087 * bits match absolutely!).
1088 * 1078 *
1089 * @param first the first hashcode 1079 * @param hc hash code that serves to generate the key
1090 * @param second the hashcode to compare first to 1080 * @param skey set to a valid session key
1091 * @return the number of bits that match 1081 * @param iv set to a valid initialization vector
1092 */ 1082 */
1093unsigned int 1083void
1094GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode *first, 1084GNUNET_CRYPTO_hash_to_aes_key (
1095 const struct GNUNET_HashCode *second); 1085 const struct GNUNET_HashCode *hc,
1086 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
1087 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv);
1096 1088
1097 1089
1098/** 1090/**
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c
index 972b3a79d..35278db29 100644
--- a/src/nse/gnunet-service-nse.c
+++ b/src/nse/gnunet-service-nse.c
@@ -774,24 +774,6 @@ update_flood_message (void *cls)
774 774
775 775
776/** 776/**
777 * Count the leading zeroes in hash.
778 *
779 * @param hash to count leading zeros in
780 * @return the number of leading zero bits.
781 */
782static unsigned int
783count_leading_zeroes (const struct GNUNET_HashCode *hash)
784{
785 unsigned int hash_count;
786
787 hash_count = 0;
788 while (0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count))
789 hash_count++;
790 return hash_count;
791}
792
793
794/**
795 * Check whether the given public key and integer are a valid proof of 777 * Check whether the given public key and integer are a valid proof of
796 * work. 778 * work.
797 * 779 *
@@ -799,7 +781,7 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash)
799 * @param val the integer 781 * @param val the integer
800 * @return #GNUNET_YES if valid, #GNUNET_NO if not 782 * @return #GNUNET_YES if valid, #GNUNET_NO if not
801 */ 783 */
802static int 784static enum GNUNET_GenericReturnValue
803check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, 785check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
804 uint64_t val) 786 uint64_t val)
805{ 787{
@@ -815,8 +797,10 @@ check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
815 buf, 797 buf,
816 sizeof(buf), 798 sizeof(buf),
817 &result); 799 &result);
818 return (count_leading_zeroes (&result) >= nse_work_required) ? GNUNET_YES 800 return (GNUNET_CRYPTO_hash_count_leading_zeroes (&result) >=
819 : GNUNET_NO; 801 nse_work_required)
802 ? GNUNET_YES
803 : GNUNET_NO;
820} 804}
821 805
822 806
@@ -877,7 +861,8 @@ find_proof (void *cls)
877 buf, 861 buf,
878 sizeof(buf), 862 sizeof(buf),
879 &result); 863 &result);
880 if (nse_work_required <= count_leading_zeroes (&result)) 864 if (nse_work_required <=
865 GNUNET_CRYPTO_hash_count_leading_zeroes (&result))
881 { 866 {
882 my_proof = counter; 867 my_proof = counter;
883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
index f2b95bafa..1032b98f7 100644
--- a/src/revocation/revocation_api.c
+++ b/src/revocation/revocation_api.c
@@ -389,23 +389,6 @@ GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h)
389 389
390 390
391/** 391/**
392 * Count the leading zeroes in hash.
393 *
394 * @param hash to count leading zeros in
395 * @return the number of leading zero bits.
396 */
397static unsigned int
398count_leading_zeroes (const struct GNUNET_HashCode *hash)
399{
400 unsigned int hash_count;
401 hash_count = 0;
402 while ((0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count)))
403 hash_count++;
404 return hash_count;
405}
406
407
408/**
409 * Calculate the average zeros in the pows. 392 * Calculate the average zeros in the pows.
410 * 393 *
411 * @param ph the PowHandle 394 * @param ph the PowHandle
@@ -535,7 +518,7 @@ GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
535 buf, 518 buf,
536 sizeof(buf), 519 sizeof(buf),
537 &result); 520 &result);
538 tmp_score = count_leading_zeroes (&result); 521 tmp_score = GNUNET_CRYPTO_hash_count_leading_zeroes (&result);
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Score %u with %" PRIu64 " (#%u)\n", 523 "Score %u with %" PRIu64 " (#%u)\n",
541 tmp_score, pow_val, i); 524 tmp_score, pow_val, i);
diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c
index d62ec8012..b51ecd242 100644
--- a/src/util/crypto_hash.c
+++ b/src/util/crypto_hash.c
@@ -135,18 +135,57 @@ GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a,
135 const struct GNUNET_HashCode *b, 135 const struct GNUNET_HashCode *b,
136 struct GNUNET_HashCode *result) 136 struct GNUNET_HashCode *result)
137{ 137{
138 for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(unsigned int)) - 1; 138 const unsigned long long *lla = (const unsigned long long *) a;
139 i >= 0; 139 const unsigned long long *llb = (const unsigned long long *) b;
140 i--) 140 unsigned long long *llr = (unsigned long long *) result;
141 result->bits[i] = a->bits[i] ^ b->bits[i]; 141
142 GNUNET_static_assert (8 == sizeof (unsigned long long));
143 GNUNET_static_assert (0 == sizeof (*a) % sizeof (unsigned long long));
144 for (int i = sizeof (*result) / sizeof (*llr) - 1; i>=0; i--)
145 llr[i] = lla[i] ^ llb[i];
146}
147
148
149uint64_t
150GNUNET_CRYPTO_hash_bucket_distance (const struct GNUNET_HashCode *xor,
151 unsigned int bucket)
152{
153 const uint64_t *u = (const uint64_t *) xor;
154 unsigned int idx;
155 unsigned int bits;
156 uint64_t rval;
157
158 if (bucket == 8 * sizeof(*xor))
159 return 0;
160 bucket++;
161 idx = bucket / 64;
162 bits = bucket % 64;
163 if (idx >= sizeof (*xor) / sizeof (*u))
164 return 0;
165 if (0 == bits)
166 {
167 /* keeps no bits */
168 rval = 0;
169 }
170 else
171 {
172 /* keeps lowest (64-bits) bits */
173 rval = GNUNET_ntohll (u[idx]) << bits;
174 }
175 if (idx + 1 < sizeof (*xor) / sizeof (*u))
176 {
177 /* discards lowest (bits) bits */
178 rval |= GNUNET_ntohll (u[idx + 1]) >> (64 - bits);
179 }
180 return rval;
142} 181}
143 182
144 183
145void 184void
146GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc, 185GNUNET_CRYPTO_hash_to_aes_key (
147 struct GNUNET_CRYPTO_SymmetricSessionKey *skey, 186 const struct GNUNET_HashCode *hc,
148 struct 187 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
149 GNUNET_CRYPTO_SymmetricInitializationVector *iv) 188 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
150{ 189{
151 GNUNET_assert (GNUNET_YES == 190 GNUNET_assert (GNUNET_YES ==
152 GNUNET_CRYPTO_kdf ( 191 GNUNET_CRYPTO_kdf (
@@ -167,33 +206,47 @@ GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc,
167} 206}
168 207
169 208
170int 209unsigned int
171GNUNET_CRYPTO_hash_get_bit_ltr (const struct GNUNET_HashCode *code, 210GNUNET_CRYPTO_hash_count_leading_zeros (const struct GNUNET_HashCode *h)
172 unsigned int bit)
173{ 211{
174 GNUNET_assert (bit < 8 * sizeof(struct GNUNET_HashCode)); 212 const unsigned long long *llp = (const unsigned long long *) h;
175 return (((unsigned char *) code)[bit >> 3] & (128 >> (bit & 7))) > 0; 213 unsigned int ret = 0;
176} 214 unsigned int i;
177
178 215
179int 216 GNUNET_static_assert (8 == sizeof (unsigned long long));
180GNUNET_CRYPTO_hash_get_bit_rtl (const struct GNUNET_HashCode *code, 217 GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
181 unsigned int bit) 218 for (i = 0; i<sizeof (*h) / sizeof (*llp); i++)
182{ 219 {
183 GNUNET_assert (bit < 8 * sizeof(struct GNUNET_HashCode)); 220 if (0LLU != llp[i])
184 return (((unsigned char *) code)[bit >> 3] & (1 << (bit & 7))) > 0; 221 break;
222 ret += sizeof (*llp) * 8;
223 }
224 if (ret == 8 * sizeof (*h))
225 return ret;
226 ret += __builtin_clzll (GNUNET_ntohll ((uint64_t) llp[i]));
227 return ret;
185} 228}
186 229
187 230
188unsigned int 231unsigned int
189GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode *first, 232GNUNET_CRYPTO_hash_count_tailing_zeros (const struct GNUNET_HashCode *h)
190 const struct GNUNET_HashCode *second)
191{ 233{
192 for (unsigned int i = 0; i < sizeof(struct GNUNET_HashCode) * 8; i++) 234 const unsigned long long *llp = (const unsigned long long *) h;
193 if (GNUNET_CRYPTO_hash_get_bit_rtl (first, i) != 235 unsigned int ret = 0;
194 GNUNET_CRYPTO_hash_get_bit_rtl (second, i)) 236 int i;
195 return i; 237
196 return sizeof(struct GNUNET_HashCode) * 8; 238 GNUNET_static_assert (8 == sizeof (unsigned long long));
239 GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
240 for (i = sizeof (*h) / sizeof (*llp) - 1; i>=0; i--)
241 {
242 if (0LLU != llp[i])
243 break;
244 ret += sizeof (*llp) * 8;
245 }
246 if (ret == 8 * sizeof (*h))
247 return ret;
248 ret += __builtin_ctzll (GNUNET_ntohll ((uint64_t) llp[i]));
249 return ret;
197} 250}
198 251
199 252
@@ -243,25 +296,30 @@ GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1,
243 296
244 297
245void 298void
246GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key, 299GNUNET_CRYPTO_hmac_derive_key (
247 const struct 300 struct GNUNET_CRYPTO_AuthKey *key,
248 GNUNET_CRYPTO_SymmetricSessionKey *rkey, 301 const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
249 const void *salt, size_t salt_len, ...) 302 const void *salt, size_t salt_len,
303 ...)
250{ 304{
251 va_list argp; 305 va_list argp;
252 306
253 va_start (argp, salt_len); 307 va_start (argp,
254 GNUNET_CRYPTO_hmac_derive_key_v (key, rkey, salt, salt_len, argp); 308 salt_len);
309 GNUNET_CRYPTO_hmac_derive_key_v (key,
310 rkey,
311 salt, salt_len,
312 argp);
255 va_end (argp); 313 va_end (argp);
256} 314}
257 315
258 316
259void 317void
260GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, 318GNUNET_CRYPTO_hmac_derive_key_v (
261 const struct 319 struct GNUNET_CRYPTO_AuthKey *key,
262 GNUNET_CRYPTO_SymmetricSessionKey *rkey, 320 const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
263 const void *salt, size_t salt_len, 321 const void *salt, size_t salt_len,
264 va_list argp) 322 va_list argp)
265{ 323{
266 GNUNET_CRYPTO_kdf_v (key->key, sizeof(key->key), 324 GNUNET_CRYPTO_kdf_v (key->key, sizeof(key->key),
267 salt, salt_len, 325 salt, salt_len,
@@ -283,7 +341,9 @@ GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len,
283 { 341 {
284 once = 1; 342 once = 1;
285 GNUNET_assert (GPG_ERR_NO_ERROR == 343 GNUNET_assert (GPG_ERR_NO_ERROR ==
286 gcry_md_open (&md, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC)); 344 gcry_md_open (&md,
345 GCRY_MD_SHA512,
346 GCRY_MD_FLAG_HMAC));
287 } 347 }
288 else 348 else
289 { 349 {
@@ -323,15 +383,12 @@ GNUNET_CRYPTO_hash_context_start ()
323 struct GNUNET_HashContext *hc; 383 struct GNUNET_HashContext *hc;
324 384
325 BENCHMARK_START (hash_context_start); 385 BENCHMARK_START (hash_context_start);
326
327 hc = GNUNET_new (struct GNUNET_HashContext); 386 hc = GNUNET_new (struct GNUNET_HashContext);
328 GNUNET_assert (0 == 387 GNUNET_assert (0 ==
329 gcry_md_open (&hc->hd, 388 gcry_md_open (&hc->hd,
330 GCRY_MD_SHA512, 389 GCRY_MD_SHA512,
331 0)); 390 0));
332
333 BENCHMARK_END (hash_context_start); 391 BENCHMARK_END (hash_context_start);
334
335 return hc; 392 return hc;
336} 393}
337 394
diff --git a/src/util/gnunet-scrypt.c b/src/util/gnunet-scrypt.c
index fe8b6769f..ad46e3f39 100644
--- a/src/util/gnunet-scrypt.c
+++ b/src/util/gnunet-scrypt.c
@@ -78,24 +78,6 @@ shutdown_task (void *cls)
78 78
79 79
80/** 80/**
81 * Count the leading zeroes in hash.
82 *
83 * @param hash to count leading zeros in
84 * @return the number of leading zero bits.
85 */
86static unsigned int
87count_leading_zeroes (const struct GNUNET_HashCode *hash)
88{
89 unsigned int hash_count;
90
91 hash_count = 0;
92 while (0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count))
93 hash_count++;
94 return hash_count;
95}
96
97
98/**
99 * Find our proof of work. 81 * Find our proof of work.
100 * 82 *
101 * @param cls closure (unused) 83 * @param cls closure (unused)
@@ -131,7 +113,8 @@ find_proof (void *cls)
131 buf, 113 buf,
132 sizeof(buf), 114 sizeof(buf),
133 &result); 115 &result);
134 if (nse_work_required <= count_leading_zeroes (&result)) 116 if (nse_work_required <=
117 GNUNET_CRYPTO_hash_count_leading_zeros (&result))
135 { 118 {
136 proof = counter; 119 proof = counter;
137 fprintf (stdout, 120 fprintf (stdout,
diff --git a/src/util/test_crypto_hash.c b/src/util/test_crypto_hash.c
index d22e1f5d3..1fddcfba8 100644
--- a/src/util/test_crypto_hash.c
+++ b/src/util/test_crypto_hash.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2002, 2003, 2004, 2006, 2009 GNUnet e.V. 3 Copyright (C) 2002, 2003, 2004, 2006, 2009, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -37,25 +37,29 @@ test (int number)
37 struct GNUNET_HashCode h2; 37 struct GNUNET_HashCode h2;
38 struct GNUNET_CRYPTO_HashAsciiEncoded enc; 38 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
39 39
40 memset (&h1, number, sizeof(struct GNUNET_HashCode)); 40 memset (&h1,
41 GNUNET_CRYPTO_hash_to_enc (&h1, &enc); 41 number,
42 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &h2)) 42 sizeof(struct GNUNET_HashCode));
43 GNUNET_CRYPTO_hash_to_enc (&h1,
44 &enc);
45 if (GNUNET_OK !=
46 GNUNET_CRYPTO_hash_from_string ((char *) &enc,
47 &h2))
43 { 48 {
44 printf ("enc2hash failed!\n"); 49 printf ("enc2hash failed!\n");
45 return 1; 50 return 1;
46 } 51 }
47 if (0 != memcmp (&h1, &h2, sizeof(struct GNUNET_HashCode))) 52 if (0 != GNUNET_memcmp (&h1,
53 &h2))
48 return 1; 54 return 1;
49 return 0; 55 return 0;
50} 56}
51 57
52 58
53static int 59static int
54testEncoding () 60test_encoding (void)
55{ 61{
56 int i; 62 for (int i = 0; i < 255; i++)
57
58 for (i = 0; i < 255; i++)
59 if (0 != test (i)) 63 if (0 != test (i))
60 return 1; 64 return 1;
61 return 0; 65 return 0;
@@ -63,7 +67,7 @@ testEncoding ()
63 67
64 68
65static int 69static int
66testArithmetic () 70test_arithmetic (void)
67{ 71{
68 struct GNUNET_HashCode h1; 72 struct GNUNET_HashCode h1;
69 struct GNUNET_HashCode h2; 73 struct GNUNET_HashCode h2;
@@ -72,49 +76,150 @@ testArithmetic ()
72 struct GNUNET_CRYPTO_SymmetricSessionKey skey; 76 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
73 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 77 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
74 78
75 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &h1); 79 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
76 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &h2); 80 &h1);
77 if (GNUNET_CRYPTO_hash_distance_u32 (&h1, &h2) != 81 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
78 GNUNET_CRYPTO_hash_distance_u32 (&h2, &h1)) 82 &h2);
79 return 1; 83 if (GNUNET_CRYPTO_hash_distance_u32 (&h1,
80 GNUNET_CRYPTO_hash_difference (&h1, &h2, &d); 84 &h2) !=
81 GNUNET_CRYPTO_hash_sum (&h1, &d, &s); 85 GNUNET_CRYPTO_hash_distance_u32 (&h2,
82 if (0 != GNUNET_CRYPTO_hash_cmp (&s, &h2)) 86 &h1))
83 return 1;
84 GNUNET_CRYPTO_hash_xor (&h1, &h2, &d);
85 GNUNET_CRYPTO_hash_xor (&h1, &d, &s);
86 if (0 != GNUNET_CRYPTO_hash_cmp (&s, &h2))
87 return 1;
88 if (0 != GNUNET_CRYPTO_hash_xorcmp (&s, &h2, &h1))
89 return 1;
90 if (-1 != GNUNET_CRYPTO_hash_xorcmp (&h1, &h2, &h1))
91 return 1; 87 return 1;
92 if (1 != GNUNET_CRYPTO_hash_xorcmp (&h1, &h2, &h2)) 88 GNUNET_CRYPTO_hash_difference (&h1,
89 &h2,
90 &d);
91 GNUNET_CRYPTO_hash_sum (&h1,
92 &d,
93 &s);
94 if (0 !=
95 GNUNET_CRYPTO_hash_cmp (&s,
96 &h2))
93 return 1; 97 return 1;
94 memset (&d, 0x40, sizeof(d)); 98 GNUNET_CRYPTO_hash_xor (&h1,
95 if (0 != GNUNET_CRYPTO_hash_get_bit_rtl (&d, 3)) 99 &h2,
100 &d);
101 GNUNET_CRYPTO_hash_xor (&h1,
102 &d,
103 &s);
104 if (0 !=
105 GNUNET_CRYPTO_hash_cmp (&s,
106 &h2))
96 return 1; 107 return 1;
97 if (1 != GNUNET_CRYPTO_hash_get_bit_rtl (&d, 6)) 108 if (0 !=
109 GNUNET_CRYPTO_hash_xorcmp (&s,
110 &h2,
111 &h1))
98 return 1; 112 return 1;
99 memset (&d, 0x02, sizeof(d)); 113 if (-1 !=
100 if (0 != GNUNET_CRYPTO_hash_get_bit_ltr (&d, 3)) 114 GNUNET_CRYPTO_hash_xorcmp (&h1,
115 &h2,
116 &h1))
101 return 1; 117 return 1;
102 if (1 != GNUNET_CRYPTO_hash_get_bit_ltr (&d, 6)) 118 if (1 !=
119 GNUNET_CRYPTO_hash_xorcmp (&h1,
120 &h2,
121 &h2))
103 return 1; 122 return 1;
104 memset (&d, 0, sizeof(d)); 123 memset (&d,
105 GNUNET_CRYPTO_hash_to_aes_key (&d, &skey, &iv); 124 0,
125 sizeof(d));
126 GNUNET_CRYPTO_hash_to_aes_key (&d,
127 &skey,
128 &iv);
129 memset (&h1,
130 0,
131 sizeof (h1));
132 h1.bits[1] = htonl (0x00200000); /* 32 + 8 + 2 = 42 MSB bits cleared */
133 GNUNET_assert (42 ==
134 GNUNET_CRYPTO_hash_count_leading_zeros (&h1));
135 GNUNET_assert (512 - 42 - 1 ==
136 GNUNET_CRYPTO_hash_count_tailing_zeros (&h1));
137 memset (&h1,
138 0,
139 sizeof (h1));
140 memset (&h2,
141 0,
142 sizeof (h2));
143 h1.bits[3] = htonl (0x00800011); /* 3*32 + 8 Bits identical */
144 h2.bits[3] = htonl (0x00000101); /* residual delta: 0x000220.. (+1 bit)*/
145 /* Note: XOR: 0x00800110 */
146 h1.bits[4] = htonl (0x14144141);
147 h2.bits[4] = htonl (0x28288282); /* residual delta: 0x3C3CC3.. */
148 /* Note: XOR: 0x3C3CC3C3 */
149 /* Note: XOR<<1: 0x78798786 */
150 GNUNET_assert (104 ==
151 GNUNET_CRYPTO_hash_count_leading_zeros (&h1));
152 GNUNET_CRYPTO_hash_xor (&h1,
153 &h2,
154 &s);
155 GNUNET_assert (104 ==
156 GNUNET_CRYPTO_hash_count_leading_zeros (&s));
157 GNUNET_assert (0x0002207879878600LLU ==
158 GNUNET_CRYPTO_hash_bucket_distance (&s,
159 104));
160
161 memset (&h1,
162 0,
163 sizeof (h1));
164 memset (&h2,
165 0,
166 sizeof (h2));
167 h1.bits[4] = htonl (0x00000001); /* 5*32 - 1 Bits identical */
168 h2.bits[4] = htonl (0x00000000);
169 /* Note: XOR: 0x00000001 */
170 h1.bits[5] = htonl (0x14144141);
171 h2.bits[5] = htonl (0x28288282);
172 /* Note: XOR: 0x3C3CC3C3 */
173 GNUNET_assert (159 ==
174 GNUNET_CRYPTO_hash_count_leading_zeros (&h1));
175 GNUNET_CRYPTO_hash_xor (&h1,
176 &h2,
177 &s);
178 GNUNET_assert (159 ==
179 GNUNET_CRYPTO_hash_count_leading_zeros (&s));
180 GNUNET_assert (0x3C3CC3C300000000 ==
181 GNUNET_CRYPTO_hash_bucket_distance (&s,
182 159));
183
184 memset (&h1,
185 0,
186 sizeof (h1));
187 memset (&h2,
188 0,
189 sizeof (h2));
190 h1.bits[14] = htonl (0x00000001); /* 15*32 - 1 Bits identical */
191 h2.bits[14] = htonl (0x00000000);
192 /* Note: XOR: 0x00000001 */
193 h1.bits[15] = htonl (0x14144141);
194 h2.bits[15] = htonl (0x28288282);
195 /* Note: XOR: 0x3C3CC3C3 */
196 GNUNET_assert (479 ==
197 GNUNET_CRYPTO_hash_count_leading_zeros (&h1));
198 GNUNET_CRYPTO_hash_xor (&h1,
199 &h2,
200 &s);
201 GNUNET_assert (479 ==
202 GNUNET_CRYPTO_hash_count_leading_zeros (&s));
203 GNUNET_assert (0x3C3CC3C300000000 ==
204 GNUNET_CRYPTO_hash_bucket_distance (&s,
205 479));
206
106 return 0; 207 return 0;
107} 208}
108 209
109 210
110static void 211static void
111finished_task (void *cls, const struct GNUNET_HashCode *res) 212finished_task (void *cls,
213 const struct GNUNET_HashCode *res)
112{ 214{
113 int *ret = cls; 215 int *ret = cls;
114 struct GNUNET_HashCode want; 216 struct GNUNET_HashCode want;
115 217
116 GNUNET_CRYPTO_hash (block, sizeof(block), &want); 218 GNUNET_CRYPTO_hash (block,
117 if (0 != memcmp (res, &want, sizeof(want))) 219 sizeof(block),
220 &want);
221 if (0 != GNUNET_memcmp (res,
222 &want))
118 *ret = 2; 223 *ret = 2;
119 else 224 else
120 *ret = 0; 225 *ret = 0;
@@ -126,43 +231,57 @@ file_hasher (void *cls)
126{ 231{
127 GNUNET_assert (NULL != 232 GNUNET_assert (NULL !=
128 GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_DEFAULT, 233 GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
129 FILENAME, 1024, &finished_task, cls)); 234 FILENAME,
235 1024,
236 &finished_task,
237 cls));
130} 238}
131 239
132 240
133static int 241static int
134testFileHash () 242test_file_hash (void)
135{ 243{
136 int ret; 244 int ret;
137 FILE *f; 245 FILE *f;
138 246
139 memset (block, 42, sizeof(block) / 2); 247 memset (block,
140 memset (&block[sizeof(block) / 2], 43, sizeof(block) / 2); 248 42,
249 sizeof(block) / 2);
250 memset (&block[sizeof(block) / 2],
251 43,
252 sizeof(block) / 2);
141 GNUNET_assert (NULL != (f = fopen (FILENAME, "w+"))); 253 GNUNET_assert (NULL != (f = fopen (FILENAME, "w+")));
142 GNUNET_break (sizeof(block) == fwrite (block, 1, sizeof(block), f)); 254 GNUNET_break (sizeof(block) ==
255 fwrite (block,
256 1,
257 sizeof(block),
258 f));
143 GNUNET_break (0 == fclose (f)); 259 GNUNET_break (0 == fclose (f));
144 ret = 1; 260 ret = 1;
145 GNUNET_SCHEDULER_run (&file_hasher, &ret); 261 GNUNET_SCHEDULER_run (&file_hasher,
262 &ret);
146 GNUNET_break (0 == unlink (FILENAME)); 263 GNUNET_break (0 == unlink (FILENAME));
147 return ret; 264 return ret;
148} 265}
149 266
150 267
151int 268int
152main (int argc, char *argv[]) 269main (int argc,
270 char *argv[])
153{ 271{
154 int failureCount = 0; 272 int failureCount = 0;
155 int i; 273
156 274 GNUNET_log_setup ("test-crypto-hash",
157 GNUNET_log_setup ("test-crypto-hash", "WARNING", NULL); 275 "WARNING",
158 for (i = 0; i < 10; i++) 276 NULL);
159 failureCount += testEncoding (); 277 for (int i = 0; i < 10; i++)
160 failureCount += testArithmetic (); 278 failureCount += test_encoding ();
161 failureCount += testFileHash (); 279 failureCount += test_arithmetic ();
162 if (failureCount != 0) 280 failureCount += test_file_hash ();
281 if (0 != failureCount)
163 return 1; 282 return 1;
164 return 0; 283 return 0;
165} 284}
166 285
167 286
168/* end of hashingtest.c */ 287/* end of test_crypto_hash.c */