#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.
This commit is contained in:
Mike Gelfand 2014-12-04 12:13:59 +00:00
parent f6f7bf8227
commit 4cfe7e7ddb
14 changed files with 148 additions and 66 deletions

View File

@ -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

View File

@ -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;

View File

@ -10,6 +10,7 @@
#include <assert.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#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)

View File

@ -8,6 +8,7 @@
*/
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h> /* 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)
{

View File

@ -10,13 +10,44 @@
#ifndef TR_CRYPTO_UTILS_H
#define TR_CRYPTO_UTILS_H
#include <inttypes.h>
#include <stddef.h>
#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).
*/

View File

@ -15,7 +15,6 @@
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/rc4.h>
#include <openssl/sha.h>
#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

View File

@ -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);

View File

@ -12,10 +12,9 @@
#include <stdlib.h> /* bsearch () */
#include <string.h> /* memcmp () */
#include <openssl/sha.h>
#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;

View File

@ -15,7 +15,7 @@
#include <event2/util.h> /* 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"

View File

@ -13,7 +13,7 @@
#include <event2/buffer.h>
#include "transmission.h"
#include "crypto.h" /* tr_sha1 */
#include "crypto-utils.h" /* tr_sha1 */
#include "file.h"
#include "log.h"
#include "metainfo.h"

View File

@ -13,7 +13,7 @@
#include <event2/buffer.h>
#include "transmission.h"
#include "crypto.h" /* tr_sha1 () */
#include "crypto-utils.h" /* tr_sha1 () */
#include "file.h"
#include "log.h"
#include "magnet.h"

View File

@ -19,6 +19,7 @@
#include <assert.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h> /* remove () */
#include <string.h> /* memcmp */
#include <stdlib.h> /* qsort */
#include <limits.h> /* 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"

View File

@ -49,7 +49,6 @@
/* libT */
#include "transmission.h"
#include "crypto.h"
#include "crypto-utils.h"
#include "file.h"
#include "log.h"

View File

@ -15,10 +15,9 @@
#include <fcntl.h> /* posix_fadvise () */
#endif
#include <openssl/sha.h>
#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 */