2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
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 2, or (at your
8 option) any later version.
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.
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.
20 SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com>
22 Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
23 Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
24 Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
28 * @file util/crypto_hash.c
29 * @brief SHA-512 GNUNET_CRYPTO_hash related functions
30 * @author Christian Grothoff
34 #include "gnunet_common.h"
35 #include "gnunet_crypto_lib.h"
36 #include "gnunet_disk_lib.h"
38 #define SHA512_DIGEST_SIZE 64
39 #define SHA512_HMAC_BLOCK_SIZE 128
43 unsigned long long state[8];
44 unsigned int count[4];
45 unsigned char buf[128];
48 static unsigned long long
49 Ch (unsigned long long x, unsigned long long y, unsigned long long z)
51 return z ^ (x & (y ^ z));
54 static unsigned long long
55 Maj (unsigned long long x, unsigned long long y, unsigned long long z)
57 return (x & y) | (z & (x | y));
60 static unsigned long long
61 RORu64 (unsigned long long x, unsigned long long y)
63 return (x >> y) | (x << (64 - y));
66 #define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
67 #define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
68 #define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
69 #define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
71 /* H* initial state for SHA-512 */
72 #define H0 0x6a09e667f3bcc908ULL
73 #define H1 0xbb67ae8584caa73bULL
74 #define H2 0x3c6ef372fe94f82bULL
75 #define H3 0xa54ff53a5f1d36f1ULL
76 #define H4 0x510e527fade682d1ULL
77 #define H5 0x9b05688c2b3e6c1fULL
78 #define H6 0x1f83d9abfb41bd6bULL
79 #define H7 0x5be0cd19137e2179ULL
81 /* H'* initial state for SHA-384 */
82 #define HP0 0xcbbb9d5dc1059ed8ULL
83 #define HP1 0x629a292a367cd507ULL
84 #define HP2 0x9159015a3070dd17ULL
85 #define HP3 0x152fecd8f70e5939ULL
86 #define HP4 0x67332667ffc00b31ULL
87 #define HP5 0x8eb44a8768581511ULL
88 #define HP6 0xdb0c2e0d64f98fa7ULL
89 #define HP7 0x47b5481dbefa4fa4ULL
91 #define LOAD_OP(t1, I, W, input) \
92 t1 = input[(8*I) ] & 0xff;\
94 t1 |= input[(8*I)+1] & 0xff;\
96 t1 |= input[(8*I)+2] & 0xff;\
98 t1 |= input[(8*I)+3] & 0xff;\
100 t1 |= input[(8*I)+4] & 0xff;\
102 t1 |= input[(8*I)+5] & 0xff;\
104 t1 |= input[(8*I)+6] & 0xff;\
106 t1 |= input[(8*I)+7] & 0xff;\
110 #define BLEND_OP(I, W) \
111 W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
114 sha512_transform (unsigned long long *state, const unsigned char *input)
116 static const unsigned long long sha512_K[80] = {
117 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
118 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
119 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
120 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
121 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
122 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
123 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
124 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
125 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
126 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
127 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
128 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
129 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
130 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
131 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
132 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
133 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
134 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
135 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
136 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
137 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
138 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
139 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
140 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
141 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
142 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
143 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
146 unsigned long long a, b, c, d, e, f, g, h, t1, t2;
147 unsigned long long W[80];
148 unsigned long long t0;
152 for (i = 0; i < 16; i++)
154 LOAD_OP (t0, i, W, input);
157 for (i = 16; i < 80; i++)
162 /* load the state into our registers */
173 for (i = 0; i < 80; i += 8)
175 t1 = h + e1 (e) + Ch (e, f, g) + sha512_K[i] + W[i];
176 t2 = e0 (a) + Maj (a, b, c);
179 t1 = g + e1 (d) + Ch (d, e, f) + sha512_K[i + 1] + W[i + 1];
180 t2 = e0 (h) + Maj (h, a, b);
183 t1 = f + e1 (c) + Ch (c, d, e) + sha512_K[i + 2] + W[i + 2];
184 t2 = e0 (g) + Maj (g, h, a);
187 t1 = e + e1 (b) + Ch (b, c, d) + sha512_K[i + 3] + W[i + 3];
188 t2 = e0 (f) + Maj (f, g, h);
191 t1 = d + e1 (a) + Ch (a, b, c) + sha512_K[i + 4] + W[i + 4];
192 t2 = e0 (e) + Maj (e, f, g);
195 t1 = c + e1 (h) + Ch (h, a, b) + sha512_K[i + 5] + W[i + 5];
196 t2 = e0 (d) + Maj (d, e, f);
199 t1 = b + e1 (g) + Ch (g, h, a) + sha512_K[i + 6] + W[i + 6];
200 t2 = e0 (c) + Maj (c, d, e);
203 t1 = a + e1 (f) + Ch (f, g, h) + sha512_K[i + 7] + W[i + 7];
204 t2 = e0 (b) + Maj (b, c, d);
220 sha512_init (struct sha512_ctx *sctx)
230 sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
231 memset (sctx->buf, 0, sizeof (sctx->buf));
235 sha512_update (struct sha512_ctx *sctx,
236 const unsigned char *data, unsigned int len)
238 unsigned int i, index, part_len;
240 /* Compute number of bytes mod 128 */
241 index = (unsigned int) ((sctx->count[0] >> 3) & 0x7F);
243 /* Update number of bits */
244 if ((sctx->count[0] += (len << 3)) < (len << 3))
246 if ((sctx->count[1] += 1) < 1)
247 if ((sctx->count[2] += 1) < 1)
249 sctx->count[1] += (len >> 29);
252 part_len = 128 - index;
254 /* Transform as many times as possible. */
257 memcpy (&sctx->buf[index], data, part_len);
258 sha512_transform (sctx->state, sctx->buf);
260 for (i = part_len; i + 127 < len; i += 128)
261 sha512_transform (sctx->state, &data[i]);
270 /* Buffer remaining input */
271 memcpy (&sctx->buf[index], &data[i], len - i);
275 sha512_final (struct sha512_ctx *sctx, unsigned char *hash)
277 static unsigned char padding[128] = { 0x80, };
280 unsigned char bits[128];
282 unsigned int pad_len;
283 unsigned long long t2;
286 /* Save number of bits */
320 /* Pad out to 112 mod 128. */
321 index = (sctx->count[0] >> 3) & 0x7f;
322 pad_len = (index < 112) ? (112 - index) : ((128 + 112) - index);
323 sha512_update (sctx, padding, pad_len);
325 /* Append length (before padding) */
326 sha512_update (sctx, bits, 16);
328 /* Store state in digest */
329 for (i = j = 0; i < 8; i++, j += 8)
332 hash[j + 7] = (char) t2 & 0xff;
334 hash[j + 6] = (char) t2 & 0xff;
336 hash[j + 5] = (char) t2 & 0xff;
338 hash[j + 4] = (char) t2 & 0xff;
340 hash[j + 3] = (char) t2 & 0xff;
342 hash[j + 2] = (char) t2 & 0xff;
344 hash[j + 1] = (char) t2 & 0xff;
346 hash[j] = (char) t2 & 0xff;
349 /* Zeroize sensitive information. */
350 memset (sctx, 0, sizeof (struct sha512_ctx));
355 * Hash block of given size.
357 * @param block the data to GNUNET_CRYPTO_hash, length is given as a second argument
358 * @param size the length of the data to GNUNET_CRYPTO_hash
359 * @param ret pointer to where to write the hashcode
362 GNUNET_CRYPTO_hash (const void *block, size_t size, GNUNET_HashCode * ret)
364 struct sha512_ctx ctx;
367 sha512_update (&ctx, block, size);
368 sha512_final (&ctx, (unsigned char *) ret);
373 * Context used when hashing a file.
375 struct GNUNET_CRYPTO_FileHashContext
379 * Function to call upon completion.
381 GNUNET_CRYPTO_HashCompletedCallback callback;
384 * Closure for callback.
391 unsigned char *buffer;
394 * Name of the file we are hashing.
401 struct GNUNET_DISK_FileHandle *fh;
406 struct GNUNET_SCHEDULER_Handle *sched;
411 struct sha512_ctx hctx;
424 * Current task for hashing.
426 GNUNET_SCHEDULER_TaskIdentifier task;
437 * Report result of hash computation to callback
438 * and free associated resources.
441 file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc,
442 const GNUNET_HashCode * res)
444 fhc->callback (fhc->callback_cls, res);
445 GNUNET_free (fhc->filename);
446 if (!GNUNET_DISK_handle_invalid (fhc->fh))
447 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh));
448 GNUNET_free (fhc); /* also frees fhc->buffer */
459 file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
461 struct GNUNET_CRYPTO_FileHashContext *fhc = cls;
465 fhc->task = GNUNET_SCHEDULER_NO_TASK;
466 GNUNET_assert (fhc->offset < fhc->fsize);
468 if (fhc->fsize - fhc->offset < delta)
469 delta = fhc->fsize - fhc->offset;
470 if (delta != GNUNET_DISK_file_read (fhc->fh, fhc->buffer, delta))
472 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
473 "read", fhc->filename);
474 file_hash_finish (fhc, NULL);
477 sha512_update (&fhc->hctx, fhc->buffer, delta);
478 fhc->offset += delta;
479 if (fhc->offset == fhc->fsize)
481 sha512_final (&fhc->hctx, (unsigned char *) &res);
482 file_hash_finish (fhc, &res);
486 = GNUNET_SCHEDULER_add_after (tc->sched,
487 GNUNET_SCHEDULER_NO_TASK,
488 &file_hash_task, fhc);
493 * Compute the hash of an entire file.
495 * @param sched scheduler to use
496 * @param priority scheduling priority to use
497 * @param filename name of file to hash
498 * @param blocksize number of bytes to process in one task
499 * @param callback function to call upon completion
500 * @param callback_cls closure for callback
501 * @return NULL on (immediate) errror
503 struct GNUNET_CRYPTO_FileHashContext *
504 GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched,
505 enum GNUNET_SCHEDULER_Priority priority,
506 const char *filename,
508 GNUNET_CRYPTO_HashCompletedCallback callback,
511 struct GNUNET_CRYPTO_FileHashContext *fhc;
513 GNUNET_assert (blocksize > 0);
514 fhc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize);
515 fhc->callback = callback;
516 fhc->callback_cls = callback_cls;
518 fhc->buffer = (unsigned char *) &fhc[1];
519 fhc->filename = GNUNET_strdup (filename);
521 sha512_init (&fhc->hctx);
522 fhc->bsize = blocksize;
523 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO))
525 GNUNET_free (fhc->filename);
529 fhc->fh = GNUNET_DISK_file_open (filename,
530 GNUNET_DISK_OPEN_READ,
531 GNUNET_DISK_PERM_NONE);
534 GNUNET_free (fhc->filename);
539 = GNUNET_SCHEDULER_add_with_priority (sched, priority,
540 &file_hash_task, fhc);
546 * Cancel a file hashing operation.
548 * @param fhc operation to cancel (callback must not yet have been invoked)
551 GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc)
553 GNUNET_SCHEDULER_cancel (fhc->sched,
555 GNUNET_free (fhc->filename);
556 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh));
562 /* ***************** binary-ASCII encoding *************** */
565 getValue__ (unsigned char a)
567 if ((a >= '0') && (a <= '9'))
569 if ((a >= 'A') && (a <= 'V'))
570 return (a - 'A' + 10);
575 * Convert GNUNET_CRYPTO_hash to ASCII encoding. The ASCII encoding is rather
576 * GNUnet specific. It was chosen such that it only uses characters
577 * in [0-9A-V], can be produced without complex arithmetics and uses a
578 * small number of characters. The GNUnet encoding uses 102
579 * characters plus a null terminator.
581 * @param block the hash code
582 * @param result where to store the encoding (struct GNUNET_CRYPTO_HashAsciiEncoded can be
583 * safely cast to char*, a '\\0' termination is set).
586 GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block,
587 struct GNUNET_CRYPTO_HashAsciiEncoded *result)
590 * 32 characters for encoding (GNUNET_CRYPTO_hash => 32 characters)
592 static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
598 GNUNET_assert (block != NULL);
599 GNUNET_assert (result != NULL);
604 while ((rpos < sizeof (GNUNET_HashCode)) || (vbit > 0))
606 if ((rpos < sizeof (GNUNET_HashCode)) && (vbit < 5))
608 bits = (bits << 8) | ((unsigned char *) block)[rpos++]; /* eat 8 more bits */
613 bits <<= (5 - vbit); /* zero-padding */
614 GNUNET_assert (vbit == 2); /* padding by 3: 512+3 mod 5 == 0 */
617 GNUNET_assert (wpos <
618 sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1);
619 result->encoding[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
622 GNUNET_assert (wpos == sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1);
623 GNUNET_assert (vbit == 0);
624 result->encoding[wpos] = '\0';
628 * Convert ASCII encoding back to GNUNET_CRYPTO_hash
630 * @param enc the encoding
631 * @param result where to store the GNUNET_CRYPTO_hash code
632 * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding
635 GNUNET_CRYPTO_hash_from_string (const char *enc, GNUNET_HashCode * result)
642 if (strlen (enc) != sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1)
643 return GNUNET_SYSERR;
645 vbit = 2; /* padding! */
646 wpos = sizeof (GNUNET_HashCode);
647 rpos = sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1;
648 bits = getValue__ (enc[--rpos]) >> 3;
651 GNUNET_assert (rpos > 0);
652 bits = (getValue__ (enc[--rpos]) << vbit) | bits;
656 ((unsigned char *) result)[--wpos] = (unsigned char) bits;
661 GNUNET_assert (rpos == 0);
662 GNUNET_assert (vbit == 0);
667 * Compute the distance between 2 hashcodes. The computation must be
668 * fast, not involve bits[0] or bits[4] (they're used elsewhere), and be
669 * somewhat consistent. And of course, the result should be a positive
672 * @param a some hash code
673 * @param b some hash code
674 * @return a positive number which is a measure for
675 * hashcode proximity.
678 GNUNET_CRYPTO_hash_distance_u32 (const GNUNET_HashCode * a,
679 const GNUNET_HashCode * b)
681 unsigned int x1 = (a->bits[1] - b->bits[1]) >> 16;
682 unsigned int x2 = (b->bits[1] - a->bits[1]) >> 16;
687 GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode,
688 GNUNET_HashCode * result)
691 for (i = (sizeof (GNUNET_HashCode) / sizeof (uint32_t)) - 1; i >= 0; i--)
692 result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, UINT32_MAX);
696 GNUNET_CRYPTO_hash_difference (const GNUNET_HashCode * a,
697 const GNUNET_HashCode * b,
698 GNUNET_HashCode * result)
701 for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;
703 result->bits[i] = b->bits[i] - a->bits[i];
707 GNUNET_CRYPTO_hash_sum (const GNUNET_HashCode * a,
708 const GNUNET_HashCode * delta,
709 GNUNET_HashCode * result)
712 for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;
714 result->bits[i] = delta->bits[i] + a->bits[i];
718 GNUNET_CRYPTO_hash_xor (const GNUNET_HashCode * a,
719 const GNUNET_HashCode * b, GNUNET_HashCode * result)
722 for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;
724 result->bits[i] = a->bits[i] ^ b->bits[i];
728 * Convert a hashcode into a key.
731 GNUNET_CRYPTO_hash_to_aes_key (const GNUNET_HashCode * hc,
732 struct GNUNET_CRYPTO_AesSessionKey *skey,
733 struct GNUNET_CRYPTO_AesInitializationVector
736 GNUNET_assert (sizeof (GNUNET_HashCode) >=
737 GNUNET_CRYPTO_AES_KEY_LENGTH +
738 sizeof (struct GNUNET_CRYPTO_AesInitializationVector));
739 memcpy (skey, hc, GNUNET_CRYPTO_AES_KEY_LENGTH);
741 htonl (GNUNET_CRYPTO_crc32_n (skey, GNUNET_CRYPTO_AES_KEY_LENGTH));
742 memcpy (iv, &((char *) hc)[GNUNET_CRYPTO_AES_KEY_LENGTH],
743 sizeof (struct GNUNET_CRYPTO_AesInitializationVector));
747 * Obtain a bit from a hashcode.
748 * @param code the GNUNET_CRYPTO_hash to index bit-wise
749 * @param bit index into the hashcode, [0...511]
750 * @return Bit \a bit from hashcode \a code, -1 for invalid index
753 GNUNET_CRYPTO_hash_get_bit (const GNUNET_HashCode * code, unsigned int bit)
755 GNUNET_assert (bit < 8 * sizeof (GNUNET_HashCode));
756 return (((unsigned char *) code)[bit >> 3] & (1 << (bit & 7))) > 0;
760 * Determine how many low order bits match in two
761 * GNUNET_HashCodes. i.e. - 010011 and 011111 share
762 * the first two lowest order bits, and therefore the
763 * return value is two (NOT XOR distance, nor how many
764 * bits match absolutely!).
766 * @param first the first hashcode
767 * @param second the hashcode to compare first to
769 * @return the number of bits that match
771 unsigned int GNUNET_CRYPTO_hash_matching_bits(const GNUNET_HashCode *first, const GNUNET_HashCode *second)
775 for (i = 0; i < sizeof (GNUNET_HashCode) * 8; i++)
776 if (GNUNET_CRYPTO_hash_get_bit (first, i) != GNUNET_CRYPTO_hash_get_bit (second, i))
778 return sizeof (GNUNET_HashCode) * 8;
782 * Compare function for HashCodes, producing a total ordering
784 * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.
787 GNUNET_CRYPTO_hash_cmp (const GNUNET_HashCode * h1,
788 const GNUNET_HashCode * h2)
794 i1 = (unsigned int *) h1;
795 i2 = (unsigned int *) h2;
796 for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0;
808 * Find out which of the two GNUNET_CRYPTO_hash codes is closer to target
809 * in the XOR metric (Kademlia).
810 * @return -1 if h1 is closer, 1 if h2 is closer and 0 if h1==h2.
813 GNUNET_CRYPTO_hash_xorcmp (const GNUNET_HashCode * h1,
814 const GNUNET_HashCode * h2,
815 const GNUNET_HashCode * target)
821 for (i = sizeof (GNUNET_HashCode) / sizeof (unsigned int) - 1; i >= 0; i--)
823 d1 = ((unsigned int *) h1)[i] ^ ((unsigned int *) target)[i];
824 d2 = ((unsigned int *) h2)[i] ^ ((unsigned int *) target)[i];
835 * Calculate HMAC of a message (RFC 2104)
837 * @param key secret key
838 * @param plaintext input plaintext
839 * @param plaintext_len length of plaintext
840 * @param hmac where to store the hmac
843 GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AesSessionKey *key,
844 const void *plaintext,
845 size_t plaintext_len,
846 GNUNET_HashCode *hmac)
849 GNUNET_HashCode ipad;
850 GNUNET_HashCode opad;
852 struct sha512_ctx sctx;
854 memset (&kh, 0, sizeof (kh));
855 GNUNET_assert (sizeof (GNUNET_HashCode) > sizeof (struct GNUNET_CRYPTO_AesSessionKey));
856 memcpy (&kh, key, sizeof (struct GNUNET_CRYPTO_AesSessionKey));
857 memset (&ipad, 0x5c, sizeof (ipad));
858 memset (&opad, 0x36, sizeof (opad));
859 GNUNET_CRYPTO_hash_xor (&ipad, &kh, &ipad);
860 GNUNET_CRYPTO_hash_xor (&opad, &kh, &opad);
862 sha512_update (&sctx, (const unsigned char*) &ipad, sizeof (ipad));
863 sha512_update (&sctx, plaintext, plaintext_len);
864 sha512_final (&sctx, (unsigned char*) &him);
866 sha512_update (&sctx, (const unsigned char*) &opad, sizeof (opad));
867 sha512_update (&sctx, (const unsigned char*) &him, sizeof (him));
868 sha512_final (&sctx, (unsigned char*) hmac);
872 /* end of crypto_hash.c */