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 |