From: Mike Gelfand Date: Thu, 4 Dec 2014 12:13:59 +0000 (+0000) Subject: #4400, #5462: Move SHA1 helpers to crypto-utils X-Git-Tag: 2.90~337 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4cfe7e7ddbc7a9d03d7e160c62f46f926e2699e8;p=transmission #4400, #5462: Move SHA1 helpers to crypto-utils On a way to factoring out OpenSSL support to a standalone file to ease addition of other crypto libraries support in the future, move helpers providing SHA1 calculation to crypto-utils.{c,h}. OpenSSL-related functionality (SHA1 context management) is moved to crypto-utils-openssl.c. Add new tr_sha1_ctx_t type and functions to be implemented by crypto backends: * tr_sha1_init - allocate SHA1 context and and initialize it, * tr_sha1_update - hash some [more] data, * tr_sha1_final - finish hash calculation and free the context. Add new files to CMakeLists.txt (leftover from previous commit) to fix CMake-based configuration. --- diff --git a/libtransmission/CMakeLists.txt b/libtransmission/CMakeLists.txt index f987f99ec..30ff96022 100644 --- a/libtransmission/CMakeLists.txt +++ b/libtransmission/CMakeLists.txt @@ -14,6 +14,8 @@ set(${PROJECT_NAME}_SOURCES completion.c ConvertUTF.c crypto.c + crypto-utils.c + crypto-utils-openssl.c error.c fdlimit.c file.c @@ -91,6 +93,7 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS completion.h ConvertUTF.h crypto.h + crypto-utils.h fdlimit.h handshake.h history.h diff --git a/libtransmission/crypto-test.c b/libtransmission/crypto-test.c index 3a76226ef..df283b008 100644 --- a/libtransmission/crypto-test.c +++ b/libtransmission/crypto-test.c @@ -99,10 +99,10 @@ test_sha1 (void) { uint8_t hash[SHA_DIGEST_LENGTH]; - tr_sha1 (hash, "test", 4, NULL); + check (tr_sha1 (hash, "test", 4, NULL)); check (memcmp (hash, "\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1c\x4c\x08\x73\xd3\x91\xe9\x87\x98\x2f\xbb\xd3", SHA_DIGEST_LENGTH) == 0); - tr_sha1 (hash, "1", 1, "22", 2, "333", 3, NULL); + check (tr_sha1 (hash, "1", 1, "22", 2, "333", 3, NULL)); check (memcmp (hash, "\x1f\x74\x64\x8e\x50\xa6\xa6\x70\x8e\xc5\x4a\xb3\x27\xa1\x63\xd5\x53\x6b\x7c\xed", SHA_DIGEST_LENGTH) == 0); return 0; diff --git a/libtransmission/crypto-utils-openssl.c b/libtransmission/crypto-utils-openssl.c index 556573b29..187288875 100644 --- a/libtransmission/crypto-utils-openssl.c +++ b/libtransmission/crypto-utils-openssl.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "transmission.h" @@ -82,6 +83,54 @@ check_openssl_pointer (void * pointer, **** ***/ +tr_sha1_ctx_t +tr_sha1_init (void) +{ + EVP_MD_CTX * handle = EVP_MD_CTX_create (); + + if (check_result (EVP_DigestInit_ex (handle, EVP_sha1 (), NULL))) + return handle; + + EVP_MD_CTX_destroy (handle); + return NULL; +} + +bool +tr_sha1_update (tr_sha1_ctx_t handle, + const void * data, + size_t data_length) +{ + assert (handle != NULL); + assert (data != NULL); + + return check_result (EVP_DigestUpdate (handle, data, data_length)); +} + +bool +tr_sha1_final (tr_sha1_ctx_t handle, + uint8_t * hash) +{ + bool ret = true; + + if (hash != NULL) + { + unsigned int hash_length; + + assert (handle != NULL); + + ret = check_result (EVP_DigestFinal_ex (handle, hash, &hash_length)); + + assert (!ret || hash_length == SHA_DIGEST_LENGTH); + } + + EVP_MD_CTX_destroy (handle); + return ret; +} + +/*** +**** +***/ + bool tr_rand_buffer (void * buffer, size_t length) diff --git a/libtransmission/crypto-utils.c b/libtransmission/crypto-utils.c index 0be91772d..f6f0273ab 100644 --- a/libtransmission/crypto-utils.c +++ b/libtransmission/crypto-utils.c @@ -8,6 +8,7 @@ */ #include +#include #include /* abs (), srand (), rand () */ #include "transmission.h" @@ -18,6 +19,45 @@ **** ***/ +bool +tr_sha1 (uint8_t * hash, + const void * data1, + int data1_length, + ...) +{ + tr_sha1_ctx_t sha; + + if ((sha = tr_sha1_init ()) == NULL) + return false; + + if (tr_sha1_update (sha, data1, data1_length)) + { + va_list vl; + const void * data; + + va_start (vl, data1_length); + while ((data = va_arg (vl, const void *)) != NULL) + { + const int data_length = va_arg (vl, int); + assert (data_length >= 0); + if (!tr_sha1_update (sha, data, data_length)) + break; + } + va_end (vl); + + /* did we reach the end of argument list? */ + if (data == NULL) + return tr_sha1_final (sha, hash); + } + + tr_sha1_final (sha, NULL); + return false; +} + +/*** +**** +***/ + int tr_rand_int (int upper_bound) { diff --git a/libtransmission/crypto-utils.h b/libtransmission/crypto-utils.h index 5189e12e6..a839775c6 100644 --- a/libtransmission/crypto-utils.h +++ b/libtransmission/crypto-utils.h @@ -10,13 +10,44 @@ #ifndef TR_CRYPTO_UTILS_H #define TR_CRYPTO_UTILS_H +#include #include +#include "utils.h" /* TR_GNUC_NULL_TERMINATED */ + /** *** @addtogroup utils Utilities *** @{ **/ + /** @brief Opaque SHA1 context type. */ +typedef void * tr_sha1_ctx_t; + +/** + * @brief Generate a SHA1 hash from one or more chunks of memory. + */ +bool tr_sha1 (uint8_t * hash, + const void * data1, + int data1_length, + ...) TR_GNUC_NULL_TERMINATED; + +/** + * @brief Allocate and initialize new SHA1 hasher context. + */ +tr_sha1_ctx_t tr_sha1_init (void); + +/** + * @brief Update SHA1 hash. + */ +bool tr_sha1_update (tr_sha1_ctx_t handle, + const void * data, + size_t data_length); + +/** + * @brief Finalize and export SHA1 hash, free hasher context. + */ +bool tr_sha1_final (tr_sha1_ctx_t handle, + uint8_t * hash); /** * @brief Returns a random number in the range of [0...upper_bound). */ diff --git a/libtransmission/crypto.c b/libtransmission/crypto.c index d801cdc28..31b8bf9b9 100644 --- a/libtransmission/crypto.c +++ b/libtransmission/crypto.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "transmission.h" #include "crypto.h" @@ -29,28 +28,6 @@ *** **/ -void -tr_sha1 (uint8_t * setme, const void * content1, int content1_len, ...) -{ - va_list vl; - SHA_CTX sha; - const void * content; - - SHA1_Init (&sha); - SHA1_Update (&sha, content1, content1_len); - - va_start (vl, content1_len); - while ((content = va_arg (vl, const void*))) - SHA1_Update (&sha, content, va_arg (vl, int)); - va_end (vl); - - SHA1_Final (setme, &sha); -} - -/** -*** -**/ - #define KEY_LEN 96 #define PRIME_LEN 96 @@ -198,24 +175,17 @@ initRC4 (tr_crypto * crypto, RC4_KEY * setme, const char * key) { - SHA_CTX sha; uint8_t buf[SHA_DIGEST_LENGTH]; assert (crypto->torrentHashIsSet); assert (crypto->mySecretIsSet); - if (SHA1_Init (&sha) - && SHA1_Update (&sha, key, 4) - && SHA1_Update (&sha, crypto->mySecret, KEY_LEN) - && SHA1_Update (&sha, crypto->torrentHash, SHA_DIGEST_LENGTH) - && SHA1_Final (buf, &sha)) - { - RC4_set_key (setme, SHA_DIGEST_LENGTH, buf); - } - else - { - logErrorFromSSL (); - } + if (tr_sha1 (buf, + key, 4, + crypto->mySecret, KEY_LEN, + crypto->torrentHash, SHA_DIGEST_LENGTH, + NULL)) + RC4_set_key (setme, SHA_DIGEST_LENGTH, buf); } void diff --git a/libtransmission/crypto.h b/libtransmission/crypto.h index 972817950..985c90141 100644 --- a/libtransmission/crypto.h +++ b/libtransmission/crypto.h @@ -86,14 +86,6 @@ void tr_cryptoEncrypt (tr_crypto * crypto, *** @{ **/ - -/** @brief generate a SHA1 hash from one or more chunks of memory */ -void tr_sha1 (uint8_t * setme, - const void * content1, - int content1_len, - ...) TR_GNUC_NULL_TERMINATED; - - /** @brief generate a SSHA password from its plaintext source */ char* tr_ssha1 (const void * plaintext); diff --git a/libtransmission/inout.c b/libtransmission/inout.c index 63bd1874a..82a769380 100644 --- a/libtransmission/inout.c +++ b/libtransmission/inout.c @@ -12,10 +12,9 @@ #include /* bsearch () */ #include /* memcmp () */ -#include - #include "transmission.h" #include "cache.h" /* tr_cacheReadBlock () */ +#include "crypto-utils.h" #include "error.h" #include "fdlimit.h" #include "file.h" @@ -278,7 +277,7 @@ recalculateHash (tr_torrent * tor, tr_piece_index_t pieceIndex, uint8_t * setme) bool success = true; const size_t buflen = tor->blockSize; void * buffer = tr_valloc (buflen); - SHA_CTX sha; + tr_sha1_ctx_t sha; assert (tor != NULL); assert (pieceIndex < tor->info.pieceCount); @@ -286,7 +285,7 @@ recalculateHash (tr_torrent * tor, tr_piece_index_t pieceIndex, uint8_t * setme) assert (buflen > 0); assert (setme != NULL); - SHA1_Init (&sha); + sha = tr_sha1_init (); bytesLeft = tr_torPieceCountBytes (tor, pieceIndex); tr_ioPrefetch (tor, pieceIndex, offset, bytesLeft); @@ -297,13 +296,12 @@ recalculateHash (tr_torrent * tor, tr_piece_index_t pieceIndex, uint8_t * setme) success = !tr_cacheReadBlock (tor->session->cache, tor, pieceIndex, offset, len, buffer); if (!success) break; - SHA1_Update (&sha, buffer, len); + tr_sha1_update (sha, buffer, len); offset += len; bytesLeft -= len; } - if (success) - SHA1_Final (setme, &sha); + tr_sha1_final (sha, success ? setme : NULL); tr_free (buffer); return success; diff --git a/libtransmission/makemeta.c b/libtransmission/makemeta.c index df8e727f2..26f39d061 100644 --- a/libtransmission/makemeta.c +++ b/libtransmission/makemeta.c @@ -15,7 +15,7 @@ #include /* evutil_ascii_strcasecmp () */ #include "transmission.h" -#include "crypto.h" /* tr_sha1 */ +#include "crypto-utils.h" /* tr_sha1 */ #include "error.h" #include "file.h" #include "log.h" diff --git a/libtransmission/metainfo.c b/libtransmission/metainfo.c index c7f3581dc..9a913cfe6 100644 --- a/libtransmission/metainfo.c +++ b/libtransmission/metainfo.c @@ -13,7 +13,7 @@ #include #include "transmission.h" -#include "crypto.h" /* tr_sha1 */ +#include "crypto-utils.h" /* tr_sha1 */ #include "file.h" #include "log.h" #include "metainfo.h" diff --git a/libtransmission/torrent-magnet.c b/libtransmission/torrent-magnet.c index cad15ead4..850086599 100644 --- a/libtransmission/torrent-magnet.c +++ b/libtransmission/torrent-magnet.c @@ -13,7 +13,7 @@ #include #include "transmission.h" -#include "crypto.h" /* tr_sha1 () */ +#include "crypto-utils.h" /* tr_sha1 () */ #include "file.h" #include "log.h" #include "magnet.h" diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index ea2e8d450..ff36fb8e6 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -19,6 +19,7 @@ #include #include #include +#include /* remove () */ #include /* memcmp */ #include /* qsort */ #include /* INT_MAX */ @@ -30,8 +31,7 @@ #include "bandwidth.h" #include "cache.h" #include "completion.h" -#include "crypto.h" /* for tr_sha1 */ -#include "crypto-utils.h" +#include "crypto-utils.h" /* for tr_sha1 */ #include "error.h" #include "fdlimit.h" /* tr_fdTorrentClose */ #include "file.h" diff --git a/libtransmission/tr-dht.c b/libtransmission/tr-dht.c index e40d26832..23a03b621 100644 --- a/libtransmission/tr-dht.c +++ b/libtransmission/tr-dht.c @@ -49,7 +49,6 @@ /* libT */ #include "transmission.h" -#include "crypto.h" #include "crypto-utils.h" #include "file.h" #include "log.h" diff --git a/libtransmission/verify.c b/libtransmission/verify.c index 1c1129694..cad8ff83b 100644 --- a/libtransmission/verify.c +++ b/libtransmission/verify.c @@ -15,10 +15,9 @@ #include /* posix_fadvise () */ #endif -#include - #include "transmission.h" #include "completion.h" +#include "crypto-utils.h" #include "file.h" #include "list.h" #include "log.h" @@ -40,7 +39,7 @@ static bool verifyTorrent (tr_torrent * tor, bool * stopFlag) { time_t end; - SHA_CTX sha; + tr_sha1_ctx_t sha; tr_sys_file_t fd = TR_BAD_SYS_FILE; uint64_t filePos = 0; bool changed = false; @@ -54,7 +53,7 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag) const size_t buflen = 1024 * 128; /* 128 KiB buffer */ uint8_t * buffer = tr_valloc (buflen); - SHA1_Init (&sha); + sha = tr_sha1_init (); tr_logAddTorDbg (tor, "%s", "verifying torrent..."); tr_torrentSetChecked (tor, 0); @@ -92,7 +91,7 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag) if (tr_sys_file_read_at (fd, buffer, bytesThisPass, filePos, &numRead, NULL) && numRead > 0) { bytesThisPass = numRead; - SHA1_Update (&sha, buffer, bytesThisPass); + tr_sha1_update (sha, buffer, bytesThisPass); #if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_DONTNEED posix_fadvise (fd, filePos, bytesThisPass, POSIX_FADV_DONTNEED); #endif @@ -112,7 +111,7 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag) bool hasPiece; uint8_t hash[SHA_DIGEST_LENGTH]; - SHA1_Final (hash, &sha); + tr_sha1_final (sha, hash); hasPiece = !memcmp (hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH); if (hasPiece || hadPiece) @@ -133,7 +132,7 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag) tr_wait_msec (MSEC_TO_SLEEP_PER_SECOND_DURING_VERIFY); } - SHA1_Init (&sha); + sha = tr_sha1_init (); pieceIndex++; piecePos = 0; } @@ -154,6 +153,7 @@ verifyTorrent (tr_torrent * tor, bool * stopFlag) /* cleanup */ if (fd != TR_BAD_SYS_FILE) tr_sys_file_close (fd, NULL); + tr_sha1_final (sha, NULL); free (buffer); /* stopwatch */