Chromium Code Reviews| 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> |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 const char kExampleAuthorizedEntity[] = "my-sender-id"; | 33 const char kExampleAuthorizedEntity[] = "my-sender-id"; |
| 34 const char kExampleMessage[] = "Hello, world, this is the GCM Driver!"; | 34 const char kExampleMessage[] = "Hello, world, this is the GCM Driver!"; |
| 35 | 35 |
| 36 const char kValidEncryptionHeader[] = | 36 const char kValidEncryptionHeader[] = |
| 37 "keyid=foo;salt=MTIzNDU2Nzg5MDEyMzQ1Ng;rs=1024"; | 37 "keyid=foo;salt=MTIzNDU2Nzg5MDEyMzQ1Ng;rs=1024"; |
| 38 const char kInvalidEncryptionHeader[] = "keyid"; | 38 const char kInvalidEncryptionHeader[] = "keyid"; |
| 39 | 39 |
| 40 const char kValidCryptoKeyHeader[] = | 40 const char kValidCryptoKeyHeader[] = |
| 41 "keyid=foo;dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbehXM7fqi1OMFefDUEi0eJ" | 41 "keyid=foo;dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbehXM7fqi1OMFefDUEi0eJ" |
| 42 "vsKfyVBWYkQjH-lSPJKxjAyslg"; | 42 "vsKfyVBWYkQjH-lSPJKxjAyslg"; |
| 43 const char kValidThreeValueCryptoKeyHeader[] = | |
| 44 "keyid=foo,keyid=bar,keyid=baz;dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbe" | |
| 45 "hXM7fqi1OMFefDUEi0eJvsKfyVBWYkQjH-lSPJKxjAyslg"; | |
| 46 | |
| 43 const char kInvalidCryptoKeyHeader[] = "keyid"; | 47 const char kInvalidCryptoKeyHeader[] = "keyid"; |
| 48 const char kInValidThreeValueCryptoKeyHeader[] = | |
|
johnme
2016/06/30 18:07:26
Micro-nit: lowercase V for consistency
Peter Beverloo
2016/06/30 18:09:37
Done.
| |
| 49 "keyid=foo,dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6j88ybbehXM7fqi1OMFefDUEi0eJ" | |
|
johnme
2016/06/30 18:07:26
Would it be clearer to use `keyid=foo;dh` instead
Peter Beverloo
2016/06/30 18:09:37
This way it skips headers, which is the new logic
| |
| 50 "vsKfyVBWYkQjH-lSPJKxjAyslg,keyid=baz,dh=BL_UGhfudEkXMUd4U4-D4nP5KHxKjQHsW6" | |
| 51 "j88ybbehXM7fqi1OMFefDUEi0eJvsKfyVBWYkQjH-lSPJKxjAyslg"; | |
| 44 | 52 |
| 45 } // namespace | 53 } // namespace |
| 46 | 54 |
| 47 class GCMEncryptionProviderTest : public ::testing::Test { | 55 class GCMEncryptionProviderTest : public ::testing::Test { |
| 48 public: | 56 public: |
| 49 void SetUp() override { | 57 void SetUp() override { |
| 50 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); | 58 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); |
| 51 | 59 |
| 52 encryption_provider_.reset(new GCMEncryptionProvider); | 60 encryption_provider_.reset(new GCMEncryptionProvider); |
| 53 encryption_provider_->Init(scoped_temp_dir_.path(), | 61 encryption_provider_->Init(scoped_temp_dir_.path(), |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 valid_message.data["encryption"] = kValidEncryptionHeader; | 205 valid_message.data["encryption"] = kValidEncryptionHeader; |
| 198 valid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; | 206 valid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; |
| 199 valid_message.raw_data = "foo"; | 207 valid_message.raw_data = "foo"; |
| 200 | 208 |
| 201 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); | 209 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); |
| 202 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER, | 210 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER, |
| 203 decryption_result()); | 211 decryption_result()); |
| 204 } | 212 } |
| 205 | 213 |
| 206 TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsing) { | 214 TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsing) { |
| 207 // The Encryption-Key header must be parsable and contain valid values. | 215 // The Crypto-Key header must be parsable and contain valid values. |
| 208 // Note that this is more extensively tested in EncryptionHeaderParsersTest. | 216 // Note that this is more extensively tested in EncryptionHeaderParsersTest. |
| 209 | 217 |
| 210 IncomingMessage invalid_message; | 218 IncomingMessage invalid_message; |
| 211 invalid_message.data["encryption"] = kValidEncryptionHeader; | 219 invalid_message.data["encryption"] = kValidEncryptionHeader; |
| 212 invalid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; | 220 invalid_message.data["crypto-key"] = kInvalidCryptoKeyHeader; |
| 213 invalid_message.raw_data = "foo"; | 221 invalid_message.raw_data = "foo"; |
| 214 | 222 |
| 215 ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message)); | 223 ASSERT_NO_FATAL_FAILURE(Decrypt(invalid_message)); |
| 216 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, | 224 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, |
| 217 decryption_result()); | 225 decryption_result()); |
| 218 | 226 |
| 219 IncomingMessage valid_message; | 227 IncomingMessage valid_message; |
| 220 valid_message.data["encryption"] = kInvalidEncryptionHeader; | 228 valid_message.data["encryption"] = kValidEncryptionHeader; |
| 221 valid_message.data["crypto-key"] = kValidCryptoKeyHeader; | 229 valid_message.data["crypto-key"] = kValidCryptoKeyHeader; |
| 222 valid_message.raw_data = "foo"; | 230 valid_message.raw_data = "foo"; |
| 223 | 231 |
| 224 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); | 232 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); |
| 225 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, | 233 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, |
| 226 decryption_result()); | 234 decryption_result()); |
| 227 } | 235 } |
| 228 | 236 |
| 237 TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderParsingThirdValue) { | |
| 238 // The Crypto-Key header must be parsable and contain valid values, in which | |
| 239 // values will be ignored unless they contain a "dh" property. | |
| 240 | |
| 241 IncomingMessage valid_message; | |
| 242 valid_message.data["encryption"] = kValidEncryptionHeader; | |
| 243 valid_message.data["crypto-key"] = kValidThreeValueCryptoKeyHeader; | |
| 244 valid_message.raw_data = "foo"; | |
| 245 | |
| 246 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); | |
| 247 EXPECT_NE(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, | |
| 248 decryption_result()); | |
| 249 } | |
| 250 | |
| 251 TEST_F(GCMEncryptionProviderTest, VerifiesCryptoKeyHeaderSingleDhEntry) { | |
| 252 // The Crypto-Key header must include at most one value that contains the | |
| 253 // "dh" property. Having more than once occurrence is forbidden. | |
| 254 | |
| 255 IncomingMessage valid_message; | |
| 256 valid_message.data["encryption"] = kValidEncryptionHeader; | |
| 257 valid_message.data["crypto-key"] = kInValidThreeValueCryptoKeyHeader; | |
| 258 valid_message.raw_data = "foo"; | |
| 259 | |
| 260 ASSERT_NO_FATAL_FAILURE(Decrypt(valid_message)); | |
| 261 EXPECT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER, | |
| 262 decryption_result()); | |
| 263 } | |
| 264 | |
| 229 TEST_F(GCMEncryptionProviderTest, VerifiesExistingKeys) { | 265 TEST_F(GCMEncryptionProviderTest, VerifiesExistingKeys) { |
| 230 // When both headers are valid, the encryption keys still must be known to | 266 // When both headers are valid, the encryption keys still must be known to |
| 231 // the GCM key store before the message can be decrypted. | 267 // the GCM key store before the message can be decrypted. |
| 232 | 268 |
| 233 IncomingMessage message; | 269 IncomingMessage message; |
| 234 message.data["encryption"] = kValidEncryptionHeader; | 270 message.data["encryption"] = kValidEncryptionHeader; |
| 235 message.data["crypto-key"] = kValidCryptoKeyHeader; | 271 message.data["crypto-key"] = kValidCryptoKeyHeader; |
| 236 message.raw_data = "foo"; | 272 message.raw_data = "foo"; |
| 237 | 273 |
| 238 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); | 274 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 } | 537 } |
| 502 | 538 |
| 503 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripInstanceIDToken) { | 539 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripInstanceIDToken) { |
| 504 // GCMEncryptionProvider::DecryptMessage should succeed when the message was | 540 // GCMEncryptionProvider::DecryptMessage should succeed when the message was |
| 505 // sent to an InstanceID token (non-empty authorized_entity). | 541 // sent to an InstanceID token (non-empty authorized_entity). |
| 506 ASSERT_NO_FATAL_FAILURE( | 542 ASSERT_NO_FATAL_FAILURE( |
| 507 TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity)); | 543 TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity)); |
| 508 } | 544 } |
| 509 | 545 |
| 510 } // namespace gcm | 546 } // namespace gcm |
| OLD | NEW |