-fix ftbfs
[oweals/gnunet.git] / src / util / crypto_hash.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19
20 */
21 /**
22  * @file util/crypto_hash.c
23  * @brief SHA-512 #GNUNET_CRYPTO_hash() related functions
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include <gcrypt.h>
29
30 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
31
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33
34 /**
35  * Hash block of given size.
36  *
37  * @param block the data to #GNUNET_CRYPTO_hash, length is given as a second argument
38  * @param size the length of the data to #GNUNET_CRYPTO_hash in @a block
39  * @param ret pointer to where to write the hashcode
40  */
41 void
42 GNUNET_CRYPTO_hash (const void *block,
43                     size_t size,
44                     struct GNUNET_HashCode *ret)
45 {
46   gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size);
47 }
48
49
50 /* ***************** binary-ASCII encoding *************** */
51
52
53 /**
54  * Convert GNUNET_CRYPTO_hash to ASCII encoding.  The ASCII encoding is rather
55  * GNUnet specific.  It was chosen such that it only uses characters
56  * in [0-9A-V], can be produced without complex arithmetics and uses a
57  * small number of characters.  The GNUnet encoding uses 103
58  * characters plus a null terminator.
59  *
60  * @param block the hash code
61  * @param result where to store the encoding (struct GNUNET_CRYPTO_HashAsciiEncoded can be
62  *  safely cast to char*, a '\\0' termination is set).
63  */
64 void
65 GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode *block,
66                            struct GNUNET_CRYPTO_HashAsciiEncoded *result)
67 {
68   char *np;
69
70   np = GNUNET_STRINGS_data_to_string ((const unsigned char *) block,
71                                       sizeof (struct GNUNET_HashCode),
72                                       (char*) result,
73                                       sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1);
74   GNUNET_assert (NULL != np);
75   *np = '\0';
76 }
77
78
79 /**
80  * Convert ASCII encoding back to hash code.
81  *
82  * @param enc the encoding
83  * @param enclen number of characters in @a enc (without 0-terminator, which can be missing)
84  * @param result where to store the hash code
85  * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
86  */
87 int
88 GNUNET_CRYPTO_hash_from_string2 (const char *enc,
89                                  size_t enclen,
90                                  struct GNUNET_HashCode *result)
91 {
92   char upper_enc[enclen];
93   char *up_ptr = upper_enc;
94
95   GNUNET_STRINGS_utf8_toupper (enc, up_ptr);
96
97   return GNUNET_STRINGS_string_to_data (upper_enc, enclen,
98                                         (unsigned char*) result,
99                                         sizeof (struct GNUNET_HashCode));
100 }
101
102
103 /**
104  * @ingroup hash
105  *
106  * Compute the distance between 2 hashcodes.  The computation must be
107  * fast, not involve bits[0] or bits[4] (they're used elsewhere), and be
108  * somewhat consistent. And of course, the result should be a positive
109  * number.
110  *
111  * @param a some hash code
112  * @param b some hash code
113  * @return a positive number which is a measure for
114  *  hashcode proximity.
115  */
116 unsigned int
117 GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode *a,
118                                  const struct GNUNET_HashCode *b)
119 {
120   unsigned int x1 = (a->bits[1] - b->bits[1]) >> 16;
121   unsigned int x2 = (b->bits[1] - a->bits[1]) >> 16;
122
123   return (x1 * x2);
124 }
125
126
127 /**
128  * Create a random hash code.
129  *
130  * @param mode desired quality level
131  * @param result hash code that is randomized
132  */
133 void
134 GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode,
135                                   struct GNUNET_HashCode *result)
136 {
137   int i;
138
139   for (i = (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t)) - 1; i >= 0; i--)
140     result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, UINT32_MAX);
141 }
142
143
144 /**
145  * compute result(delta) = b - a
146  *
147  * @param a some hash code
148  * @param b some hash code
149  * @param result set to b - a
150  */
151 void
152 GNUNET_CRYPTO_hash_difference (const struct GNUNET_HashCode *a,
153                                const struct GNUNET_HashCode *b,
154                                struct GNUNET_HashCode *result)
155 {
156   int i;
157
158   for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--)
159     result->bits[i] = b->bits[i] - a->bits[i];
160 }
161
162
163 /**
164  * compute result(b) = a + delta
165  *
166  * @param a some hash code
167  * @param delta some hash code
168  * @param result set to a + delta
169  */
170 void
171 GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode * a,
172                         const struct GNUNET_HashCode * delta, struct GNUNET_HashCode * result)
173 {
174   int i;
175
176   for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--)
177     result->bits[i] = delta->bits[i] + a->bits[i];
178 }
179
180
181 /**
182  * compute result = a ^ b
183  *
184  * @param a some hash code
185  * @param b some hash code
186  * @param result set to a ^ b
187  */
188 void
189 GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a,
190                         const struct GNUNET_HashCode *b,
191                         struct GNUNET_HashCode *result)
192 {
193   int i;
194
195   for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--)
196     result->bits[i] = a->bits[i] ^ b->bits[i];
197 }
198
199
200 /**
201  * Convert a hashcode into a key.
202  *
203  * @param hc hash code that serves to generate the key
204  * @param skey set to a valid session key
205  * @param iv set to a valid initialization vector
206  */
207 void
208 GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc,
209                                struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
210                                struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
211 {
212   GNUNET_assert (GNUNET_YES ==
213                  GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
214                                     "Hash key derivation", strlen ("Hash key derivation"),
215                                     hc, sizeof (struct GNUNET_HashCode),
216                                     NULL, 0));
217   GNUNET_assert (GNUNET_YES ==
218                  GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
219                                     "Initialization vector derivation", strlen ("Initialization vector derivation"),
220                                     hc, sizeof (struct GNUNET_HashCode),
221                                     NULL, 0));
222 }
223
224
225 /**
226  * Obtain a bit from a hashcode.
227  * @param code the GNUNET_CRYPTO_hash to index bit-wise
228  * @param bit index into the hashcode, [0...511]
229  * @return Bit \a bit from hashcode \a code, -1 for invalid index
230  */
231 int
232 GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode * code, unsigned int bit)
233 {
234   GNUNET_assert (bit < 8 * sizeof (struct GNUNET_HashCode));
235   return (((unsigned char *) code)[bit >> 3] & (1 << (bit & 7))) > 0;
236 }
237
238
239 /**
240  * Determine how many low order bits match in two
241  * `struct GNUNET_HashCode`s.  i.e. - 010011 and 011111 share
242  * the first two lowest order bits, and therefore the
243  * return value is two (NOT XOR distance, nor how many
244  * bits match absolutely!).
245  *
246  * @param first the first hashcode
247  * @param second the hashcode to compare first to
248  *
249  * @return the number of bits that match
250  */
251 unsigned int
252 GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode * first,
253                                   const struct GNUNET_HashCode * second)
254 {
255   unsigned int i;
256
257   for (i = 0; i < sizeof (struct GNUNET_HashCode) * 8; i++)
258     if (GNUNET_CRYPTO_hash_get_bit (first, i) !=
259         GNUNET_CRYPTO_hash_get_bit (second, i))
260       return i;
261   return sizeof (struct GNUNET_HashCode) * 8;
262 }
263
264
265 /**
266  * Compare function for HashCodes, producing a total ordering
267  * of all hashcodes.
268  *
269  * @param h1 some hash code
270  * @param h2 some hash code
271  * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.
272  */
273 int
274 GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode *h1,
275                         const struct GNUNET_HashCode *h2)
276 {
277   unsigned int *i1;
278   unsigned int *i2;
279   int i;
280
281   i1 = (unsigned int *) h1;
282   i2 = (unsigned int *) h2;
283   for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--)
284   {
285     if (i1[i] > i2[i])
286       return 1;
287     if (i1[i] < i2[i])
288       return -1;
289   }
290   return 0;
291 }
292
293
294 /**
295  * Find out which of the two `struct GNUNET_HashCode`s is closer to target
296  * in the XOR metric (Kademlia).
297  *
298  * @param h1 some hash code
299  * @param h2 some hash code
300  * @param target some hash code
301  * @return -1 if h1 is closer, 1 if h2 is closer and 0 if h1==h2.
302  */
303 int
304 GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1,
305                            const struct GNUNET_HashCode *h2,
306                            const struct GNUNET_HashCode *target)
307 {
308   int i;
309   unsigned int d1;
310   unsigned int d2;
311
312   for (i = sizeof (struct GNUNET_HashCode) / sizeof (unsigned int) - 1; i >= 0; i--)
313   {
314     d1 = ((unsigned int *) h1)[i] ^ ((unsigned int *) target)[i];
315     d2 = ((unsigned int *) h2)[i] ^ ((unsigned int *) target)[i];
316     if (d1 > d2)
317       return 1;
318     else if (d1 < d2)
319       return -1;
320   }
321   return 0;
322 }
323
324
325 /**
326  * @brief Derive an authentication key
327  * @param key authentication key
328  * @param rkey root key
329  * @param salt salt
330  * @param salt_len size of the @a salt
331  * @param ... pair of void * & size_t for context chunks, terminated by NULL
332  */
333 void
334 GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key,
335                                const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
336                                const void *salt, size_t salt_len, ...)
337 {
338   va_list argp;
339
340   va_start (argp, salt_len);
341   GNUNET_CRYPTO_hmac_derive_key_v (key, rkey, salt, salt_len, argp);
342   va_end (argp);
343 }
344
345
346 /**
347  * @brief Derive an authentication key
348  * @param key authentication key
349  * @param rkey root key
350  * @param salt salt
351  * @param salt_len size of the @a salt
352  * @param argp pair of void * & size_t for context chunks, terminated by NULL
353  */
354 void
355 GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key,
356                                  const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey,
357                                  const void *salt, size_t salt_len,
358                                  va_list argp)
359 {
360   GNUNET_CRYPTO_kdf_v (key->key, sizeof (key->key),
361                        salt, salt_len,
362                        rkey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
363                        argp);
364 }
365
366
367 /**
368  * Calculate HMAC of a message (RFC 2104)
369  *
370  * @param key secret key
371  * @param plaintext input plaintext
372  * @param plaintext_len length of @a plaintext
373  * @param hmac where to store the hmac
374  */
375 void
376 GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key,
377                     const void *plaintext, size_t plaintext_len,
378                     struct GNUNET_HashCode *hmac)
379 {
380   static int once;
381   static gcry_md_hd_t md;
382   const unsigned char *mc;
383
384   if (! once)
385   {
386     once = 1;
387     GNUNET_assert (GPG_ERR_NO_ERROR ==
388                    gcry_md_open (&md, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC));
389   }
390   else
391   {
392     gcry_md_reset (md);
393   }
394   gcry_md_setkey (md, key->key, sizeof (key->key));
395   gcry_md_write (md, plaintext, plaintext_len);
396   mc = gcry_md_read (md, GCRY_MD_SHA512);
397   GNUNET_assert (NULL != mc);
398   memcpy (hmac->bits, mc, sizeof (hmac->bits));
399 }
400
401
402 /**
403  * Context for cummulative hashing.
404  */
405 struct GNUNET_HashContext
406 {
407   /**
408    * Internal state of the hash function.
409    */
410   gcry_md_hd_t hd;
411 };
412
413
414 /**
415  * Start incremental hashing operation.
416  *
417  * @return context for incremental hash computation
418  */
419 struct GNUNET_HashContext *
420 GNUNET_CRYPTO_hash_context_start ()
421 {
422   struct GNUNET_HashContext *hc;
423
424   hc = GNUNET_new (struct GNUNET_HashContext);
425   GNUNET_assert (0 ==
426                  gcry_md_open (&hc->hd,
427                                GCRY_MD_SHA512,
428                                0));
429   return hc;
430 }
431
432
433 /**
434  * Add data to be hashed.
435  *
436  * @param hc cummulative hash context
437  * @param buf data to add
438  * @param size number of bytes in @a buf
439  */
440 void
441 GNUNET_CRYPTO_hash_context_read (struct GNUNET_HashContext *hc,
442                          const void *buf,
443                          size_t size)
444 {
445   gcry_md_write (hc->hd, buf, size);
446 }
447
448
449 /**
450  * Finish the hash computation.
451  *
452  * @param hc hash context to use
453  * @param r_hash where to write the latest / final hash code
454  */
455 void
456 GNUNET_CRYPTO_hash_context_finish (struct GNUNET_HashContext *hc,
457                            struct GNUNET_HashCode *r_hash)
458 {
459   const void *res = gcry_md_read (hc->hd, 0);
460
461   GNUNET_assert (NULL != res);
462   if (NULL != r_hash)
463     memcpy (r_hash,
464             res,
465             sizeof (struct GNUNET_HashCode));
466   GNUNET_CRYPTO_hash_context_abort (hc);
467 }
468
469
470 /**
471  * Abort hashing, do not bother calculating final result.
472  *
473  * @param hc hash context to destroy
474  */
475 void
476 GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext *hc)
477 {
478   gcry_md_close (hc->hd);
479   GNUNET_free (hc);
480 }
481
482
483 /* end of crypto_hash.c */