#include "components/os_crypt/sync/os_crypt.h"
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/os_crypt/sync/os_crypt_mocker.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
#include "components/os_crypt/sync/os_crypt_mocker_linux.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "components/prefs/testing_pref_service.h"
#include "crypto/random.h"
#endif
namespace {
class OSCryptTest : public testing::Test { … };
TEST_F(OSCryptTest, String16EncryptionDecryption) { … }
TEST_F(OSCryptTest, EncryptionDecryption) { … }
TEST_F(OSCryptTest, CypherTextDiffers) { … }
TEST_F(OSCryptTest, DecryptError) { … }
class OSCryptConcurrencyTest : public testing::Test { … };
#if BUILDFLAG(IS_WIN)
#define MAYBE_ConcurrentInitialization …
#else
#define MAYBE_ConcurrentInitialization …
#endif
TEST_F(OSCryptConcurrencyTest, MAYBE_ConcurrentInitialization) { … }
#if BUILDFLAG(IS_WIN)
class OSCryptTestWin : public testing::Test {
public:
OSCryptTestWin() {}
OSCryptTestWin(const OSCryptTestWin&) = delete;
OSCryptTestWin& operator=(const OSCryptTestWin&) = delete;
~OSCryptTestWin() override { OSCryptMocker::ResetState(); }
};
TEST_F(OSCryptTestWin, DPAPIHeader) {
OSCryptMocker::SetLegacyEncryption(true);
std::string plaintext(10, '\0');
crypto::RandBytes(base::as_writable_byte_span(plaintext));
std::string ciphertext;
ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
using std::string_literals::operator""s;
const std::string expected_header("\x01\x00\x00\x00"s);
ASSERT_EQ(4U, expected_header.length());
ASSERT_TRUE(ciphertext.length() >= expected_header.length());
std::string dpapi_header = ciphertext.substr(0, expected_header.length());
EXPECT_EQ(expected_header, dpapi_header);
}
TEST_F(OSCryptTestWin, ReadOldData) {
OSCryptMocker::SetLegacyEncryption(true);
std::string plaintext = "secrets";
std::string legacy_ciphertext;
ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &legacy_ciphertext));
OSCryptMocker::SetLegacyEncryption(false);
TestingPrefServiceSimple pref_service_simple;
OSCrypt::RegisterLocalPrefs(pref_service_simple.registry());
ASSERT_TRUE(OSCrypt::Init(&pref_service_simple));
std::string decrypted;
ASSERT_TRUE(OSCrypt::DecryptString(legacy_ciphertext, &decrypted));
EXPECT_EQ(plaintext, decrypted);
std::string new_ciphertext;
ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &new_ciphertext));
EXPECT_NE(legacy_ciphertext, new_ciphertext);
ASSERT_TRUE(OSCrypt::DecryptString(new_ciphertext, &decrypted));
EXPECT_EQ(plaintext, decrypted);
}
TEST_F(OSCryptTestWin, PrefsKeyTest) {
TestingPrefServiceSimple first_prefs;
OSCrypt::RegisterLocalPrefs(first_prefs.registry());
ASSERT_TRUE(OSCrypt::Init(&first_prefs));
std::string first_key = OSCrypt::GetRawEncryptionKey();
std::string plaintext = "secrets";
std::string ciphertext;
ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
TestingPrefServiceSimple second_prefs;
OSCrypt::RegisterLocalPrefs(second_prefs.registry());
OSCryptMocker::ResetState();
ASSERT_TRUE(OSCrypt::Init(&second_prefs));
std::string second_key = OSCrypt::GetRawEncryptionKey();
EXPECT_NE(first_key, second_key);
std::string decrypted;
EXPECT_FALSE(OSCrypt::DecryptString(ciphertext, &decrypted));
OSCryptMocker::ResetState();
OSCrypt::SetRawEncryptionKey(first_key);
ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decrypted));
EXPECT_EQ(plaintext, decrypted);
OSCryptMocker::ResetState();
ASSERT_TRUE(OSCrypt::Init(&first_prefs));
ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decrypted));
EXPECT_EQ(plaintext, decrypted);
}
TEST_F(OSCryptTestWin, AuditMigrationTest) {
constexpr char kOsCryptEncryptedKeyPrefName[] = "os_crypt.encrypted_key";
constexpr char kOsCryptAuditEnabledPrefName[] = "os_crypt.audit_enabled";
TestingPrefServiceSimple prefs;
OSCrypt::RegisterLocalPrefs(prefs.registry());
ASSERT_TRUE(OSCrypt::Init(&prefs));
EXPECT_TRUE(prefs.GetBoolean(kOsCryptAuditEnabledPrefName));
auto encrypted_key = prefs.GetString(kOsCryptEncryptedKeyPrefName);
EXPECT_TRUE(!encrypted_key.empty());
OSCrypt::ResetStateForTesting();
prefs.ClearPref(kOsCryptAuditEnabledPrefName);
ASSERT_TRUE(OSCrypt::Init(&prefs));
EXPECT_TRUE(prefs.GetBoolean(kOsCryptAuditEnabledPrefName));
auto encrypted_key2 = prefs.GetString(kOsCryptEncryptedKeyPrefName);
EXPECT_TRUE(!encrypted_key2.empty());
EXPECT_NE(encrypted_key, encrypted_key2);
OSCrypt::ResetStateForTesting();
ASSERT_TRUE(OSCrypt::Init(&prefs));
auto encrypted_key3 = prefs.GetString(kOsCryptEncryptedKeyPrefName);
EXPECT_EQ(encrypted_key2, encrypted_key3);
}
#endif
}