transmission/libtransmission/crypto-test.c

304 lines
7.4 KiB
C
Raw Normal View History

/*
* This file Copyright (C) 2013-2014 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#include <string.h>
#include "transmission.h"
#include "crypto.h"
#include "crypto-utils.h"
#include "libtransmission-test.h"
#include "crypto-test-ref.h"
static int
test_torrent_hash (void)
{
tr_crypto a;
uint8_t hash[SHA_DIGEST_LENGTH];
uint8_t i;
for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
hash[i] = i;
tr_cryptoConstruct (&a, NULL, true);
check (!tr_cryptoHasTorrentHash (&a));
check (tr_cryptoGetTorrentHash (&a) == NULL);
tr_cryptoSetTorrentHash (&a, hash);
check (tr_cryptoHasTorrentHash (&a));
check (tr_cryptoGetTorrentHash (&a) != NULL);
check (memcmp (tr_cryptoGetTorrentHash (&a), hash, SHA_DIGEST_LENGTH) == 0);
tr_cryptoDestruct (&a);
for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
hash[i] = i + 1;
tr_cryptoConstruct (&a, hash, false);
check (tr_cryptoHasTorrentHash (&a));
check (tr_cryptoGetTorrentHash (&a) != NULL);
check (memcmp (tr_cryptoGetTorrentHash (&a), hash, SHA_DIGEST_LENGTH) == 0);
tr_cryptoSetTorrentHash (&a, NULL);
check (!tr_cryptoHasTorrentHash (&a));
check (tr_cryptoGetTorrentHash (&a) == NULL);
tr_cryptoDestruct (&a);
return 0;
}
static int
test_encrypt_decrypt (void)
{
tr_crypto a;
tr_crypto_ b;
uint8_t hash[SHA_DIGEST_LENGTH];
const char test1[] = { "test1" };
char buf11[sizeof (test1)], buf12[sizeof (test1)];
const char test2[] = { "@#)C$@)#(*%bvkdjfhwbc039bc4603756VB3)" };
char buf21[sizeof (test2)], buf22[sizeof (test2)];
int i;
for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
hash[i] = (uint8_t)i;
tr_cryptoConstruct (&a, hash, false);
tr_cryptoConstruct_ (&b, hash, true);
check (tr_cryptoComputeSecret (&a, tr_cryptoGetMyPublicKey_ (&b, &i)));
check (tr_cryptoComputeSecret_ (&b, tr_cryptoGetMyPublicKey (&a, &i)));
tr_cryptoEncryptInit (&a);
tr_cryptoEncrypt (&a, sizeof (test1), test1, buf11);
tr_cryptoDecryptInit_ (&b);
tr_cryptoDecrypt_ (&b, sizeof (test1), buf11, buf12);
check_streq (test1, buf12);
tr_cryptoEncryptInit_ (&b);
tr_cryptoEncrypt_ (&b, sizeof (test2), test2, buf21);
tr_cryptoDecryptInit (&a);
tr_cryptoDecrypt (&a, sizeof (test2), buf21, buf22);
check_streq (test2, buf22);
tr_cryptoDestruct_ (&b);
tr_cryptoDestruct (&a);
return 0;
}
static int
test_sha1 (void)
{
uint8_t hash[SHA_DIGEST_LENGTH];
uint8_t hash_[SHA_DIGEST_LENGTH];
check (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);
check (memcmp (hash, hash_, SHA_DIGEST_LENGTH) == 0);
check (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);
check (memcmp (hash, hash_, SHA_DIGEST_LENGTH) == 0);
return 0;
}
static int
test_ssha1 (void)
{
struct
{
const char * const plain_text;
const char * const ssha1;
}
test_data[] =
{
{ "test", "{15ad0621b259a84d24dcd4e75b09004e98a3627bAMbyRHJy" },
{ "QNY)(*#$B)!_X$B !_B#($^!)*&$%CV!#)&$C!@$(P*)", "{10e2d7acbb104d970514a147cd16d51dfa40fb3c0OSwJtOL" }
};
size_t i;
#define HASH_COUNT (4 * 1024)
for (i = 0; i < sizeof (test_data) / sizeof (*test_data); ++i)
{
char * const phrase = tr_strdup (test_data[i].plain_text);
char ** hashes = tr_new (char *, HASH_COUNT);
size_t j;
check (tr_ssha1_matches (test_data[i].ssha1, phrase));
check (tr_ssha1_matches_ (test_data[i].ssha1, phrase));
for (j = 0; j < HASH_COUNT; ++j)
{
hashes[j] = j % 2 == 0 ? tr_ssha1 (phrase) : tr_ssha1_ (phrase);
check (hashes[j] != NULL);
/* phrase matches each of generated hashes */
check (tr_ssha1_matches (hashes[j], phrase));
check (tr_ssha1_matches_ (hashes[j], phrase));
}
for (j = 0; j < HASH_COUNT; ++j)
{
size_t k;
/* all hashes are different */
for (k = 0; k < HASH_COUNT; ++k)
check (k == j || strcmp (hashes[j], hashes[k]) != 0);
}
/* exchange two first chars */
phrase[0] ^= phrase[1];
phrase[1] ^= phrase[0];
phrase[0] ^= phrase[1];
for (j = 0; j < HASH_COUNT; ++j)
{
/* changed phrase doesn't match the hashes */
check (!tr_ssha1_matches (hashes[j], phrase));
check (!tr_ssha1_matches_ (hashes[j], phrase));
}
for (j = 0; j < HASH_COUNT; ++j)
tr_free (hashes[j]);
tr_free (hashes);
tr_free (phrase);
}
#undef HASH_COUNT
/* should work with different salt lengths as well */
check (tr_ssha1_matches ("{a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", "test"));
check (tr_ssha1_matches ("{d209a21d3bc4f8fc4f8faf347e69f3def597eb170pySy4ai1ZPMjeU1", "test"));
return 0;
}
static int
test_random (void)
{
int i;
/* test that tr_rand_int () stays in-bounds */
for (i = 0; i < 100000; ++i)
{
const int val = tr_rand_int (100);
check (val >= 0);
check (val < 100);
}
return 0;
}
static bool
base64_eq (const char * a,
const char * b)
{
for (; ; ++a, ++b)
{
while (*a == '\r' || *a == '\n')
++a;
while (*b == '\r' || *b == '\n')
++b;
if (*a == '\0' || *b == '\0' || *a != *b)
break;
}
return *a == *b;
}
static int
test_base64 (void)
{
size_t len;
char * in, * out;
size_t i;
out = tr_base64_encode_str ("YOYO!", &len);
check_uint_eq (strlen (out), len);
check (base64_eq ("WU9ZTyE=", out));
in = tr_base64_decode_str (out, &len);
check_uint_eq (5, len);
check_streq ("YOYO!", in);
tr_free (in);
tr_free (out);
out = tr_base64_encode ("", 0, &len);
check_uint_eq (0, len);
check_streq ("", out);
tr_free (out);
out = tr_base64_decode ("", 0, &len);
check_uint_eq (0, len);
check_streq ("", out);
tr_free (out);
out = tr_base64_encode (NULL, 0, &len);
check_uint_eq (0, len);
check (out == NULL);
out = tr_base64_decode (NULL, 0, &len);
check_uint_eq (0, len);
check (out == NULL);
#define MAX_BUF_SIZE 1024
for (i = 1; i <= MAX_BUF_SIZE; ++i)
{
size_t j;
char buf[MAX_BUF_SIZE + 1];
for (j = 0; j < i; ++j)
buf[j] = (char) tr_rand_int_weak (256);
out = tr_base64_encode (buf, j, &len);
check_uint_eq (strlen (out), len);
in = tr_base64_decode (out, len, &len);
check_uint_eq (j, len);
check (memcmp (in, buf, len) == 0);
tr_free (in);
tr_free (out);
for (j = 0; j < i; ++j)
buf[j] = (char)(1 + tr_rand_int_weak (255));
buf[j] = '\0';
out = tr_base64_encode_str (buf, &len);
check_uint_eq (strlen (out), len);
in = tr_base64_decode_str (out, &len);
check_uint_eq (j, len);
check_streq (in, buf);
tr_free (in);
tr_free (out);
}
#undef MAX_BUF_SIZE
return 0;
}
int
main (void)
{
const testFunc tests[] = { test_torrent_hash,
test_encrypt_decrypt,
test_sha1,
test_ssha1,
test_random,
test_base64 };
return runTests (tests, NUM_TESTS (tests));
}