mirror of https://github.com/oxen-io/lokinet
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
347 lines
8.6 KiB
C++
347 lines
8.6 KiB
C++
#include <crypto/types.hpp>
|
|
|
|
#include <fstream>
|
|
#include <string>
|
|
|
|
#include <test_util.hpp>
|
|
#include <gtest/gtest.h>
|
|
|
|
// This used to be implied via the headers above *shrug*
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
struct ToStringData
|
|
{
|
|
llarp::PubKey::Data input;
|
|
std::string output;
|
|
};
|
|
|
|
struct PubKeyString : public ::testing::TestWithParam< ToStringData >
|
|
{
|
|
};
|
|
|
|
TEST_P(PubKeyString, tostring)
|
|
{
|
|
auto d = GetParam();
|
|
llarp::PubKey key(d.input);
|
|
|
|
ASSERT_EQ(key.ToString(), d.output);
|
|
}
|
|
|
|
TEST_P(PubKeyString, fromstring)
|
|
{
|
|
auto d = GetParam();
|
|
|
|
llarp::PubKey key;
|
|
|
|
ASSERT_TRUE(key.FromString(d.output));
|
|
ASSERT_EQ(key, llarp::PubKey(d.input));
|
|
}
|
|
|
|
llarp::PubKey::Data empty = {};
|
|
llarp::PubKey::Data full = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
|
|
|
// clang-format off
|
|
ToStringData toStringData[] = {
|
|
{empty, "0000000000000000000000000000000000000000000000000000000000000000"},
|
|
{full, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
|
|
};
|
|
// clang-format on
|
|
|
|
INSTANTIATE_TEST_CASE_P(TestCryptoTypes, PubKeyString,
|
|
::testing::ValuesIn(toStringData), );
|
|
|
|
// Concerns
|
|
// - file missing
|
|
// - file empty
|
|
// - file too small
|
|
// - file too large
|
|
// - raw buffer
|
|
// - bencoded
|
|
|
|
struct TestCryptoTypesSecret : public ::testing::Test
|
|
{
|
|
std::string filename;
|
|
fs::path p;
|
|
|
|
TestCryptoTypesSecret() : filename(llarp::test::randFilename()), p(filename)
|
|
{
|
|
}
|
|
};
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_missing)
|
|
{
|
|
// Verify loading an empty file fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't create a file
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_empty)
|
|
{
|
|
// Verify loading an empty file fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_smaller)
|
|
{
|
|
// Verify loading a file which is too small fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), llarp::SecretKey::SIZE / 2,
|
|
0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_smaller_bencode)
|
|
{
|
|
// Verify loading a file which is too small fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
f.write("32:", 3);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), 32, 0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_smaller_corrupt_bencode)
|
|
{
|
|
// Verify loading a file which is too small + corrupt fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
f.write("256:", 4);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), 32, 0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_larger)
|
|
{
|
|
// Verify loading a file which is too large fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), llarp::SecretKey::SIZE * 2,
|
|
0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_larger_bencode)
|
|
{
|
|
// Verify loading a file which is too large fails cleanly.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
f.write("256:", 4);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), 256, 0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_happy_raw)
|
|
{
|
|
// Verify loading a valid raw file succeeds.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), llarp::SecretKey::SIZE, 0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_TRUE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_from_file_happy_bencode)
|
|
{
|
|
// Verify loading a valid bencoded file succeeds.
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
// Create empty file
|
|
std::fstream f;
|
|
f.open(filename, std::ios::out | std::ios::binary);
|
|
f.write("64:", 4);
|
|
std::fill_n(std::ostream_iterator< byte_t >(f), llarp::SecretKey::SIZE, 0xAA);
|
|
f.close();
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_TRUE(key.LoadFromFile(filename.c_str()));
|
|
|
|
// Verify we didn't delete the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
// Save to file
|
|
|
|
// Concerns
|
|
// - file not writeable
|
|
// - happy path
|
|
|
|
// Win32: check for root/admin/elevation privileges
|
|
#ifdef _WIN32
|
|
BOOL
|
|
IsRunAsAdmin()
|
|
{
|
|
BOOL fIsRunAsAdmin = FALSE;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
PSID pAdministratorsGroup = NULL;
|
|
|
|
// Allocate and initialize a SID of the administrators group.
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
if(!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
|
|
&pAdministratorsGroup))
|
|
{
|
|
dwError = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Determine whether the SID of administrators group is enabled in
|
|
// the primary access token of the process.
|
|
if(!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin))
|
|
{
|
|
dwError = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
// Centralized cleanup for all allocated resources.
|
|
if(pAdministratorsGroup)
|
|
{
|
|
FreeSid(pAdministratorsGroup);
|
|
pAdministratorsGroup = NULL;
|
|
}
|
|
|
|
// Throw the error if something failed in the function.
|
|
if(ERROR_SUCCESS != dwError)
|
|
{
|
|
throw dwError;
|
|
}
|
|
|
|
return fIsRunAsAdmin;
|
|
}
|
|
#endif
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_to_missing_file)
|
|
{
|
|
// Verify writing to an unwritable file fails.
|
|
// Assume we're not running as root, so can't write to [C:]/
|
|
// if we are root just skip this test
|
|
#ifndef _WIN32
|
|
if(getuid() == 0)
|
|
return;
|
|
#else
|
|
if(IsRunAsAdmin())
|
|
return;
|
|
#endif
|
|
filename = "/" + filename;
|
|
p = filename;
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
ASSERT_FALSE(key.SaveToFile(filename.c_str()));
|
|
|
|
// Verify we didn't create the file
|
|
ASSERT_FALSE(fs::exists(fs::status(fs::path(filename))));
|
|
}
|
|
|
|
TEST_F(TestCryptoTypesSecret, secret_key_to_file)
|
|
{
|
|
ASSERT_FALSE(fs::exists(fs::status(p)));
|
|
|
|
llarp::test::FileGuard guard(p);
|
|
|
|
llarp::SecretKey key;
|
|
key.Randomize();
|
|
ASSERT_TRUE(key.SaveToFile(filename.c_str()));
|
|
|
|
// Verify we created the file
|
|
ASSERT_TRUE(fs::exists(fs::status(fs::path(filename))));
|
|
|
|
llarp::SecretKey other;
|
|
other.LoadFromFile(filename.c_str());
|
|
|
|
ASSERT_EQ(other, key);
|
|
}
|