os_crypt_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/os_crypt/os_crypt.h"
  5. #include <string>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "base/compiler_specific.h"
  9. #include "base/strings/string_util.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "base/task/single_thread_task_runner.h"
  12. #include "base/threading/thread.h"
  13. #include "build/build_config.h"
  14. #include "build/chromeos_buildflags.h"
  15. #include "components/os_crypt/os_crypt_mocker.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
  18. // of lacros-chrome is complete.
  19. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  20. #include "components/os_crypt/os_crypt_mocker_linux.h"
  21. #endif
  22. #if BUILDFLAG(IS_WIN)
  23. #include "components/prefs/testing_pref_service.h"
  24. #include "crypto/random.h"
  25. #endif
  26. namespace {
  27. class OSCryptTest : public testing::Test {
  28. public:
  29. OSCryptTest() { OSCryptMocker::SetUp(); }
  30. OSCryptTest(const OSCryptTest&) = delete;
  31. OSCryptTest& operator=(const OSCryptTest&) = delete;
  32. ~OSCryptTest() override { OSCryptMocker::TearDown(); }
  33. };
  34. TEST_F(OSCryptTest, String16EncryptionDecryption) {
  35. std::u16string plaintext;
  36. std::u16string result;
  37. std::string utf8_plaintext;
  38. std::string utf8_result;
  39. std::string ciphertext;
  40. // Test borderline cases (empty strings).
  41. EXPECT_TRUE(OSCrypt::EncryptString16(plaintext, &ciphertext));
  42. EXPECT_TRUE(OSCrypt::DecryptString16(ciphertext, &result));
  43. EXPECT_EQ(plaintext, result);
  44. // Test a simple string.
  45. plaintext = u"hello";
  46. EXPECT_TRUE(OSCrypt::EncryptString16(plaintext, &ciphertext));
  47. EXPECT_TRUE(OSCrypt::DecryptString16(ciphertext, &result));
  48. EXPECT_EQ(plaintext, result);
  49. // Test a 16-byte aligned string. This previously hit a boundary error in
  50. // base::OSCrypt::Crypt() on Mac.
  51. plaintext = u"1234567890123456";
  52. EXPECT_TRUE(OSCrypt::EncryptString16(plaintext, &ciphertext));
  53. EXPECT_TRUE(OSCrypt::DecryptString16(ciphertext, &result));
  54. EXPECT_EQ(plaintext, result);
  55. // Test Unicode.
  56. char16_t wchars[] = {0xdbeb, 0xdf1b, 0x4e03, 0x6708, 0x8849, 0x661f, 0x671f,
  57. 0x56db, 0x597c, 0x4e03, 0x6708, 0x56db, 0x6708, 0xe407,
  58. 0xdbaf, 0xdeb5, 0x4ec5, 0x544b, 0x661f, 0x671f, 0x65e5,
  59. 0x661f, 0x671f, 0x4e94, 0xd8b1, 0xdce1, 0x7052, 0x5095,
  60. 0x7c0b, 0xe586, 0};
  61. plaintext = wchars;
  62. utf8_plaintext = base::UTF16ToUTF8(plaintext);
  63. EXPECT_EQ(plaintext, base::UTF8ToUTF16(utf8_plaintext));
  64. EXPECT_TRUE(OSCrypt::EncryptString16(plaintext, &ciphertext));
  65. EXPECT_TRUE(OSCrypt::DecryptString16(ciphertext, &result));
  66. EXPECT_EQ(plaintext, result);
  67. EXPECT_TRUE(OSCrypt::DecryptString(ciphertext, &utf8_result));
  68. EXPECT_EQ(utf8_plaintext, base::UTF16ToUTF8(result));
  69. EXPECT_TRUE(OSCrypt::EncryptString(utf8_plaintext, &ciphertext));
  70. EXPECT_TRUE(OSCrypt::DecryptString16(ciphertext, &result));
  71. EXPECT_EQ(plaintext, result);
  72. EXPECT_TRUE(OSCrypt::DecryptString(ciphertext, &utf8_result));
  73. EXPECT_EQ(utf8_plaintext, base::UTF16ToUTF8(result));
  74. }
  75. TEST_F(OSCryptTest, EncryptionDecryption) {
  76. std::string plaintext;
  77. std::string result;
  78. std::string ciphertext;
  79. // Test borderline cases (empty strings).
  80. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  81. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &result));
  82. EXPECT_EQ(plaintext, result);
  83. // Test a simple string.
  84. plaintext = "hello";
  85. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  86. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &result));
  87. EXPECT_EQ(plaintext, result);
  88. // Make sure it null terminates.
  89. plaintext.assign("hello", 3);
  90. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  91. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &result));
  92. EXPECT_EQ(plaintext, "hel");
  93. }
  94. TEST_F(OSCryptTest, CypherTextDiffers) {
  95. std::string plaintext;
  96. std::string result;
  97. std::string ciphertext;
  98. // Test borderline cases (empty strings).
  99. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  100. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &result));
  101. // |cyphertext| is empty on the Mac, different on Windows.
  102. EXPECT_TRUE(ciphertext.empty() || plaintext != ciphertext);
  103. EXPECT_EQ(plaintext, result);
  104. // Test a simple string.
  105. plaintext = "hello";
  106. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  107. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &result));
  108. EXPECT_NE(plaintext, ciphertext);
  109. EXPECT_EQ(plaintext, result);
  110. // Make sure it null terminates.
  111. plaintext.assign("hello", 3);
  112. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  113. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &result));
  114. EXPECT_NE(plaintext, ciphertext);
  115. EXPECT_EQ(result, "hel");
  116. }
  117. TEST_F(OSCryptTest, DecryptError) {
  118. std::string plaintext;
  119. std::string result;
  120. std::string ciphertext;
  121. // Test a simple string, messing with ciphertext prior to decrypting.
  122. plaintext = "hello";
  123. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  124. EXPECT_NE(plaintext, ciphertext);
  125. ASSERT_LT(4UL, ciphertext.size());
  126. ciphertext[3] = ciphertext[3] + 1;
  127. EXPECT_FALSE(OSCrypt::DecryptString(ciphertext, &result));
  128. EXPECT_NE(plaintext, result);
  129. EXPECT_TRUE(result.empty());
  130. }
  131. class OSCryptConcurrencyTest : public testing::Test {
  132. public:
  133. OSCryptConcurrencyTest() { OSCryptMocker::SetUp(); }
  134. OSCryptConcurrencyTest(const OSCryptConcurrencyTest&) = delete;
  135. OSCryptConcurrencyTest& operator=(const OSCryptConcurrencyTest&) = delete;
  136. ~OSCryptConcurrencyTest() override { OSCryptMocker::TearDown(); }
  137. };
  138. // Flaky on Win 7 (dbg) and win-asan, see https://crbug.com/1066699
  139. #if BUILDFLAG(IS_WIN)
  140. #define MAYBE_ConcurrentInitialization DISABLED_ConcurrentInitialization
  141. #else
  142. #define MAYBE_ConcurrentInitialization ConcurrentInitialization
  143. #endif
  144. TEST_F(OSCryptConcurrencyTest, MAYBE_ConcurrentInitialization) {
  145. // Launch multiple threads
  146. base::Thread thread1("thread1");
  147. base::Thread thread2("thread2");
  148. std::vector<base::Thread*> threads = {&thread1, &thread2};
  149. for (base::Thread* thread : threads) {
  150. ASSERT_TRUE(thread->Start());
  151. }
  152. // Make calls.
  153. for (base::Thread* thread : threads) {
  154. ASSERT_TRUE(thread->task_runner()->PostTask(
  155. FROM_HERE, base::BindOnce([]() -> void {
  156. std::string plaintext = "secrets";
  157. std::string encrypted;
  158. std::string decrypted;
  159. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &encrypted));
  160. ASSERT_TRUE(OSCrypt::DecryptString(encrypted, &decrypted));
  161. ASSERT_EQ(plaintext, decrypted);
  162. })));
  163. }
  164. // Cleanup
  165. for (base::Thread* thread : threads) {
  166. thread->Stop();
  167. }
  168. }
  169. #if BUILDFLAG(IS_WIN)
  170. class OSCryptTestWin : public testing::Test {
  171. public:
  172. OSCryptTestWin() {}
  173. OSCryptTestWin(const OSCryptTestWin&) = delete;
  174. OSCryptTestWin& operator=(const OSCryptTestWin&) = delete;
  175. ~OSCryptTestWin() override { OSCryptMocker::ResetState(); }
  176. };
  177. // This test verifies that the header of the data returned from CryptProtectData
  178. // never collides with the kEncryptionVersionPrefix ("v10") used in
  179. // os_crypt_win.cc. If this ever happened, we would not be able to distinguish
  180. // between data encrypted using the legacy DPAPI interface, and data that's been
  181. // encrypted with the new session key.
  182. // If this test ever breaks do not ignore it as it might result in data loss for
  183. // users.
  184. TEST_F(OSCryptTestWin, DPAPIHeader) {
  185. std::string plaintext;
  186. std::string ciphertext;
  187. OSCryptMocker::SetLegacyEncryption(true);
  188. crypto::RandBytes(base::WriteInto(&plaintext, 11), 10);
  189. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  190. using std::string_literals::operator""s;
  191. const std::string expected_header("\x01\x00\x00\x00"s);
  192. ASSERT_EQ(4U, expected_header.length());
  193. ASSERT_TRUE(ciphertext.length() >= expected_header.length());
  194. std::string dpapi_header = ciphertext.substr(0, expected_header.length());
  195. EXPECT_EQ(expected_header, dpapi_header);
  196. }
  197. TEST_F(OSCryptTestWin, ReadOldData) {
  198. OSCryptMocker::SetLegacyEncryption(true);
  199. std::string plaintext = "secrets";
  200. std::string legacy_ciphertext;
  201. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &legacy_ciphertext));
  202. OSCryptMocker::SetLegacyEncryption(false);
  203. TestingPrefServiceSimple pref_service_simple;
  204. OSCrypt::RegisterLocalPrefs(pref_service_simple.registry());
  205. ASSERT_TRUE(OSCrypt::Init(&pref_service_simple));
  206. std::string decrypted;
  207. // Should be able to decrypt data encrypted with DPAPI.
  208. ASSERT_TRUE(OSCrypt::DecryptString(legacy_ciphertext, &decrypted));
  209. EXPECT_EQ(plaintext, decrypted);
  210. // Should now encrypt same plaintext to get different ciphertext.
  211. std::string new_ciphertext;
  212. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &new_ciphertext));
  213. // Should be different from DPAPI ciphertext.
  214. EXPECT_NE(legacy_ciphertext, new_ciphertext);
  215. // Decrypt new ciphertext to give original string.
  216. ASSERT_TRUE(OSCrypt::DecryptString(new_ciphertext, &decrypted));
  217. EXPECT_EQ(plaintext, decrypted);
  218. }
  219. TEST_F(OSCryptTestWin, PrefsKeyTest) {
  220. TestingPrefServiceSimple first_prefs;
  221. OSCrypt::RegisterLocalPrefs(first_prefs.registry());
  222. // Verify new random key can be generated.
  223. ASSERT_TRUE(OSCrypt::Init(&first_prefs));
  224. std::string first_key = OSCrypt::GetRawEncryptionKey();
  225. std::string plaintext = "secrets";
  226. std::string ciphertext;
  227. ASSERT_TRUE(OSCrypt::EncryptString(plaintext, &ciphertext));
  228. TestingPrefServiceSimple second_prefs;
  229. OSCrypt::RegisterLocalPrefs(second_prefs.registry());
  230. OSCryptMocker::ResetState();
  231. ASSERT_TRUE(OSCrypt::Init(&second_prefs));
  232. std::string second_key = OSCrypt::GetRawEncryptionKey();
  233. // Keys should be different since they are random.
  234. EXPECT_NE(first_key, second_key);
  235. std::string decrypted;
  236. // Cannot decrypt with the wrong key.
  237. EXPECT_FALSE(OSCrypt::DecryptString(ciphertext, &decrypted));
  238. // Initialize OSCrypt from existing key.
  239. OSCryptMocker::ResetState();
  240. OSCrypt::SetRawEncryptionKey(first_key);
  241. // Verify decryption works with first key.
  242. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decrypted));
  243. EXPECT_EQ(plaintext, decrypted);
  244. // Initialize OSCrypt from existing prefs.
  245. OSCryptMocker::ResetState();
  246. ASSERT_TRUE(OSCrypt::Init(&first_prefs));
  247. // Verify decryption works with key from first prefs.
  248. ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decrypted));
  249. EXPECT_EQ(plaintext, decrypted);
  250. }
  251. #endif // BUILDFLAG(IS_WIN)
  252. } // namespace