| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/gcm_driver/crypto/gcm_encryption_provider.h" | 5 #include "components/gcm_driver/crypto/gcm_encryption_provider.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "base/base64url.h" | 12 #include "base/base64url.h" |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/files/scoped_temp_dir.h" | 14 #include "base/files/scoped_temp_dir.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_piece.h" | 18 #include "base/strings/string_piece.h" |
| 19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 20 #include "base/test/histogram_tester.h" |
| 20 #include "components/gcm_driver/common/gcm_messages.h" | 21 #include "components/gcm_driver/common/gcm_messages.h" |
| 21 #include "components/gcm_driver/crypto/gcm_key_store.h" | 22 #include "components/gcm_driver/crypto/gcm_key_store.h" |
| 22 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h" | 23 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h" |
| 23 #include "components/gcm_driver/crypto/p256_key_util.h" | 24 #include "components/gcm_driver/crypto/p256_key_util.h" |
| 24 #include "crypto/random.h" | 25 #include "crypto/random.h" |
| 25 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 26 | 27 |
| 27 namespace gcm { | 28 namespace gcm { |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 } | 70 } |
| 70 | 71 |
| 71 // To be used as a callback for GCMKeyStore::CreateKeys(). | 72 // To be used as a callback for GCMKeyStore::CreateKeys(). |
| 72 void DidCreateKeys(KeyPair* pair_out, std::string* auth_secret_out, | 73 void DidCreateKeys(KeyPair* pair_out, std::string* auth_secret_out, |
| 73 const KeyPair& pair, const std::string& auth_secret) { | 74 const KeyPair& pair, const std::string& auth_secret) { |
| 74 *pair_out = pair; | 75 *pair_out = pair; |
| 75 *auth_secret_out = auth_secret; | 76 *auth_secret_out = auth_secret; |
| 76 } | 77 } |
| 77 | 78 |
| 78 protected: | 79 protected: |
| 79 // Tri-state enumaration listing whether the decryption operation is idle | |
| 80 // (hasn't started yet), succeeded or failed. | |
| 81 enum DecryptionResult { | |
| 82 DECRYPTION_IDLE, | |
| 83 DECRYPTION_SUCCEEDED, | |
| 84 DECRYPTION_FAILED | |
| 85 }; | |
| 86 | |
| 87 // Decrypts the |message| and then synchronously waits until either the | 80 // Decrypts the |message| and then synchronously waits until either the |
| 88 // success or failure callbacks has been invoked. | 81 // success or failure callbacks has been invoked. |
| 89 void Decrypt(const IncomingMessage& message) { | 82 void Decrypt(const IncomingMessage& message) { |
| 90 decryption_result_ = DECRYPTION_IDLE; | |
| 91 encryption_provider_->DecryptMessage( | 83 encryption_provider_->DecryptMessage( |
| 92 kExampleAppId, message, | 84 kExampleAppId, message, |
| 93 base::Bind(&GCMEncryptionProviderTest::OnDecryptionSucceeded, | 85 base::Bind(&GCMEncryptionProviderTest::DidDecryptMessage, |
| 94 base::Unretained(this)), | |
| 95 base::Bind(&GCMEncryptionProviderTest::OnDecryptionFailed, | |
| 96 base::Unretained(this))); | 86 base::Unretained(this))); |
| 97 | 87 |
| 98 // The encryption keys will be read asynchronously. | 88 // The encryption keys will be read asynchronously. |
| 99 base::RunLoop().RunUntilIdle(); | 89 base::RunLoop().RunUntilIdle(); |
| 100 | |
| 101 ASSERT_NE(decryption_result_, DECRYPTION_IDLE); | |
| 102 } | 90 } |
| 103 | 91 |
| 104 DecryptionResult decryption_result() { return decryption_result_; } | 92 // Returns the result of the previous decryption operation. |
| 93 GCMEncryptionProvider::DecryptionResult decryption_result() { |
| 94 return decryption_result_; |
| 95 } |
| 105 | 96 |
| 97 // Returns the message resulting from the previous decryption operation. |
| 106 const IncomingMessage& decrypted_message() { return decrypted_message_; } | 98 const IncomingMessage& decrypted_message() { return decrypted_message_; } |
| 107 | 99 |
| 108 GCMEncryptionProvider::DecryptionFailure failure_reason() { | |
| 109 return failure_reason_; | |
| 110 } | |
| 111 | |
| 112 GCMEncryptionProvider* encryption_provider() { | 100 GCMEncryptionProvider* encryption_provider() { |
| 113 return encryption_provider_.get(); | 101 return encryption_provider_.get(); |
| 114 } | 102 } |
| 115 | 103 |
| 116 private: | 104 private: |
| 117 void OnDecryptionSucceeded(const IncomingMessage& message) { | 105 void DidDecryptMessage(GCMEncryptionProvider::DecryptionResult result, |
| 118 decryption_result_ = DECRYPTION_SUCCEEDED; | 106 const IncomingMessage& message) { |
| 107 decryption_result_ = result; |
| 119 decrypted_message_ = message; | 108 decrypted_message_ = message; |
| 120 } | 109 } |
| 121 | 110 |
| 122 void OnDecryptionFailed(GCMEncryptionProvider::DecryptionFailure reason) { | |
| 123 decryption_result_ = DECRYPTION_FAILED; | |
| 124 failure_reason_ = reason; | |
| 125 } | |
| 126 | |
| 127 base::MessageLoop message_loop_; | 111 base::MessageLoop message_loop_; |
| 128 base::ScopedTempDir scoped_temp_dir_; | 112 base::ScopedTempDir scoped_temp_dir_; |
| 113 base::HistogramTester histogram_tester_; |
| 129 | 114 |
| 130 scoped_ptr<GCMEncryptionProvider> encryption_provider_; | 115 scoped_ptr<GCMEncryptionProvider> encryption_provider_; |
| 131 | 116 |
| 132 DecryptionResult decryption_result_ = DECRYPTION_IDLE; | 117 GCMEncryptionProvider::DecryptionResult decryption_result_ = |
| 133 GCMEncryptionProvider::DecryptionFailure failure_reason_ = | 118 GCMEncryptionProvider::DECRYPTION_RESULT_UNENCRYPTED; |
| 134 GCMEncryptionProvider::DECRYPTION_FAILURE_UNKNOWN; | |
| 135 | 119 |
| 136 IncomingMessage decrypted_message_; | 120 IncomingMessage decrypted_message_; |
| 137 }; | 121 }; |
| 138 | 122 |
| 139 TEST_F(GCMEncryptionProviderTest, IsEncryptedMessage) { | 123 TEST_F(GCMEncryptionProviderTest, IsEncryptedMessage) { |
| 140 // Both the Encryption and Encryption-Key headers must be present, and the raw | 124 // Both the Encryption and Encryption-Key headers must be present, and the raw |
| 141 // data must be non-empty for a message to be considered encrypted. | 125 // data must be non-empty for a message to be considered encrypted. |
| 142 | 126 |
| 143 IncomingMessage empty_message; | 127 IncomingMessage empty_message; |
| 144 EXPECT_FALSE(encryption_provider()->IsEncryptedMessage(empty_message)); | 128 EXPECT_FALSE(encryption_provider()->IsEncryptedMessage(empty_message)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 162 double_header_with_data_message)); | 146 double_header_with_data_message)); |
| 163 } | 147 } |
| 164 | 148 |
| 165 TEST_F(GCMEncryptionProviderTest, VerifiesEncryptionHeaderParsing) { | 149 TEST_F(GCMEncryptionProviderTest, VerifiesEncryptionHeaderParsing) { |
| 166 // The Encryption header must be parsable and contain valid values. | 150 // The Encryption header must be parsable and contain valid values. |
| 167 // Note that this is more extensively tested in EncryptionHeaderParsersTest. | 151 // Note that this is more extensively tested in EncryptionHeaderParsersTest. |
| 168 | 152 |
| 169 IncomingMessage invalid_message; | 153 IncomingMessage invalid_message; |
| 170 invalid_message.data["encryption"] = kInvalidEncryptionHeader; | 154 invalid_message.data["encryption"] = kInvalidEncryptionHeader; |
| 171 invalid_message.data["crypto-key"] = kValidCryptoKeyHeader; | 155 invalid_message.data["crypto-key"] = kValidCryptoKeyHeader; |
| 156 invalid_message.raw_data = "foo"; |
| 172 | 157 |
| 173 ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message)); | 158 ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message)); |
| 174 ASSERT_EQ(DECRYPTION_FAILED, decryption_result()); | 159 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER, |
| 175 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_FAILURE_INVALID_ENCRYPTION_HEADER, | 160 decryption_result()); |
| 176 failure_reason()); | |
| 177 | 161 |
| 178 IncomingMessage valid_message; | 162 IncomingMessage valid_message; |
| 179 valid_message.data["encryption"] = kValidEncryptionHeader; | 163 valid_message.data["encryption"] = kValidEncryptionHeader; |
| 180 valid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; | 164 valid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; |
| 165 valid_message.raw_data = "foo"; |
| 181 | 166 |
| 182 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); | 167 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); |
| 183 ASSERT_EQ(DECRYPTION_FAILED, decryption_result()); | 168 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER, |
| 184 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_FAILURE_INVALID_ENCRYPTION_HEADER, | 169 decryption_result()); |
| 185 failure_reason()); | |
| 186 } | 170 } |
| 187 | 171 |
| 188 TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsing) { | 172 TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsing) { |
| 189 // The Encryption-Key header must be parsable and contain valid values. | 173 // The Encryption-Key header must be parsable and contain valid values. |
| 190 // Note that this is more extensively tested in EncryptionHeaderParsersTest. | 174 // Note that this is more extensively tested in EncryptionHeaderParsersTest. |
| 191 | 175 |
| 192 IncomingMessage invalid_message; | 176 IncomingMessage invalid_message; |
| 193 invalid_message.data["encryption"] = kValidEncryptionHeader; | 177 invalid_message.data["encryption"] = kValidEncryptionHeader; |
| 194 invalid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; | 178 invalid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; |
| 179 invalid_message.raw_data = "foo"; |
| 195 | 180 |
| 196 ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message)); | 181 ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message)); |
| 197 ASSERT_EQ(DECRYPTION_FAILED, decryption_result()); | 182 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, |
| 198 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_FAILURE_INVALID_CRYPTO_KEY_HEADER, | 183 decryption_result()); |
| 199 failure_reason()); | |
| 200 | 184 |
| 201 IncomingMessage valid_message; | 185 IncomingMessage valid_message; |
| 202 valid_message.data["encryption"] = kInvalidEncryptionHeader; | 186 valid_message.data["encryption"] = kInvalidEncryptionHeader; |
| 203 valid_message.data["crypto-key"] = kValidCryptoKeyHeader; | 187 valid_message.data["crypto-key"] = kValidCryptoKeyHeader; |
| 188 valid_message.raw_data = "foo"; |
| 204 | 189 |
| 205 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); | 190 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); |
| 206 ASSERT_EQ(DECRYPTION_FAILED, decryption_result()); | 191 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, |
| 207 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_FAILURE_INVALID_CRYPTO_KEY_HEADER, | 192 decryption_result()); |
| 208 failure_reason()); | |
| 209 } | 193 } |
| 210 | 194 |
| 211 TEST_F(GCMEncryptionProviderTest, VerifiesExistingKeys) { | 195 TEST_F(GCMEncryptionProviderTest, VerifiesExistingKeys) { |
| 212 // When both headers are valid, the encryption keys still must be known to | 196 // When both headers are valid, the encryption keys still must be known to |
| 213 // the GCM key store before the message can be decrypted. | 197 // the GCM key store before the message can be decrypted. |
| 214 | 198 |
| 215 IncomingMessage message; | 199 IncomingMessage message; |
| 216 message.data["encryption"] = kValidEncryptionHeader; | 200 message.data["encryption"] = kValidEncryptionHeader; |
| 217 message.data["crypto-key"] = kValidCryptoKeyHeader; | 201 message.data["crypto-key"] = kValidCryptoKeyHeader; |
| 202 message.raw_data = "foo"; |
| 218 | 203 |
| 219 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); | 204 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); |
| 220 ASSERT_EQ(DECRYPTION_FAILED, decryption_result()); | 205 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_NO_KEYS, |
| 221 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_FAILURE_NO_KEYS, | 206 decryption_result()); |
| 222 failure_reason()); | |
| 223 | 207 |
| 224 std::string public_key, auth_secret; | 208 std::string public_key, auth_secret; |
| 225 encryption_provider()->GetEncryptionInfo( | 209 encryption_provider()->GetEncryptionInfo( |
| 226 kExampleAppId, | 210 kExampleAppId, |
| 227 base::Bind(&GCMEncryptionProviderTest::DidGetEncryptionInfo, | 211 base::Bind(&GCMEncryptionProviderTest::DidGetEncryptionInfo, |
| 228 base::Unretained(this), &public_key, &auth_secret)); | 212 base::Unretained(this), &public_key, &auth_secret)); |
| 229 | 213 |
| 230 // Getting (or creating) the public key will be done asynchronously. | 214 // Getting (or creating) the public key will be done asynchronously. |
| 231 base::RunLoop().RunUntilIdle(); | 215 base::RunLoop().RunUntilIdle(); |
| 232 | 216 |
| 233 ASSERT_GT(public_key.size(), 0u); | 217 ASSERT_GT(public_key.size(), 0u); |
| 234 ASSERT_GT(auth_secret.size(), 0u); | 218 ASSERT_GT(auth_secret.size(), 0u); |
| 235 | 219 |
| 236 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); | 220 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); |
| 237 ASSERT_EQ(DECRYPTION_FAILED, decryption_result()); | 221 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_NO_KEYS, |
| 238 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_FAILURE_NO_KEYS, | 222 decryption_result()); |
| 239 failure_reason()); | |
| 240 } | 223 } |
| 241 | 224 |
| 242 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTrip) { | 225 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTrip) { |
| 243 // Performs a full round-trip of the encryption feature, including getting a | 226 // Performs a full round-trip of the encryption feature, including getting a |
| 244 // public/private key-pair and performing the cryptographic operations. This | 227 // public/private key-pair and performing the cryptographic operations. This |
| 245 // is more of an integration test than a unit test. | 228 // is more of an integration test than a unit test. |
| 246 | 229 |
| 247 KeyPair pair, server_pair; | 230 KeyPair pair, server_pair; |
| 248 std::string auth_secret, server_authentication; | 231 std::string auth_secret, server_authentication; |
| 249 | 232 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 encryption_header << "rs=" << base::SizeTToString(record_size) << ";"; | 288 encryption_header << "rs=" << base::SizeTToString(record_size) << ";"; |
| 306 encryption_header << "salt=" << encoded_salt; | 289 encryption_header << "salt=" << encoded_salt; |
| 307 | 290 |
| 308 message.data["encryption"] = encryption_header.str(); | 291 message.data["encryption"] = encryption_header.str(); |
| 309 message.data["crypto-key"] = "dh=" + encoded_key; | 292 message.data["crypto-key"] = "dh=" + encoded_key; |
| 310 | 293 |
| 311 ASSERT_TRUE(encryption_provider()->IsEncryptedMessage(message)); | 294 ASSERT_TRUE(encryption_provider()->IsEncryptedMessage(message)); |
| 312 | 295 |
| 313 // Decrypt the message, and expect everything to go wonderfully well. | 296 // Decrypt the message, and expect everything to go wonderfully well. |
| 314 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); | 297 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); |
| 315 ASSERT_EQ(DECRYPTION_SUCCEEDED, decryption_result()); | 298 ASSERT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED, |
| 299 decryption_result()); |
| 316 | 300 |
| 317 EXPECT_TRUE(decrypted_message().decrypted); | 301 EXPECT_TRUE(decrypted_message().decrypted); |
| 318 EXPECT_EQ(kExampleMessage, decrypted_message().raw_data); | 302 EXPECT_EQ(kExampleMessage, decrypted_message().raw_data); |
| 319 } | 303 } |
| 320 | 304 |
| 321 } // namespace gcm | 305 } // namespace gcm |
| OLD | NEW |