GNUnet 0.21.0
crypto_hash.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2013 GNUnet e.V.
4
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
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19
20 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "benchmark.h"
30#include <gcrypt.h>
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-hash", __VA_ARGS__)
33
34#define LOG_STRERROR_FILE(kind, syscall, \
35 filename) GNUNET_log_from_strerror_file (kind, \
36 "util-crypto-hash", \
37 syscall, \
38 filename)
39
40void
41GNUNET_CRYPTO_hash (const void *block,
42 size_t size,
43 struct GNUNET_HashCode *ret)
44{
45 BENCHMARK_START (hash);
46 gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size);
47 BENCHMARK_END (hash);
48}
49
50
51/* ***************** binary-ASCII encoding *************** */
52
53
54void
57{
58 char *np;
59
60 np = GNUNET_STRINGS_data_to_string ((const unsigned char *) block,
61 sizeof(struct GNUNET_HashCode),
62 (char *) result,
63 sizeof(struct
65 - 1);
66 GNUNET_assert (NULL != np);
67 *np = '\0';
68}
69
70
73 size_t enclen,
74 struct GNUNET_HashCode *result)
75{
76 char upper_enc[enclen + 1];
77 char *up_ptr = upper_enc;
78
80 return GNUNET_SYSERR;
81
82 return GNUNET_STRINGS_string_to_data (upper_enc, enclen,
83 (unsigned char *) result,
84 sizeof(struct GNUNET_HashCode));
85}
86
87
88unsigned int
90 const struct GNUNET_HashCode *b)
91{
92 unsigned int x1 = (a->bits[1] - b->bits[1]) >> 16;
93 unsigned int x2 = (b->bits[1] - a->bits[1]) >> 16;
94
95 return(x1 * x2);
96}
97
98
99void
101 struct GNUNET_HashCode *result)
102{
103 for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(uint32_t)) - 1;
104 i >= 0;
105 i--)
106 result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, UINT32_MAX);
107}
108
109
110void
112 const struct GNUNET_HashCode *b,
113 struct GNUNET_HashCode *result)
114{
115 for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(unsigned int)) - 1;
116 i >= 0;
117 i--)
118 result->bits[i] = b->bits[i] - a->bits[i];
119}
120
121
122void
124 const struct GNUNET_HashCode *delta, struct
126{
127 for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(unsigned int)) - 1;
128 i >= 0;
129 i--)
130 result->bits[i] = delta->bits[i] + a->bits[i];
131}
132
133
134void
136 const struct GNUNET_HashCode *b,
137 struct GNUNET_HashCode *result)
138{
139 const unsigned long long *lla = (const unsigned long long *) a;
140 const unsigned long long *llb = (const unsigned long long *) b;
141 unsigned long long *llr = (unsigned long long *) result;
142
143 GNUNET_static_assert (8 == sizeof (unsigned long long));
144 GNUNET_static_assert (0 == sizeof (*a) % sizeof (unsigned long long));
145
146 for (int i = sizeof (*result) / sizeof (*llr) - 1; i>=0; i--)
147 llr[i] = lla[i] ^ llb[i];
148}
149
150
151void
153 const struct GNUNET_HashCode *hc,
156{
159 skey,
160 sizeof(*skey),
161 "Hash key derivation",
162 strlen ("Hash key derivation"),
163 hc, sizeof(*hc),
164 NULL, 0));
167 iv,
168 sizeof(*iv),
169 "Initialization vector derivation",
170 strlen ("Initialization vector derivation"),
171 hc, sizeof(*hc),
172 NULL, 0));
173}
174
175
176unsigned int
178{
179 const unsigned long long *llp = (const unsigned long long *) h;
180 unsigned int ret = 0;
181 unsigned int i;
182
183 GNUNET_static_assert (8 == sizeof (unsigned long long));
184 GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
185 for (i = 0; i<sizeof (*h) / sizeof (*llp); i++)
186 {
187 if (0LLU != llp[i])
188 break;
189 ret += sizeof (*llp) * 8;
190 }
191 if (ret == 8 * sizeof (*h))
192 return ret;
193 ret += __builtin_clzll (GNUNET_ntohll ((uint64_t) llp[i]));
194 return ret;
195}
196
197
198unsigned int
200{
201 const unsigned long long *llp = (const unsigned long long *) h;
202 unsigned int ret = 0;
203 int i;
204
205 GNUNET_static_assert (8 == sizeof (unsigned long long));
206 GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
207 for (i = sizeof (*h) / sizeof (*llp) - 1; i>=0; i--)
208 {
209 if (0LLU != llp[i])
210 break;
211 ret += sizeof (*llp) * 8;
212 }
213 if (ret == 8 * sizeof (*h))
214 return ret;
215 ret += __builtin_ctzll (GNUNET_ntohll ((uint64_t) llp[i]));
216 return ret;
217}
218
219
220int
222 const struct GNUNET_HashCode *h2)
223{
224 unsigned int *i1;
225 unsigned int *i2;
226
227 i1 = (unsigned int *) h1;
228 i2 = (unsigned int *) h2;
229 for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(unsigned int)) - 1;
230 i >= 0;
231 i--)
232 {
233 if (i1[i] > i2[i])
234 return 1;
235 if (i1[i] < i2[i])
236 return -1;
237 }
238 return 0;
239}
240
241
242int
244 const struct GNUNET_HashCode *h2,
245 const struct GNUNET_HashCode *target)
246{
247 const unsigned long long *l1 = (const unsigned long long *) h1;
248 const unsigned long long *l2 = (const unsigned long long *) h2;
249 const unsigned long long *t = (const unsigned long long *) target;
250
251 GNUNET_static_assert (0 == sizeof (*h1) % sizeof (*l1));
252 for (size_t i = 0; i < sizeof(*h1) / sizeof(*l1); i++)
253 {
254 unsigned long long x1 = l1[i] ^ t[i];
255 unsigned long long x2 = l2[i] ^ t[i];
256
257 if (x1 > x2)
258 return 1;
259 if (x1 < x2)
260 return -1;
261 }
262 return 0;
263}
264
265
266void
269 const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
270 const void *salt, size_t salt_len,
271 ...)
272{
273 va_list argp;
274
275 va_start (argp,
276 salt_len);
278 rkey,
279 salt, salt_len,
280 argp);
281 va_end (argp);
282}
283
284
285void
288 const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
289 const void *salt, size_t salt_len,
290 va_list argp)
291{
292 GNUNET_CRYPTO_kdf_v (key->key, sizeof(key->key),
293 salt, salt_len,
294 rkey, sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
295 argp);
296}
297
298
299void
300GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len,
301 const void *plaintext, size_t plaintext_len,
302 struct GNUNET_HashCode *hmac)
303{
304 static int once;
305 static gcry_md_hd_t md;
306 const unsigned char *mc;
307
308 if (! once)
309 {
310 once = 1;
311 GNUNET_assert (GPG_ERR_NO_ERROR ==
312 gcry_md_open (&md,
313 GCRY_MD_SHA512,
314 GCRY_MD_FLAG_HMAC));
315 }
316 else
317 {
318 gcry_md_reset (md);
319 }
320 GNUNET_assert (GPG_ERR_NO_ERROR ==
321 gcry_md_setkey (md, key, key_len));
322 gcry_md_write (md, plaintext, plaintext_len);
323 mc = gcry_md_read (md, GCRY_MD_SHA512);
324 GNUNET_assert (NULL != mc);
325 GNUNET_memcpy (hmac->bits, mc, sizeof(hmac->bits));
326}
327
328
329void
331 const void *plaintext, size_t plaintext_len,
332 struct GNUNET_HashCode *hmac)
333{
334 GNUNET_CRYPTO_hmac_raw ((void *) key->key, sizeof(key->key),
335 plaintext, plaintext_len,
336 hmac);
337}
338
339
341{
345 gcry_md_hd_t hd;
346};
347
348
349struct GNUNET_HashContext *
351{
352 struct GNUNET_HashContext *hc;
353
354 BENCHMARK_START (hash_context_start);
355 hc = GNUNET_new (struct GNUNET_HashContext);
356 GNUNET_assert (0 ==
357 gcry_md_open (&hc->hd,
358 GCRY_MD_SHA512,
359 0));
360 BENCHMARK_END (hash_context_start);
361 return hc;
362}
363
364
365void
367 const void *buf,
368 size_t size)
369{
370 BENCHMARK_START (hash_context_read);
371 gcry_md_write (hc->hd, buf, size);
372 BENCHMARK_END (hash_context_read);
373}
374
375
376struct GNUNET_HashContext *
378{
379 struct GNUNET_HashContext *cp;
380
381 cp = GNUNET_new (struct GNUNET_HashContext);
382 GNUNET_assert (0 ==
383 gcry_md_copy (&cp->hd,
384 hc->hd));
385 return cp;
386}
387
388
389void
391 struct GNUNET_HashCode *r_hash)
392{
393 const void *res = gcry_md_read (hc->hd, 0);
394
395 BENCHMARK_START (hash_context_finish);
396
397 GNUNET_assert (NULL != res);
398 if (NULL != r_hash)
399 GNUNET_memcpy (r_hash,
400 res,
401 sizeof(struct GNUNET_HashCode));
403 BENCHMARK_END (hash_context_finish);
404}
405
406
407void
409{
410 gcry_md_close (hc->hd);
411 GNUNET_free (hc);
412}
413
414
415/* end of crypto_hash.c */
benchmarking for various operations
#define BENCHMARK_START(opname)
Definition: benchmark.h:57
#define BENCHMARK_END(opname)
Definition: benchmark.h:58
static int once
Global to mark if we've run the initialization.
Definition: gnsrecord.c:67
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static int ret
Final status code.
Definition: gnunet-arm.c:94
struct GNUNET_HashCode key
The key used in the DHT.
static OpusEncoder * enc
OPUS encoder.
static char * res
Currently read line or NULL on EOF.
static struct GNUNET_TESTBED_Controller * mc
Handle to the master controller.
static int result
Global testing status.
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
Definition: gnunet-scrypt.c:34
static struct GNUNET_SCHEDULER_Task * t
Main task.
static enum @44 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
GNUNET_CRYPTO_Quality
Desired quality level for random numbers.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
void GNUNET_CRYPTO_hash_difference(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result)
compute result = b - a
Definition: crypto_hash.c:111
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CRYPTO_hash_to_enc(const struct GNUNET_HashCode *block, struct GNUNET_CRYPTO_HashAsciiEncoded *result)
Convert hash to ASCII encoding.
Definition: crypto_hash.c:55
void GNUNET_CRYPTO_hash_create_random(enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result)
Create a random hash code.
Definition: crypto_hash.c:100
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
Definition: crypto_hash.c:330
void GNUNET_CRYPTO_hash_sum(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *delta, struct GNUNET_HashCode *result)
compute result = a + delta
Definition: crypto_hash.c:123
void GNUNET_CRYPTO_hash_xor(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result)
compute result = a ^ b
Definition: crypto_hash.c:135
int GNUNET_CRYPTO_hash_xorcmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2, const struct GNUNET_HashCode *target)
Find out which of the two GNUNET_CRYPTO_hash codes is closer to target in the XOR metric (Kademlia).
Definition: crypto_hash.c:243
void GNUNET_CRYPTO_hmac_derive_key_v(struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len, va_list argp)
Derive an authentication key.
Definition: crypto_hash.c:286
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hash_from_string2(const char *enc, size_t enclen, struct GNUNET_HashCode *result)
Convert ASCII encoding back to a 'struct GNUNET_HashCode'.
Definition: crypto_hash.c:72
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
Definition: crypto_hash.c:221
unsigned int GNUNET_CRYPTO_hash_distance_u32(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b)
Compute the distance between 2 hashcodes.
Definition: crypto_hash.c:89
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:70
void GNUNET_CRYPTO_hmac_derive_key(struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len,...)
Derive an authentication key.
Definition: crypto_hash.c:267
void GNUNET_CRYPTO_hash_to_aes_key(const struct GNUNET_HashCode *hc, struct GNUNET_CRYPTO_SymmetricSessionKey *skey, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
Convert a hashcode into a key.
Definition: crypto_hash.c:152
unsigned int GNUNET_CRYPTO_hash_count_leading_zeros(const struct GNUNET_HashCode *h)
Count the number of leading 0 bits in h.
Definition: crypto_hash.c:177
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
Definition: crypto_hash.c:366
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_copy(const struct GNUNET_HashContext *hc)
Make a copy of the hash computation.
Definition: crypto_hash.c:377
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf_v(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len, va_list argp)
Derive key.
Definition: crypto_kdf.c:38
void GNUNET_CRYPTO_hash_context_abort(struct GNUNET_HashContext *hc)
Abort hashing, do not bother calculating final result.
Definition: crypto_hash.c:408
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:390
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
unsigned int GNUNET_CRYPTO_hash_count_tailing_zeros(const struct GNUNET_HashCode *h)
Count the number of tailing 0 bits in h.
Definition: crypto_hash.c:199
GNUNET_GenericReturnValue
Named constants for return values.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start()
Start incremental hashing operation.
Definition: crypto_hash.c:350
void GNUNET_CRYPTO_hmac_raw(const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104) TODO: Shouldn't this be the standard hmac function and the abo...
Definition: crypto_hash.c:300
#define GNUNET_static_assert(cond)
Assertion to be checked (if supported by C compiler) at compile time, otherwise checked at runtime an...
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using CrockfordBase32.
Definition: strings.c:709
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:472
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:789
static unsigned int size
Size of the "table".
Definition: peer.c:68
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
type for (message) authentication keys
0-terminated ASCII encoding of a struct GNUNET_HashCode.
A 512-bit hashcode.
uint32_t bits[512/8/sizeof(uint32_t)]
gcry_md_hd_t hd
Internal state of the hash function.
Definition: crypto_hash.c:345