GNUnet  0.17.6
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  */
26 #include "platform.h"
27 #include "gnunet_crypto_lib.h"
28 #include "gnunet_strings_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 
40 void
41 GNUNET_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 
54 void
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];
77  char *up_ptr = upper_enc;
78 
79  if (GNUNET_OK != GNUNET_STRINGS_utf8_toupper (enc, up_ptr))
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 
88 unsigned 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 
99 void
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 
110 void
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 
122 void
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 
134 void
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  for (int i = sizeof (*result) / sizeof (*llr) - 1; i>=0; i--)
146  llr[i] = lla[i] ^ llb[i];
147 }
148 
149 
150 void
152  const struct GNUNET_HashCode *hc,
155 {
158  skey,
159  sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
160  "Hash key derivation",
161  strlen ("Hash key derivation"),
162  hc, sizeof(struct GNUNET_HashCode),
163  NULL, 0));
166  iv,
168  "Initialization vector derivation",
169  strlen ("Initialization vector derivation"),
170  hc, sizeof(struct GNUNET_HashCode),
171  NULL, 0));
172 }
173 
174 
175 unsigned int
177 {
178  const unsigned long long *llp = (const unsigned long long *) h;
179  unsigned int ret = 0;
180  unsigned int i;
181 
182  GNUNET_static_assert (8 == sizeof (unsigned long long));
183  GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
184  for (i = 0; i<sizeof (*h) / sizeof (*llp); i++)
185  {
186  if (0LLU != llp[i])
187  break;
188  ret += sizeof (*llp) * 8;
189  }
190  if (ret == 8 * sizeof (*h))
191  return ret;
192  ret += __builtin_clzll (GNUNET_ntohll ((uint64_t) llp[i]));
193  return ret;
194 }
195 
196 
197 unsigned int
199 {
200  const unsigned long long *llp = (const unsigned long long *) h;
201  unsigned int ret = 0;
202  int i;
203 
204  GNUNET_static_assert (8 == sizeof (unsigned long long));
205  GNUNET_static_assert (0 == sizeof (*h) % sizeof (unsigned long long));
206  for (i = sizeof (*h) / sizeof (*llp) - 1; i>=0; i--)
207  {
208  if (0LLU != llp[i])
209  break;
210  ret += sizeof (*llp) * 8;
211  }
212  if (ret == 8 * sizeof (*h))
213  return ret;
214  ret += __builtin_ctzll (GNUNET_ntohll ((uint64_t) llp[i]));
215  return ret;
216 }
217 
218 
219 int
221  const struct GNUNET_HashCode *h2)
222 {
223  unsigned int *i1;
224  unsigned int *i2;
225 
226  i1 = (unsigned int *) h1;
227  i2 = (unsigned int *) h2;
228  for (ssize_t i = (sizeof(struct GNUNET_HashCode) / sizeof(unsigned int)) - 1;
229  i >= 0;
230  i--)
231  {
232  if (i1[i] > i2[i])
233  return 1;
234  if (i1[i] < i2[i])
235  return -1;
236  }
237  return 0;
238 }
239 
240 
241 int
243  const struct GNUNET_HashCode *h2,
244  const struct GNUNET_HashCode *target)
245 {
246  const unsigned long long *l1 = (const unsigned long long *) h1;
247  const unsigned long long *l2 = (const unsigned long long *) h2;
248  const unsigned long long *t = (const unsigned long long *) target;
249 
250  GNUNET_static_assert (0 == sizeof (*h1) % sizeof (*l1));
251  for (size_t i = 0; i < sizeof(*h1) / sizeof(*l1); i++)
252  {
253  unsigned long long x1 = l1[i] ^ t[i];
254  unsigned long long x2 = l2[i] ^ t[i];
255 
256  if (x1 > x2)
257  return 1;
258  if (x1 < x2)
259  return -1;
260  }
261  return 0;
262 }
263 
264 
265 void
267  struct GNUNET_CRYPTO_AuthKey *key,
268  const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
269  const void *salt, size_t salt_len,
270  ...)
271 {
272  va_list argp;
273 
274  va_start (argp,
275  salt_len);
277  rkey,
278  salt, salt_len,
279  argp);
280  va_end (argp);
281 }
282 
283 
284 void
286  struct GNUNET_CRYPTO_AuthKey *key,
287  const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
288  const void *salt, size_t salt_len,
289  va_list argp)
290 {
291  GNUNET_CRYPTO_kdf_v (key->key, sizeof(key->key),
292  salt, salt_len,
293  rkey, sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
294  argp);
295 }
296 
297 
298 void
299 GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len,
300  const void *plaintext, size_t plaintext_len,
301  struct GNUNET_HashCode *hmac)
302 {
303  static int once;
304  static gcry_md_hd_t md;
305  const unsigned char *mc;
306 
307  if (! once)
308  {
309  once = 1;
310  GNUNET_assert (GPG_ERR_NO_ERROR ==
311  gcry_md_open (&md,
312  GCRY_MD_SHA512,
313  GCRY_MD_FLAG_HMAC));
314  }
315  else
316  {
317  gcry_md_reset (md);
318  }
319  gcry_md_setkey (md, key, key_len);
320  gcry_md_write (md, plaintext, plaintext_len);
321  mc = gcry_md_read (md, GCRY_MD_SHA512);
322  GNUNET_assert (NULL != mc);
323  GNUNET_memcpy (hmac->bits, mc, sizeof(hmac->bits));
324 }
325 
326 
327 void
329  const void *plaintext, size_t plaintext_len,
330  struct GNUNET_HashCode *hmac)
331 {
332  GNUNET_CRYPTO_hmac_raw ((void *) key->key, sizeof(key->key),
333  plaintext, plaintext_len,
334  hmac);
335 }
336 
337 
339 {
343  gcry_md_hd_t hd;
344 };
345 
346 
347 struct GNUNET_HashContext *
349 {
350  struct GNUNET_HashContext *hc;
351 
352  BENCHMARK_START (hash_context_start);
353  hc = GNUNET_new (struct GNUNET_HashContext);
354  GNUNET_assert (0 ==
355  gcry_md_open (&hc->hd,
356  GCRY_MD_SHA512,
357  0));
358  BENCHMARK_END (hash_context_start);
359  return hc;
360 }
361 
362 
363 void
365  const void *buf,
366  size_t size)
367 {
368  BENCHMARK_START (hash_context_read);
369  gcry_md_write (hc->hd, buf, size);
370  BENCHMARK_END (hash_context_read);
371 }
372 
373 
374 struct GNUNET_HashContext *
376 {
377  struct GNUNET_HashContext *cp;
378 
379  cp = GNUNET_new (struct GNUNET_HashContext);
380  GNUNET_assert (0 ==
381  gcry_md_copy (&cp->hd,
382  hc->hd));
383  return cp;
384 }
385 
386 
387 void
389  struct GNUNET_HashCode *r_hash)
390 {
391  const void *res = gcry_md_read (hc->hd, 0);
392 
393  BENCHMARK_START (hash_context_finish);
394 
395  GNUNET_assert (NULL != res);
396  if (NULL != r_hash)
397  GNUNET_memcpy (r_hash,
398  res,
399  sizeof(struct GNUNET_HashCode));
401  BENCHMARK_END (hash_context_finish);
402 }
403 
404 
405 void
407 {
408  gcry_md_close (hc->hd);
409  GNUNET_free (hc);
410 }
411 
412 
413 /* 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:68
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static int res
struct GNUNET_HashCode key
The key used in the DHT.
static OpusEncoder * enc
OPUS encoder.
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.
static char buf[2048]
static struct GNUNET_SCHEDULER_Task * t
Main task.
cryptographic primitives for GNUnet
static enum @8 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
Strings and string handling functions.
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:328
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:242
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:285
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:220
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:69
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:266
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:151
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:176
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start()
Start incremental hashing operation.
Definition: crypto_hash.c:348
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:364
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
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:37
void GNUNET_CRYPTO_hash_context_abort(struct GNUNET_HashContext *hc)
Abort hashing, do not bother calculating final result.
Definition: crypto_hash.c:406
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_copy(const struct GNUNET_HashContext *hc)
Make a copy of the hash computation.
Definition: crypto_hash.c:375
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:388
#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:198
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:96
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:299
#define GNUNET_static_assert(cond)
Assertion to be checked (if supported by C compiler) at compile time, otherwise checked at runtime an...
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#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:67
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
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:343