X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_hash.c;h=af492e15e021ff5d861d7f26df91d561308cbe7c;hb=94f01bdd2fda575769f01f8072689fa6936af8f4;hp=dcee545f79e811b20ff2fc1f0272a8d48e25e9c9;hpb=cf45b8dff29c366d51aa2e6ea6a64b99b514b9c9;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index dcee545f7..af492e15e 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c @@ -63,36 +63,6 @@ RORu64 (unsigned long long x, unsigned long long y) return (x >> y) | (x << (64 - y)); } -const unsigned long long sha512_K[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, - 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, - 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, - 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, - 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, - 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, - 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, - 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, - 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, - 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, - 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, - 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, - 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, - 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, -}; - #define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) #define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) #define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) @@ -143,6 +113,36 @@ const unsigned long long sha512_K[80] = { static void sha512_transform (unsigned long long *state, const unsigned char *input) { + static const unsigned long long sha512_K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, + }; + unsigned long long a, b, c, d, e, f, g, h, t1, t2; unsigned long long W[80]; unsigned long long t0; @@ -372,7 +372,7 @@ GNUNET_CRYPTO_hash (const void *block, size_t size, GNUNET_HashCode * ret) /** * Context used when hashing a file. */ -struct FileHashContext +struct GNUNET_CRYPTO_FileHashContext { /** @@ -396,14 +396,19 @@ struct FileHashContext char *filename; /** - * Cummulated hash. + * File descriptor. */ - struct sha512_ctx hctx; + struct GNUNET_DISK_FileHandle *fh; /** - * Blocksize. + * Our scheduler. */ - size_t bsize; + struct GNUNET_SCHEDULER_Handle *sched; + + /** + * Cummulated hash. + */ + struct sha512_ctx hctx; /** * Size of the file. @@ -416,9 +421,14 @@ struct FileHashContext uint64_t offset; /** - * File descriptor. + * Current task for hashing. */ - struct GNUNET_DISK_FileHandle *fh; + GNUNET_SCHEDULER_TaskIdentifier task; + + /** + * Blocksize. + */ + size_t bsize; }; @@ -428,7 +438,8 @@ struct FileHashContext * and free associated resources. */ static void -file_hash_finish (struct FileHashContext *fhc, const GNUNET_HashCode * res) +file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc, + const GNUNET_HashCode * res) { fhc->callback (fhc->callback_cls, res); GNUNET_free (fhc->filename); @@ -447,10 +458,11 @@ file_hash_finish (struct FileHashContext *fhc, const GNUNET_HashCode * res) static void file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct FileHashContext *fhc = cls; + struct GNUNET_CRYPTO_FileHashContext *fhc = cls; GNUNET_HashCode res; size_t delta; + fhc->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (fhc->offset < fhc->fsize); delta = fhc->bsize; if (fhc->fsize - fhc->offset < delta) @@ -470,8 +482,10 @@ file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) file_hash_finish (fhc, &res); return; } - GNUNET_SCHEDULER_add_after (tc->sched, - GNUNET_SCHEDULER_NO_TASK, &file_hash_task, fhc); + fhc->task + = GNUNET_SCHEDULER_add_after (tc->sched, + GNUNET_SCHEDULER_NO_TASK, + &file_hash_task, fhc); } @@ -484,8 +498,9 @@ file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param blocksize number of bytes to process in one task * @param callback function to call upon completion * @param callback_cls closure for callback + * @return NULL on (immediate) errror */ -void +struct GNUNET_CRYPTO_FileHashContext * GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, enum GNUNET_SCHEDULER_Priority priority, const char *filename, @@ -493,12 +508,13 @@ GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, GNUNET_CRYPTO_HashCompletedCallback callback, void *callback_cls) { - struct FileHashContext *fhc; + struct GNUNET_CRYPTO_FileHashContext *fhc; GNUNET_assert (blocksize > 0); - fhc = GNUNET_malloc (sizeof (struct FileHashContext) + blocksize); + fhc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize); fhc->callback = callback; fhc->callback_cls = callback_cls; + fhc->sched = sched; fhc->buffer = (unsigned char *) &fhc[1]; fhc->filename = GNUNET_strdup (filename); fhc->fh = NULL; @@ -506,27 +522,44 @@ GNUNET_CRYPTO_hash_file (struct GNUNET_SCHEDULER_Handle *sched, fhc->bsize = blocksize; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO)) { - file_hash_finish (fhc, NULL); - return; + GNUNET_free (fhc->filename); + GNUNET_free (fhc); + return NULL; } fhc->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (!fhc->fh) { - file_hash_finish (fhc, NULL); - return; + GNUNET_free (fhc->filename); + GNUNET_free (fhc); + return NULL; } - GNUNET_SCHEDULER_add_with_priority (sched, priority, &file_hash_task, fhc); + fhc->task + = GNUNET_SCHEDULER_add_with_priority (sched, priority, + &file_hash_task, fhc); + return fhc; } -/* ***************** binary-ASCII encoding *************** */ - /** - * 32 characters for encoding (GNUNET_CRYPTO_hash => 32 characters) + * Cancel a file hashing operation. + * + * @param fhc operation to cancel (callback must not yet have been invoked) */ -static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; +void +GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc) +{ + GNUNET_SCHEDULER_cancel (fhc->sched, + fhc->task); + GNUNET_free (fhc->filename); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh)); + GNUNET_free (fhc); +} + + + +/* ***************** binary-ASCII encoding *************** */ static unsigned int getValue__ (unsigned char a) @@ -553,6 +586,10 @@ void GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, struct GNUNET_CRYPTO_HashAsciiEncoded *result) { + /** + * 32 characters for encoding (GNUNET_CRYPTO_hash => 32 characters) + */ + static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; unsigned int wpos; unsigned int rpos; unsigned int bits; @@ -631,8 +668,10 @@ GNUNET_CRYPTO_hash_from_string (const char *enc, GNUNET_HashCode * result) * fast, not involve bits[0] or bits[4] (they're used elsewhere), and be * somewhat consistent. And of course, the result should be a positive * number. - * - * @returns a positive number which is a measure for + * + * @param a some hash code + * @param b some hash code + * @return a positive number which is a measure for * hashcode proximity. */ unsigned int @@ -650,7 +689,7 @@ GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, { int i; for (i = (sizeof (GNUNET_HashCode) / sizeof (uint32_t)) - 1; i >= 0; i--) - result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, (uint32_t) - 1); + result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, UINT32_MAX); } void @@ -769,4 +808,43 @@ GNUNET_CRYPTO_hash_xorcmp (const GNUNET_HashCode * h1, return 0; } + +/** + * Calculate HMAC of a message (RFC 2104) + * + * @param key secret key + * @param plaintext input plaintext + * @param plaintext_len length of plaintext + * @param hmac where to store the hmac + */ +void +GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AesSessionKey *key, + const void *plaintext, + size_t plaintext_len, + GNUNET_HashCode *hmac) +{ + GNUNET_HashCode kh; + GNUNET_HashCode ipad; + GNUNET_HashCode opad; + GNUNET_HashCode him; + struct sha512_ctx sctx; + + memset (&kh, 0, sizeof (kh)); + GNUNET_assert (sizeof (GNUNET_HashCode) > sizeof (struct GNUNET_CRYPTO_AesSessionKey)); + memcpy (&kh, key, sizeof (struct GNUNET_CRYPTO_AesSessionKey)); + memset (&ipad, 0x5c, sizeof (ipad)); + memset (&opad, 0x36, sizeof (opad)); + GNUNET_CRYPTO_hash_xor (&ipad, &kh, &ipad); + GNUNET_CRYPTO_hash_xor (&opad, &kh, &opad); + sha512_init (&sctx); + sha512_update (&sctx, (const unsigned char*) &ipad, sizeof (ipad)); + sha512_update (&sctx, plaintext, plaintext_len); + sha512_final (&sctx, (unsigned char*) &him); + sha512_init (&sctx); + sha512_update (&sctx, (const unsigned char*) &opad, sizeof (opad)); + sha512_update (&sctx, (const unsigned char*) &him, sizeof (him)); + sha512_final (&sctx, (unsigned char*) hmac); +} + + /* end of crypto_hash.c */