#include #include #include #include #include // This used to be implied via the headers above *shrug* #ifdef _WIN32 #include #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); }