aria2/test/UtilSecurityTest.cc

422 lines
15 KiB
C++
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#include "util.h"
#include "util_security.h"
#include <cppunit/extensions/HelperMacros.h>
// Test vectors from RFC 6234
enum {
SHA1HashSize = 20,
SHA224HashSize = 28,
SHA256HashSize = 32,
SHA384HashSize = 48,
SHA512HashSize = 64,
};
static struct hmachash {
const char* keyarray[5];
int keylength[5];
const char* dataarray[5];
int datalength[5];
const char* resultarray[5];
int resultlength[5];
} hmachashes[] = {
{/* 1 */ {"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b\x0b\x0b"},
{20},
{
"\x48\x69\x20\x54\x68\x65\x72\x65" /* "Hi There" */
},
{8},
{/* HMAC-SHA-1 */
"B617318655057264E28BC0B6FB378C8EF146BE00",
/* HMAC-SHA-224 */
"896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22",
/* HMAC-SHA-256 */
"B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32"
"CFF7",
/* HMAC-SHA-384 */
"AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB"
"C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6",
/* HMAC-SHA-512 */
"87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1"
"7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20"
"3A126854"},
{SHA1HashSize, SHA224HashSize, SHA256HashSize, SHA384HashSize,
SHA512HashSize}},
{/* 2 */ {
"\x4a\x65\x66\x65" /* "Jefe" */
},
{4},
{
"\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74"
"\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f"
/* "what do ya want for nothing?" */
},
{28},
{/* HMAC-SHA-1 */
"EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79",
/* HMAC-SHA-224 */
"A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44",
/* HMAC-SHA-256 */
"5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC"
"3843",
/* HMAC-SHA-384 */
"AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322"
"445E8E2240CA5E69E2C78B3239ECFAB21649",
/* HMAC-SHA-512 */
"164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25"
"05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A"
"38BCE737"},
{SHA1HashSize, SHA224HashSize, SHA256HashSize, SHA384HashSize,
SHA512HashSize}},
{/* 3 */
{"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa"},
{20},
{"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd"},
{50},
{/* HMAC-SHA-1 */
"125D7342B9AC11CD91A39AF48AA17B4F63F175D3",
/* HMAC-SHA-224 */
"7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA",
/* HMAC-SHA-256 */
"773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5"
"65FE",
/* HMAC-SHA-384 */
"88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966"
"144B2A5AB39DC13814B94E3AB6E101A34F27",
/* HMAC-SHA-512 */
"FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227"
"9D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859"
"E13292FB"},
{SHA1HashSize, SHA224HashSize, SHA256HashSize, SHA384HashSize,
SHA512HashSize}},
{/* 4 */ {"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19"},
{25},
{"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd"},
{50},
{/* HMAC-SHA-1 */
"4C9007F4026250C6BC8414F9BF50C86C2D7235DA",
/* HMAC-SHA-224 */
"6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A",
/* HMAC-SHA-256 */
"82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729"
"665B",
/* HMAC-SHA-384 */
"3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57"
"3B4E6801DD23C4A7D679CCF8A386C674CFFB",
/* HMAC-SHA-512 */
"B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E"
"E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB"
"10A298DD"},
{SHA1HashSize, SHA224HashSize, SHA256HashSize, SHA384HashSize,
SHA512HashSize}},
{/* 5 */ {"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c"},
{20},
{"Test With Truncation"},
{20},
{/* HMAC-SHA-1 */
"4C1A03424B55E07FE7F27BE1",
/* HMAC-SHA-224 */
"0E2AEA68A90C8D37C988BCDB9FCA6FA8",
/* HMAC-SHA-256 */
"A3B6167473100EE06E0C796C2955552B",
/* HMAC-SHA-384 */
"3ABF34C3503B2A23A46EFC619BAEF897",
/* HMAC-SHA-512 */
"415FAD6271580A531D4179BC891D87A6"},
{12, 16, 16, 16, 16}},
{/* 6 */ {"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"},
{80, 131},
{"Test Using Larger Than Block-Size Key - Hash Key First"},
{54},
{/* HMAC-SHA-1 */
"AA4AE5E15272D00E95705637CE8A3B55ED402112",
/* HMAC-SHA-224 */
"95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E",
/* HMAC-SHA-256 */
"60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3"
"7F54",
/* HMAC-SHA-384 */
"4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A"
"C4C60C2EF6AB4030FE8296248DF163F44952",
/* HMAC-SHA-512 */
"80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8"
"F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98"
"5D786598"},
{SHA1HashSize, SHA224HashSize, SHA256HashSize, SHA384HashSize,
SHA512HashSize}},
{/* 7 */ {"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"},
{80, 131},
{
"Test Using Larger Than Block-Size Key and "
"Larger Than One Block-Size Data",
"\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20"
"\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
"\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65"
"\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
"\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73"
"\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
"\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20"
"\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
"\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68"
"\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
"\x6d\x2e"
/* "This is a test using a larger than block-size key and a "
"larger than block-size data. The key needs to be hashed "
"before being used by the HMAC algorithm." */
},
{73, 152},
{/* HMAC-SHA-1 */
"E8E99D0F45237D786D6BBAA7965C7808BBFF1A91",
/* HMAC-SHA-224 */
"3A854166AC5D9F023F54D517D0B39DBD946770DB9C2B95C9F6F565D1",
/* HMAC-SHA-256 */
"9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713938A7F51535C3A"
"35E2",
/* HMAC-SHA-384 */
"6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E"
"99C5A678CC31E799176D3860E6110C46523E",
/* HMAC-SHA-512 */
"E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD"
"C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440"
"FA8C6A58"},
{SHA1HashSize, SHA224HashSize, SHA256HashSize, SHA384HashSize,
SHA512HashSize}}};
namespace aria2 {
class SecurityTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(SecurityTest);
CPPUNIT_TEST(testCompareByte);
CPPUNIT_TEST(testCompareArray);
CPPUNIT_TEST(testHMAC);
CPPUNIT_TEST(testHMACRandom);
CPPUNIT_TEST(testPBKDF2);
CPPUNIT_TEST_SUITE_END();
private:
public:
void setUp() {}
void testCompareByte();
void testCompareArray();
void testHMAC();
void testHMACRandom();
void testPBKDF2();
};
CPPUNIT_TEST_SUITE_REGISTRATION(SecurityTest);
void SecurityTest::testCompareByte()
{
CPPUNIT_ASSERT(util::security::compare('a', 'a'));
CPPUNIT_ASSERT(util::security::compare('\0', '\0'));
CPPUNIT_ASSERT(util::security::compare(0xff, 0xff));
CPPUNIT_ASSERT(!util::security::compare('a', 'f'));
CPPUNIT_ASSERT(!util::security::compare('\xfe', 'f'));
CPPUNIT_ASSERT(!util::security::compare(0, 0xff));
}
void SecurityTest::testCompareArray()
{
CPPUNIT_ASSERT(util::security::compare("", "", 0));
CPPUNIT_ASSERT(util::security::compare("a", "a", 1));
CPPUNIT_ASSERT(util::security::compare("a", "ab", 1));
CPPUNIT_ASSERT(util::security::compare("a\0b", "a\0b", 3));
CPPUNIT_ASSERT(
util::security::compare("a\0b", "a\0b", 4)); // implicit null-termination
CPPUNIT_ASSERT(util::security::compare("a\0", "a\0b", 2));
CPPUNIT_ASSERT(util::security::compare("a\xff", "a\xff", 2));
CPPUNIT_ASSERT(!util::security::compare("a", "b", 1));
CPPUNIT_ASSERT(!util::security::compare("a", "bb", 1));
CPPUNIT_ASSERT(!util::security::compare("a\1b", "a\0b", 3));
CPPUNIT_ASSERT(
!util::security::compare("a\1b", "a\0b", 4)); // implicit null-termination
CPPUNIT_ASSERT(!util::security::compare("a\4", "a\0b", 2));
CPPUNIT_ASSERT(!util::security::compare("a\0", "a\xff", 2));
}
static struct {
const char* hash;
const size_t idx;
} hmacs[] = {{"sha-1", 0},
{"sha-224", 1},
{"sha-256", 2},
{"sha-384", 3},
{"sha-512", 4}};
void SecurityTest::testHMAC()
{
for (const auto& test : hmachashes) {
for (const auto& hmac : hmacs) {
if (!util::security::HMAC::supports(hmac.hash)) {
continue;
}
#define SELECT(v) \
test.v[hmac.idx] ? test.v[hmac.idx] : test.v[1] ? test.v[1] : test.v[0]
auto key = SELECT(keyarray);
auto keylen = SELECT(keylength);
auto data = SELECT(dataarray);
auto datalen = SELECT(datalength);
auto result = SELECT(resultarray);
auto resultlen = SELECT(resultlength);
#undef SELECT
auto h = util::security::HMAC::create(hmac.hash, key, keylen);
auto h2 = util::security::HMAC::create(hmac.hash, key, keylen - 1);
auto r = h->getResult(data, datalen);
auto hr = util::toUpper(util::toHex(r.getBytes()));
CPPUNIT_ASSERT(util::security::compare(hr.data(), result, resultlen));
CPPUNIT_ASSERT(r == r);
auto r2 = r;
CPPUNIT_ASSERT(r == r2);
CPPUNIT_ASSERT(r != h2->getResult(data, datalen));
}
}
}
void SecurityTest::testHMACRandom()
{
auto h = util::security::HMAC::createRandom();
CPPUNIT_ASSERT(h->getResult("abc") == h->getResult("abc"));
auto r = h->getResult("def");
CPPUNIT_ASSERT(r == h->getResult("def"));
// Sanity check. At the very least 3 out of ten times 2 random hmacs should
// be different from each other and the 0-secret hmac.
size_t diff = 0;
for (auto i = 0; i < 10; ++i) {
auto h1 = util::security::HMAC::createRandom("sha-1");
auto h2 = util::security::HMAC::createRandom("sha-1");
auto h3 = util::security::HMAC::create("sha-1", "");
CPPUNIT_ASSERT(h1->getResult("abc") == h1->getResult("abc"));
CPPUNIT_ASSERT(h2->getResult("abc") == h2->getResult("abc"));
if (h1->getResult("abc") != h2->getResult("abc") &&
h1->getResult("abc") != h3->getResult("abc") &&
h2->getResult("abc") != h3->getResult("abc")) {
++diff;
}
}
CPPUNIT_ASSERT(diff > 3);
}
static struct pbkdf2 {
char pass[32];
size_t pass_len;
char salt[40];
size_t salt_len;
size_t iterations;
unsigned char key[32];
size_t key_len;
} pbkdf2s[] = {
{"password",
8,
"salt",
4,
1,
{0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24,
0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6},
20},
{"password",
8,
"salt",
4,
1,
{0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24,
0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6},
0},
{"password",
8,
"salt",
4,
2,
{0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a,
0xce, 0x1d, 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57},
20},
{"password",
8,
"salt",
4,
4096,
{0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, 0xd9,
0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1},
20},
/* Disabled due to #236
{
"password", 8,
"salt", 4,
16777216,
{ 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, 0xe9, 0x94, 0x5b, 0x3d,
0x6b, 0xa2, 0x15, 0x8c, 0x26, 0x34, 0xe9, 0x84 },
20,
},
*/
{
"passwordPASSWORDpassword",
24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
36,
4096,
{0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, 0x36,
0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
0x38},
25,
},
{"pass\0word",
9,
"sa\0lt",
5,
4096,
{0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 0xcc, 0x37, 0xd7, 0xf0,
0x34, 0x25, 0xe0, 0xc3},
16}};
void SecurityTest::testPBKDF2()
{
for (const auto& test : pbkdf2s) {
auto h = util::security::HMAC::create(test.pass, test.pass_len);
auto r = util::security::PBKDF2(h.get(), test.salt, test.salt_len,
test.iterations, test.key_len);
const auto kl = test.key_len ? test.key_len : r.length();
auto e = util::security::HMACResult((char*)test.key, kl);
#if 0
printf("actual [%s]  expected [%s]\n",
util::toHex(r.getBytes()).c_str(),
util::toHex(e.getBytes()).c_str()
);
#endif
CPPUNIT_ASSERT(r == e);
CPPUNIT_ASSERT(r.getBytes() == std::string((char*)test.key, kl));
}
}
} // namespace aria2