X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_hash.c;h=925d6b94dae969d8a0789a17869073231ddac5c1;hb=a90f8587871a66a71c802c2c8823c7a44d0f6d2c;hp=60ed6582d7bb71fd3291c1a2b0b8c6114e73092e;hpb=957037e37439b9378b1242270530db95b06a458c;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index 60ed6582d..925d6b94d 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c @@ -1,37 +1,37 @@ /* This file is part of GNUnet. - (C) 2001-2013 Christian Grothoff (and other contributing authors) + Copyright (C) 2001-2013 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + SPDX-License-Identifier: AGPL3.0-or-later */ - /** * @file util/crypto_hash.c - * @brief SHA-512 GNUNET_CRYPTO_hash related functions + * @brief SHA-512 #GNUNET_CRYPTO_hash() related functions * @author Christian Grothoff */ - #include "platform.h" -#include "gnunet_util_lib.h" +#include "gnunet_crypto_lib.h" +#include "gnunet_strings_lib.h" +#include "benchmark.h" #include -#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) +#define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-hash", __VA_ARGS__) -#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) +#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-hash", syscall, filename) /** * Hash block of given size. @@ -45,194 +45,9 @@ GNUNET_CRYPTO_hash (const void *block, size_t size, struct GNUNET_HashCode *ret) { + BENCHMARK_START (hash); gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size); -} - - -/** - * Context used when hashing a file. - */ -struct GNUNET_CRYPTO_FileHashContext -{ - - /** - * Function to call upon completion. - */ - GNUNET_CRYPTO_HashCompletedCallback callback; - - /** - * Closure for callback. - */ - void *callback_cls; - - /** - * IO buffer. - */ - unsigned char *buffer; - - /** - * Name of the file we are hashing. - */ - char *filename; - - /** - * File descriptor. - */ - struct GNUNET_DISK_FileHandle *fh; - - /** - * Cummulated hash. - */ - gcry_md_hd_t md; - - /** - * Size of the file. - */ - uint64_t fsize; - - /** - * Current offset. - */ - uint64_t offset; - - /** - * Current task for hashing. - */ - GNUNET_SCHEDULER_TaskIdentifier task; - - /** - * Priority we use. - */ - enum GNUNET_SCHEDULER_Priority priority; - - /** - * Blocksize. - */ - size_t bsize; - -}; - - -/** - * Report result of hash computation to callback - * and free associated resources. - */ -static void -file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc, - const struct GNUNET_HashCode * res) -{ - fhc->callback (fhc->callback_cls, res); - GNUNET_free (fhc->filename); - if (!GNUNET_DISK_handle_invalid (fhc->fh)) - GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh)); - gcry_md_close (fhc->md); - GNUNET_free (fhc); /* also frees fhc->buffer */ -} - - -/** - * File hashing task. - * - * @param cls closure - * @param tc context - */ -static void -file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_CRYPTO_FileHashContext *fhc = cls; - struct 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) - delta = fhc->fsize - fhc->offset; - if (delta != GNUNET_DISK_file_read (fhc->fh, fhc->buffer, delta)) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", fhc->filename); - file_hash_finish (fhc, NULL); - return; - } - gcry_md_write (fhc->md, fhc->buffer, delta); - fhc->offset += delta; - if (fhc->offset == fhc->fsize) - { - res = (struct GNUNET_HashCode *) gcry_md_read (fhc->md, GCRY_MD_SHA512); - file_hash_finish (fhc, res); - return; - } - fhc->task = GNUNET_SCHEDULER_add_with_priority (fhc->priority, - &file_hash_task, fhc); -} - - -/** - * Compute the hash of an entire file. - * - * @param priority scheduling priority to use - * @param filename name of file to hash - * @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 - */ -struct GNUNET_CRYPTO_FileHashContext * -GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority, - const char *filename, size_t blocksize, - GNUNET_CRYPTO_HashCompletedCallback callback, - void *callback_cls) -{ - struct GNUNET_CRYPTO_FileHashContext *fhc; - - GNUNET_assert (blocksize > 0); - fhc = - GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize); - fhc->callback = callback; - fhc->callback_cls = callback_cls; - fhc->buffer = (unsigned char *) &fhc[1]; - fhc->filename = GNUNET_strdup (filename); - if (GPG_ERR_NO_ERROR != gcry_md_open (&fhc->md, GCRY_MD_SHA512, 0)) - { - GNUNET_break (0); - GNUNET_free (fhc); - return NULL; - } - fhc->bsize = blocksize; - if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO, GNUNET_YES)) - { - 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) - { - GNUNET_free (fhc->filename); - GNUNET_free (fhc); - return NULL; - } - fhc->priority = priority; - fhc->task = - GNUNET_SCHEDULER_add_with_priority (priority, &file_hash_task, fhc); - return fhc; -} - - -/** - * Cancel a file hashing operation. - * - * @param fhc operation to cancel (callback must not yet have been invoked) - */ -void -GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc) -{ - GNUNET_SCHEDULER_cancel (fhc->task); - GNUNET_free (fhc->filename); - GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh)); - GNUNET_free (fhc); + BENCHMARK_END (hash); } @@ -257,9 +72,9 @@ GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode *block, char *np; np = GNUNET_STRINGS_data_to_string ((const unsigned char *) block, - sizeof (struct GNUNET_HashCode), - (char*) result, - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1); + sizeof (struct GNUNET_HashCode), + (char *) result, + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1); GNUNET_assert (NULL != np); *np = '\0'; } @@ -375,8 +190,9 @@ GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode * a, * @param result set to a ^ b */ void -GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode * a, const struct GNUNET_HashCode * b, - struct GNUNET_HashCode * result) +GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode *a, + const struct GNUNET_HashCode *b, + struct GNUNET_HashCode *result) { int i; @@ -554,14 +370,17 @@ GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, /** * Calculate HMAC of a message (RFC 2104) + * TODO: Shouldn' this be the standard hmac function and + * the above be renamed? * * @param key secret key + * @param key_len secret key length * @param plaintext input plaintext * @param plaintext_len length of @a plaintext * @param hmac where to store the hmac */ void -GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, +GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac) { @@ -579,11 +398,121 @@ GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, { gcry_md_reset (md); } - gcry_md_setkey (md, key->key, sizeof (key->key)); + gcry_md_setkey (md, key, key_len); gcry_md_write (md, plaintext, plaintext_len); mc = gcry_md_read (md, GCRY_MD_SHA512); GNUNET_assert (NULL != mc); - memcpy (hmac->bits, mc, sizeof (hmac->bits)); + GNUNET_memcpy (hmac->bits, mc, sizeof (hmac->bits)); +} + + +/** + * Calculate HMAC of a message (RFC 2104) + * + * @param key secret key + * @param plaintext input plaintext + * @param plaintext_len length of @a plaintext + * @param hmac where to store the hmac + */ +void +GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, + const void *plaintext, size_t plaintext_len, + struct GNUNET_HashCode *hmac) +{ + GNUNET_CRYPTO_hmac_raw ((void*) key->key, sizeof (key->key), + plaintext, plaintext_len, + hmac); +} + + +/** + * Context for cummulative hashing. + */ +struct GNUNET_HashContext +{ + /** + * Internal state of the hash function. + */ + gcry_md_hd_t hd; +}; + + +/** + * Start incremental hashing operation. + * + * @return context for incremental hash computation + */ +struct GNUNET_HashContext * +GNUNET_CRYPTO_hash_context_start () +{ + struct GNUNET_HashContext *hc; + + BENCHMARK_START (hash_context_start); + + hc = GNUNET_new (struct GNUNET_HashContext); + GNUNET_assert (0 == + gcry_md_open (&hc->hd, + GCRY_MD_SHA512, + 0)); + + BENCHMARK_END (hash_context_start); + + return hc; +} + + +/** + * Add data to be hashed. + * + * @param hc cummulative hash context + * @param buf data to add + * @param size number of bytes in @a buf + */ +void +GNUNET_CRYPTO_hash_context_read (struct GNUNET_HashContext *hc, + const void *buf, + size_t size) +{ + BENCHMARK_START (hash_context_read); + gcry_md_write (hc->hd, buf, size); + BENCHMARK_END (hash_context_read); +} + + +/** + * Finish the hash computation. + * + * @param hc hash context to use + * @param r_hash where to write the latest / final hash code + */ +void +GNUNET_CRYPTO_hash_context_finish (struct GNUNET_HashContext *hc, + struct GNUNET_HashCode *r_hash) +{ + const void *res = gcry_md_read (hc->hd, 0); + + BENCHMARK_START (hash_context_finish); + + GNUNET_assert (NULL != res); + if (NULL != r_hash) + GNUNET_memcpy (r_hash, + res, + sizeof (struct GNUNET_HashCode)); + GNUNET_CRYPTO_hash_context_abort (hc); + BENCHMARK_END (hash_context_finish); +} + + +/** + * Abort hashing, do not bother calculating final result. + * + * @param hc hash context to destroy + */ +void +GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext *hc) +{ + gcry_md_close (hc->hd); + GNUNET_free (hc); }