gcm_encryption_provider_unittest.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. // Copyright 2015 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/gcm_driver/crypto/gcm_encryption_provider.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <sstream>
  8. #include <string>
  9. #include "base/base64.h"
  10. #include "base/base64url.h"
  11. #include "base/big_endian.h"
  12. #include "base/bind.h"
  13. #include "base/callback_helpers.h"
  14. #include "base/files/scoped_temp_dir.h"
  15. #include "base/run_loop.h"
  16. #include "base/strings/string_number_conversions.h"
  17. #include "base/strings/string_piece.h"
  18. #include "base/strings/string_util.h"
  19. #include "base/test/metrics/histogram_tester.h"
  20. #include "base/test/task_environment.h"
  21. #include "base/threading/thread_task_runner_handle.h"
  22. #include "components/gcm_driver/common/gcm_message.h"
  23. #include "components/gcm_driver/crypto/gcm_decryption_result.h"
  24. #include "components/gcm_driver/crypto/gcm_encryption_result.h"
  25. #include "components/gcm_driver/crypto/gcm_key_store.h"
  26. #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
  27. #include "components/gcm_driver/crypto/p256_key_util.h"
  28. #include "crypto/random.h"
  29. #include "testing/gtest/include/gtest/gtest.h"
  30. namespace gcm {
  31. namespace {
  32. const char kExampleAppId[] = "my-app-id";
  33. const char kExampleAuthorizedEntity[] = "my-sender-id";
  34. const char kExampleMessage[] = "Hello, world, this is the GCM Driver!";
  35. const char kValidEncryptionHeader[] =
  36. "keyid=foo;salt=MTIzNDU2Nzg5MDEyMzQ1Ng;rs=1024";
  37. const char kInvalidEncryptionHeader[] = "keyid";
  38. const char kValidCryptoKeyHeader[] =
  39. "keyid=foo;dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbehXM7fqi1OMFefDUEi0eJ"
  40. "vsKfyVBWYkQjH-lSPJKxjAyslg";
  41. const char kValidThreeValueCryptoKeyHeader[] =
  42. "keyid=foo,keyid=bar,keyid=baz;dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbe"
  43. "hXM7fqi1OMFefDUEi0eJvsKfyVBWYkQjH-lSPJKxjAyslg";
  44. const char kInvalidCryptoKeyHeader[] = "keyid";
  45. const char kInvalidThreeValueCryptoKeyHeader[] =
  46. "keyid=foo,dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbehXM7fqi1OMFefDUEi0eJ"
  47. "vsKfyVBWYkQjH-lSPJKxjAyslg,keyid=baz,dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6"
  48. "j88ybbehXM7fqi1OMFefDUEi0eJvsKfyVBWYkQjH-lSPJKxjAyslg";
  49. } // namespace
  50. using ECPrivateKeyUniquePtr = std::unique_ptr<crypto::ECPrivateKey>;
  51. class GCMEncryptionProviderTest : public ::testing::Test {
  52. public:
  53. void SetUp() override {
  54. ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
  55. encryption_provider_ = std::make_unique<GCMEncryptionProvider>();
  56. encryption_provider_->Init(scoped_temp_dir_.GetPath(),
  57. base::ThreadTaskRunnerHandle::Get());
  58. }
  59. void TearDown() override {
  60. encryption_provider_.reset();
  61. // |encryption_provider_| owns a ProtoDatabase whose destructor deletes
  62. // the underlying LevelDB database on the task runner.
  63. base::RunLoop().RunUntilIdle();
  64. }
  65. // To be used as a callback for GCMEncryptionProvider::GetEncryptionInfo().
  66. void DidGetEncryptionInfo(std::string* p256dh_out,
  67. std::string* auth_secret_out,
  68. std::string p256dh,
  69. std::string auth_secret) {
  70. *p256dh_out = std::move(p256dh);
  71. *auth_secret_out = std::move(auth_secret);
  72. }
  73. // To be used as a callback for GCMKeyStore::{GetKeys,CreateKeys}.
  74. void HandleKeysCallback(ECPrivateKeyUniquePtr* key_out,
  75. std::string* auth_secret_out,
  76. ECPrivateKeyUniquePtr key,
  77. const std::string& auth_secret) {
  78. *key_out = std::move(key);
  79. *auth_secret_out = auth_secret;
  80. }
  81. protected:
  82. // Decrypts the |message| and then synchronously waits until either the
  83. // success or failure callbacks has been invoked.
  84. void Decrypt(const IncomingMessage& message) {
  85. encryption_provider_->DecryptMessage(
  86. kExampleAppId, message,
  87. base::BindOnce(&GCMEncryptionProviderTest::DidDecryptMessage,
  88. base::Unretained(this)));
  89. // The encryption keys will be read asynchronously.
  90. base::RunLoop().RunUntilIdle();
  91. }
  92. // Encrypts the |message| and then synchronously waits until either the
  93. // success or failure callbacks has been invoked.
  94. void Encrypt(const std::string& authorized_entity,
  95. const std::string& p256dh,
  96. const std::string& auth_secret,
  97. const std::string& message) {
  98. encryption_provider_->EncryptMessage(
  99. kExampleAppId, authorized_entity, p256dh, auth_secret, message,
  100. base::BindOnce(&GCMEncryptionProviderTest::DidEncryptMessage,
  101. base::Unretained(this)));
  102. // The encryption keys will be read asynchronously.
  103. base::RunLoop().RunUntilIdle();
  104. }
  105. // Checks that the underlying key store has a key for the |kExampleAppId| +
  106. // authorized entity key if and only if |should_have_key| is true. Must wrap
  107. // with ASSERT/EXPECT_NO_FATAL_FAILURE.
  108. void CheckHasKey(const std::string& authorized_entity, bool should_have_key) {
  109. ECPrivateKeyUniquePtr key;
  110. std::string auth_secret;
  111. encryption_provider()->key_store_->GetKeys(
  112. kExampleAppId, authorized_entity,
  113. false /* fallback_to_empty_authorized_entity */,
  114. base::BindOnce(&GCMEncryptionProviderTest::HandleKeysCallback,
  115. base::Unretained(this), &key, &auth_secret));
  116. base::RunLoop().RunUntilIdle();
  117. if (should_have_key) {
  118. ASSERT_TRUE(key);
  119. std::string private_key, public_key;
  120. ASSERT_TRUE(GetRawPrivateKey(*key, &private_key));
  121. ASSERT_TRUE(GetRawPublicKey(*key, &public_key));
  122. ASSERT_GT(public_key.size(), 0u);
  123. ASSERT_GT(private_key.size(), 0u);
  124. ASSERT_GT(auth_secret.size(), 0u);
  125. } else {
  126. ASSERT_FALSE(key);
  127. ASSERT_EQ(0u, auth_secret.size());
  128. }
  129. }
  130. // Returns the result of the previous decryption operation.
  131. GCMDecryptionResult decryption_result() { return decryption_result_; }
  132. // Returns the result of the previous encryption operation.
  133. GCMEncryptionResult encryption_result() { return encryption_result_; }
  134. // Returns the message resulting from the previous decryption operation.
  135. const IncomingMessage& decrypted_message() { return decrypted_message_; }
  136. // Returns the message resulting from the previous encryption operation.
  137. const std::string& encrypted_message() { return encrypted_message_; }
  138. GCMEncryptionProvider* encryption_provider() {
  139. return encryption_provider_.get();
  140. }
  141. // Performs a full round-trip test of the encryption feature. Must wrap this
  142. // in ASSERT_NO_FATAL_FAILURE.
  143. void TestEncryptionRoundTrip(const std::string& app_id,
  144. const std::string& authorized_entity,
  145. GCMMessageCryptographer::Version version,
  146. bool use_internal_raw_data_for_draft08 = false);
  147. // Performs a test encryption feature without creating proper keys. Must wrap
  148. // this in ASSERT_NO_FATAL_FAILURE.
  149. void TestEncryptionNoKeys(const std::string& app_id,
  150. const std::string& authorized_entity);
  151. private:
  152. void DidDecryptMessage(GCMDecryptionResult result, IncomingMessage message) {
  153. decryption_result_ = result;
  154. decrypted_message_ = std::move(message);
  155. }
  156. void DidEncryptMessage(GCMEncryptionResult result, std::string message) {
  157. encryption_result_ = result;
  158. encrypted_message_ = std::move(message);
  159. }
  160. base::test::SingleThreadTaskEnvironment task_environment_;
  161. base::ScopedTempDir scoped_temp_dir_;
  162. base::HistogramTester histogram_tester_;
  163. std::unique_ptr<GCMEncryptionProvider> encryption_provider_;
  164. GCMDecryptionResult decryption_result_ = GCMDecryptionResult::UNENCRYPTED;
  165. GCMEncryptionResult encryption_result_ =
  166. GCMEncryptionResult::ENCRYPTION_FAILED;
  167. IncomingMessage decrypted_message_;
  168. std::string encrypted_message_;
  169. };
  170. TEST_F(GCMEncryptionProviderTest, IsEncryptedMessage) {
  171. // Both the Encryption and Encryption-Key headers must be present, and the raw
  172. // data must be non-empty for a message to be considered encrypted.
  173. IncomingMessage empty_message;
  174. EXPECT_FALSE(encryption_provider()->IsEncryptedMessage(empty_message));
  175. IncomingMessage single_header_message;
  176. single_header_message.data["encryption"] = "";
  177. EXPECT_FALSE(
  178. encryption_provider()->IsEncryptedMessage(single_header_message));
  179. IncomingMessage double_header_message;
  180. double_header_message.data["encryption"] = "";
  181. double_header_message.data["crypto-key"] = "";
  182. EXPECT_FALSE(
  183. encryption_provider()->IsEncryptedMessage(double_header_message));
  184. IncomingMessage double_header_with_data_message;
  185. double_header_with_data_message.data["encryption"] = "";
  186. double_header_with_data_message.data["crypto-key"] = "";
  187. double_header_with_data_message.raw_data = "foo";
  188. EXPECT_TRUE(encryption_provider()->IsEncryptedMessage(
  189. double_header_with_data_message));
  190. IncomingMessage draft08_message;
  191. draft08_message.data["content-encoding"] = "aes128gcm";
  192. draft08_message.raw_data = "foo";
  193. EXPECT_TRUE(encryption_provider()->IsEncryptedMessage(draft08_message));
  194. }
  195. TEST_F(GCMEncryptionProviderTest, VerifiesEncryptionHeaderParsing) {
  196. // The Encryption header must be parsable and contain valid values.
  197. // Note that this is more extensively tested in EncryptionHeaderParsersTest.
  198. IncomingMessage invalid_message;
  199. invalid_message.data["encryption"] = kInvalidEncryptionHeader;
  200. invalid_message.data["crypto-key"] = kValidCryptoKeyHeader;
  201. invalid_message.raw_data = "foo";
  202. ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message));
  203. EXPECT_EQ(GCMDecryptionResult::INVALID_ENCRYPTION_HEADER,
  204. decryption_result());
  205. IncomingMessage valid_message;
  206. valid_message.data["encryption"] = kValidEncryptionHeader;
  207. valid_message.data["crypto-key"] = kInvalidCryptoKeyHeader;
  208. valid_message.raw_data = "foo";
  209. ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
  210. EXPECT_NE(GCMDecryptionResult::INVALID_ENCRYPTION_HEADER,
  211. decryption_result());
  212. }
  213. TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsing) {
  214. // The Crypto-Key header must be parsable and contain valid values.
  215. // Note that this is more extensively tested in EncryptionHeaderParsersTest.
  216. IncomingMessage invalid_message;
  217. invalid_message.data["encryption"] = kValidEncryptionHeader;
  218. invalid_message.data["crypto-key"] = kInvalidCryptoKeyHeader;
  219. invalid_message.raw_data = "foo";
  220. ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message));
  221. EXPECT_EQ(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
  222. decryption_result());
  223. IncomingMessage valid_message;
  224. valid_message.data["encryption"] = kValidEncryptionHeader;
  225. valid_message.data["crypto-key"] = kValidCryptoKeyHeader;
  226. valid_message.raw_data = "foo";
  227. ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
  228. EXPECT_NE(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
  229. decryption_result());
  230. }
  231. TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsingThirdValue) {
  232. // The Crypto-Key header must be parsable and contain valid values, in which
  233. // values will be ignored unless they contain a "dh" property.
  234. IncomingMessage valid_message;
  235. valid_message.data["encryption"] = kValidEncryptionHeader;
  236. valid_message.data["crypto-key"] = kValidThreeValueCryptoKeyHeader;
  237. valid_message.raw_data = "foo";
  238. ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
  239. EXPECT_NE(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
  240. decryption_result());
  241. }
  242. TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderSingleDhEntry) {
  243. // The Crypto-Key header must include at most one value that contains the
  244. // "dh" property. Having more than once occurrence is forbidden.
  245. IncomingMessage valid_message;
  246. valid_message.data["encryption"] = kValidEncryptionHeader;
  247. valid_message.data["crypto-key"] = kInvalidThreeValueCryptoKeyHeader;
  248. valid_message.raw_data = "foo";
  249. ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message));
  250. EXPECT_EQ(GCMDecryptionResult::INVALID_CRYPTO_KEY_HEADER,
  251. decryption_result());
  252. }
  253. TEST_F(GCMEncryptionProviderTest, VerifiesExistingKeys) {
  254. // When both headers are valid, the encryption keys still must be known to
  255. // the GCM key store before the message can be decrypted.
  256. IncomingMessage message;
  257. message.data["encryption"] = kValidEncryptionHeader;
  258. message.data["crypto-key"] = kValidCryptoKeyHeader;
  259. message.raw_data = "foo";
  260. ASSERT_NO_FATAL_FAILURE(Decrypt(message));
  261. EXPECT_EQ(GCMDecryptionResult::NO_KEYS, decryption_result());
  262. std::string public_key, auth_secret;
  263. encryption_provider()->GetEncryptionInfo(
  264. kExampleAppId, "" /* empty authorized entity for non-InstanceID */,
  265. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  266. base::Unretained(this), &public_key, &auth_secret));
  267. // Getting (or creating) the public key will be done asynchronously.
  268. base::RunLoop().RunUntilIdle();
  269. ASSERT_GT(public_key.size(), 0u);
  270. ASSERT_GT(auth_secret.size(), 0u);
  271. ASSERT_NO_FATAL_FAILURE(Decrypt(message));
  272. EXPECT_NE(GCMDecryptionResult::NO_KEYS, decryption_result());
  273. }
  274. TEST_F(GCMEncryptionProviderTest, VerifiesKeyRemovalGCMRegistration) {
  275. // Removing encryption info for an InstanceID token shouldn't affect a
  276. // non-InstanceID GCM registration.
  277. // Non-InstanceID callers pass an empty string for authorized_entity.
  278. std::string authorized_entity_gcm;
  279. std::string authorized_entity_1 = kExampleAuthorizedEntity + std::string("1");
  280. std::string authorized_entity_2 = kExampleAuthorizedEntity + std::string("2");
  281. // Should create encryption info.
  282. std::string public_key, auth_secret;
  283. encryption_provider()->GetEncryptionInfo(
  284. kExampleAppId, authorized_entity_gcm,
  285. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  286. base::Unretained(this), &public_key, &auth_secret));
  287. base::RunLoop().RunUntilIdle();
  288. // Should get encryption info created above.
  289. std::string read_public_key, read_auth_secret;
  290. encryption_provider()->GetEncryptionInfo(
  291. kExampleAppId, authorized_entity_gcm,
  292. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  293. base::Unretained(this), &read_public_key,
  294. &read_auth_secret));
  295. base::RunLoop().RunUntilIdle();
  296. EXPECT_GT(public_key.size(), 0u);
  297. EXPECT_GT(auth_secret.size(), 0u);
  298. EXPECT_EQ(public_key, read_public_key);
  299. EXPECT_EQ(auth_secret, read_auth_secret);
  300. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_gcm, true));
  301. encryption_provider()->RemoveEncryptionInfo(
  302. kExampleAppId, authorized_entity_1, base::DoNothing());
  303. base::RunLoop().RunUntilIdle();
  304. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_gcm, true));
  305. encryption_provider()->RemoveEncryptionInfo(kExampleAppId, "*",
  306. base::DoNothing());
  307. base::RunLoop().RunUntilIdle();
  308. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_gcm, true));
  309. encryption_provider()->RemoveEncryptionInfo(
  310. kExampleAppId, authorized_entity_gcm, base::DoNothing());
  311. base::RunLoop().RunUntilIdle();
  312. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_gcm, false));
  313. }
  314. TEST_F(GCMEncryptionProviderTest, VerifiesKeyRemovalInstanceIDToken) {
  315. // Removing encryption info for a non-InstanceID GCM registration shouldn't
  316. // affect an InstanceID token.
  317. // Non-InstanceID callers pass an empty string for authorized_entity.
  318. std::string authorized_entity_gcm;
  319. std::string authorized_entity_1 = kExampleAuthorizedEntity + std::string("1");
  320. std::string authorized_entity_2 = kExampleAuthorizedEntity + std::string("2");
  321. std::string public_key_1, auth_secret_1;
  322. encryption_provider()->GetEncryptionInfo(
  323. kExampleAppId, authorized_entity_1,
  324. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  325. base::Unretained(this), &public_key_1, &auth_secret_1));
  326. base::RunLoop().RunUntilIdle();
  327. EXPECT_GT(public_key_1.size(), 0u);
  328. EXPECT_GT(auth_secret_1.size(), 0u);
  329. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, true));
  330. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, false));
  331. std::string public_key_2, auth_secret_2;
  332. encryption_provider()->GetEncryptionInfo(
  333. kExampleAppId, authorized_entity_2,
  334. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  335. base::Unretained(this), &public_key_2, &auth_secret_2));
  336. base::RunLoop().RunUntilIdle();
  337. EXPECT_GT(public_key_2.size(), 0u);
  338. EXPECT_GT(auth_secret_2.size(), 0u);
  339. EXPECT_NE(public_key_1, public_key_2);
  340. EXPECT_NE(auth_secret_1, auth_secret_2);
  341. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, true));
  342. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, true));
  343. std::string read_public_key_1, read_auth_secret_1;
  344. encryption_provider()->GetEncryptionInfo(
  345. kExampleAppId, authorized_entity_1,
  346. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  347. base::Unretained(this), &read_public_key_1,
  348. &read_auth_secret_1));
  349. base::RunLoop().RunUntilIdle();
  350. // Should have returned existing info for authorized_entity_1.
  351. EXPECT_EQ(public_key_1, read_public_key_1);
  352. EXPECT_EQ(auth_secret_1, read_auth_secret_1);
  353. encryption_provider()->RemoveEncryptionInfo(
  354. kExampleAppId, authorized_entity_gcm, base::DoNothing());
  355. base::RunLoop().RunUntilIdle();
  356. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, true));
  357. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, true));
  358. encryption_provider()->RemoveEncryptionInfo(
  359. kExampleAppId, authorized_entity_1, base::DoNothing());
  360. base::RunLoop().RunUntilIdle();
  361. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, false));
  362. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, true));
  363. std::string public_key_1_refreshed, auth_secret_1_refreshed;
  364. encryption_provider()->GetEncryptionInfo(
  365. kExampleAppId, authorized_entity_1,
  366. base::BindOnce(&GCMEncryptionProviderTest::DidGetEncryptionInfo,
  367. base::Unretained(this), &public_key_1_refreshed,
  368. &auth_secret_1_refreshed));
  369. base::RunLoop().RunUntilIdle();
  370. // Since the info was removed, GetEncryptionInfo should have created new info.
  371. EXPECT_GT(public_key_1_refreshed.size(), 0u);
  372. EXPECT_GT(auth_secret_1_refreshed.size(), 0u);
  373. EXPECT_NE(public_key_1, public_key_1_refreshed);
  374. EXPECT_NE(auth_secret_1, auth_secret_1_refreshed);
  375. EXPECT_NE(public_key_2, public_key_1_refreshed);
  376. EXPECT_NE(auth_secret_2, auth_secret_1_refreshed);
  377. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, true));
  378. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, true));
  379. encryption_provider()->RemoveEncryptionInfo(kExampleAppId, "*",
  380. base::DoNothing());
  381. base::RunLoop().RunUntilIdle();
  382. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, false));
  383. ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, false));
  384. }
  385. void GCMEncryptionProviderTest::TestEncryptionRoundTrip(
  386. const std::string& app_id,
  387. const std::string& authorized_entity,
  388. GCMMessageCryptographer::Version version,
  389. bool use_internal_raw_data_for_draft08) {
  390. // Performs a full round-trip of the encryption feature, including getting a
  391. // public/private key-key and performing the cryptographic operations. This
  392. // is more of an integration test than a unit test.
  393. ECPrivateKeyUniquePtr key, server_key;
  394. std::string auth_secret, server_authentication;
  395. // Retrieve the public/private key-key immediately from the key store, given
  396. // that the GCMEncryptionProvider will only share the public key with users.
  397. // Also create a second key, which will act as the server's keys.
  398. encryption_provider()->key_store_->CreateKeys(
  399. app_id, authorized_entity,
  400. base::BindOnce(&GCMEncryptionProviderTest::HandleKeysCallback,
  401. base::Unretained(this), &key, &auth_secret));
  402. encryption_provider()->key_store_->CreateKeys(
  403. "server-" + app_id, authorized_entity,
  404. base::BindOnce(&GCMEncryptionProviderTest::HandleKeysCallback,
  405. base::Unretained(this), &server_key,
  406. &server_authentication));
  407. // Creating the public keys will be done asynchronously.
  408. base::RunLoop().RunUntilIdle();
  409. std::string public_key, server_public_key;
  410. ASSERT_TRUE(GetRawPublicKey(*key, &public_key));
  411. ASSERT_TRUE(GetRawPublicKey(*server_key, &server_public_key));
  412. ASSERT_GT(public_key.size(), 0u);
  413. ASSERT_GT(server_public_key.size(), 0u);
  414. std::string private_key, server_private_key;
  415. ASSERT_TRUE(GetRawPublicKey(*key, &private_key));
  416. ASSERT_TRUE(GetRawPublicKey(*server_key, &server_private_key));
  417. ASSERT_GT(private_key.size(), 0u);
  418. ASSERT_GT(server_private_key.size(), 0u);
  419. IncomingMessage message;
  420. message.sender_id = authorized_entity;
  421. switch (version) {
  422. case GCMMessageCryptographer::Version::DRAFT_03: {
  423. std::string salt;
  424. // Creates a cryptographically secure salt of |salt_size| octets in size,
  425. // and calculate the shared secret for the message.
  426. crypto::RandBytes(base::WriteInto(&salt, 16 + 1), 16);
  427. std::string shared_secret;
  428. ASSERT_TRUE(
  429. ComputeSharedP256Secret(*key, server_public_key, &shared_secret));
  430. size_t record_size;
  431. // Encrypts the |kExampleMessage| using the generated shared key and the
  432. // random |salt|, storing the result in |record_size| and the message.
  433. GCMMessageCryptographer cryptographer(version);
  434. std::string ciphertext;
  435. ASSERT_TRUE(cryptographer.Encrypt(
  436. public_key, server_public_key, shared_secret, auth_secret, salt,
  437. kExampleMessage, &record_size, &ciphertext));
  438. std::string encoded_salt, encoded_key;
  439. // Compile the incoming GCM message, including the required headers.
  440. base::Base64UrlEncode(salt, base::Base64UrlEncodePolicy::INCLUDE_PADDING,
  441. &encoded_salt);
  442. base::Base64UrlEncode(server_public_key,
  443. base::Base64UrlEncodePolicy::INCLUDE_PADDING,
  444. &encoded_key);
  445. std::stringstream encryption_header;
  446. encryption_header << "rs=" << base::NumberToString(record_size) << ";";
  447. encryption_header << "salt=" << encoded_salt;
  448. message.data["encryption"] = encryption_header.str();
  449. message.data["crypto-key"] = "dh=" + encoded_key;
  450. message.raw_data.swap(ciphertext);
  451. break;
  452. }
  453. case GCMMessageCryptographer::Version::DRAFT_08: {
  454. ASSERT_NO_FATAL_FAILURE(
  455. Encrypt(authorized_entity, public_key, auth_secret, kExampleMessage));
  456. ASSERT_EQ(GCMEncryptionResult::ENCRYPTED_DRAFT_08, encryption_result());
  457. message.data["content-encoding"] = "aes128gcm";
  458. if (use_internal_raw_data_for_draft08) {
  459. std::string raw_data_base64;
  460. base::Base64Encode(encrypted_message(), &raw_data_base64);
  461. message.data["_googRawData"] = raw_data_base64;
  462. } else {
  463. message.raw_data = encrypted_message();
  464. }
  465. break;
  466. }
  467. }
  468. ASSERT_TRUE(encryption_provider()->IsEncryptedMessage(message));
  469. // Decrypt the message, and expect everything to go wonderfully well.
  470. ASSERT_NO_FATAL_FAILURE(Decrypt(message));
  471. ASSERT_EQ(version == GCMMessageCryptographer::Version::DRAFT_03
  472. ? GCMDecryptionResult::DECRYPTED_DRAFT_03
  473. : GCMDecryptionResult::DECRYPTED_DRAFT_08,
  474. decryption_result());
  475. EXPECT_TRUE(decrypted_message().decrypted);
  476. EXPECT_EQ(kExampleMessage, decrypted_message().raw_data);
  477. }
  478. void GCMEncryptionProviderTest::TestEncryptionNoKeys(
  479. const std::string& app_id,
  480. const std::string& authorized_entity) {
  481. // Only create proper keys for receipeint without creating keys for sender.
  482. ECPrivateKeyUniquePtr key;
  483. std::string auth_secret;
  484. encryption_provider()->key_store_->CreateKeys(
  485. "receiver" + app_id, authorized_entity,
  486. base::BindOnce(&GCMEncryptionProviderTest::HandleKeysCallback,
  487. base::Unretained(this), &key, &auth_secret));
  488. // Creating the public keys will be done asynchronously.
  489. base::RunLoop().RunUntilIdle();
  490. std::string public_key;
  491. ASSERT_TRUE(GetRawPublicKey(*key, &public_key));
  492. ASSERT_GT(public_key.size(), 0u);
  493. ASSERT_NO_FATAL_FAILURE(
  494. Encrypt(authorized_entity, public_key, auth_secret, kExampleMessage));
  495. EXPECT_EQ(GCMEncryptionResult::NO_KEYS, encryption_result());
  496. }
  497. TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripGCMRegistration) {
  498. // GCMEncryptionProvider::DecryptMessage should succeed when the message was
  499. // sent to a non-InstanceID GCM registration (empty authorized_entity).
  500. ASSERT_NO_FATAL_FAILURE(TestEncryptionRoundTrip(
  501. kExampleAppId, "" /* empty authorized entity for non-InstanceID */,
  502. GCMMessageCryptographer::Version::DRAFT_03));
  503. }
  504. TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripInstanceIDToken) {
  505. // GCMEncryptionProvider::DecryptMessage should succeed when the message was
  506. // sent to an InstanceID token (non-empty authorized_entity).
  507. ASSERT_NO_FATAL_FAILURE(
  508. TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity,
  509. GCMMessageCryptographer::Version::DRAFT_03));
  510. }
  511. TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripDraft08) {
  512. // GCMEncryptionProvider::DecryptMessage should succeed when the message was
  513. // encrypted following raft-ietf-webpush-encryption-08.
  514. ASSERT_NO_FATAL_FAILURE(
  515. TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity,
  516. GCMMessageCryptographer::Version::DRAFT_08));
  517. }
  518. TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripDraft08InternalRawData) {
  519. // GCMEncryptionProvider::DecryptMessage should succeed when the message was
  520. // encrypted following raft-ietf-webpush-encryption-08 with raw_data base64
  521. // encoded in message data.
  522. ASSERT_NO_FATAL_FAILURE(
  523. TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity,
  524. GCMMessageCryptographer::Version::DRAFT_08,
  525. /*use_internal_raw_data_for_draft08=*/true));
  526. }
  527. TEST_F(GCMEncryptionProviderTest, EncryptionNoKeys) {
  528. ASSERT_NO_FATAL_FAILURE(
  529. TestEncryptionNoKeys(kExampleAppId, kExampleAuthorizedEntity));
  530. }
  531. } // namespace gcm