Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: components/gcm_driver/crypto/gcm_encryption_provider_unittest.cc

Issue 2892033002: Enable support for draft-ietf-webpush-encryption-08 (Closed)
Patch Set: Enable support for draft-ietf-webpush-encryption-08 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/big_endian.h"
13 #include "base/bind.h" 14 #include "base/bind.h"
14 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
15 #include "base/files/scoped_temp_dir.h" 16 #include "base/files/scoped_temp_dir.h"
16 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h" 18 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h" 20 #include "base/strings/string_piece.h"
20 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
21 #include "base/test/histogram_tester.h" 22 #include "base/test/histogram_tester.h"
22 #include "components/gcm_driver/common/gcm_messages.h" 23 #include "components/gcm_driver/common/gcm_messages.h"
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 // Returns the message resulting from the previous decryption operation. 135 // Returns the message resulting from the previous decryption operation.
135 const IncomingMessage& decrypted_message() { return decrypted_message_; } 136 const IncomingMessage& decrypted_message() { return decrypted_message_; }
136 137
137 GCMEncryptionProvider* encryption_provider() { 138 GCMEncryptionProvider* encryption_provider() {
138 return encryption_provider_.get(); 139 return encryption_provider_.get();
139 } 140 }
140 141
141 // Performs a full round-trip test of the encryption feature. Must wrap this 142 // Performs a full round-trip test of the encryption feature. Must wrap this
142 // in ASSERT_NO_FATAL_FAILURE. 143 // in ASSERT_NO_FATAL_FAILURE.
143 void TestEncryptionRoundTrip(const std::string& app_id, 144 void TestEncryptionRoundTrip(const std::string& app_id,
144 const std::string& authorized_entity); 145 const std::string& authorized_entity,
146 GCMMessageCryptographer::Version version);
145 147
146 private: 148 private:
147 void DidDecryptMessage(GCMEncryptionProvider::DecryptionResult result, 149 void DidDecryptMessage(GCMEncryptionProvider::DecryptionResult result,
148 const IncomingMessage& message) { 150 const IncomingMessage& message) {
149 decryption_result_ = result; 151 decryption_result_ = result;
150 decrypted_message_ = message; 152 decrypted_message_ = message;
151 } 153 }
152 154
153 base::MessageLoop message_loop_; 155 base::MessageLoop message_loop_;
154 base::ScopedTempDir scoped_temp_dir_; 156 base::ScopedTempDir scoped_temp_dir_;
(...skipping 24 matching lines...) Expand all
179 double_header_message.data["crypto-key"] = ""; 181 double_header_message.data["crypto-key"] = "";
180 EXPECT_FALSE(encryption_provider()->IsEncryptedMessage( 182 EXPECT_FALSE(encryption_provider()->IsEncryptedMessage(
181 double_header_message)); 183 double_header_message));
182 184
183 IncomingMessage double_header_with_data_message; 185 IncomingMessage double_header_with_data_message;
184 double_header_with_data_message.data["encryption"] = ""; 186 double_header_with_data_message.data["encryption"] = "";
185 double_header_with_data_message.data["crypto-key"] = ""; 187 double_header_with_data_message.data["crypto-key"] = "";
186 double_header_with_data_message.raw_data = "foo"; 188 double_header_with_data_message.raw_data = "foo";
187 EXPECT_TRUE(encryption_provider()->IsEncryptedMessage( 189 EXPECT_TRUE(encryption_provider()->IsEncryptedMessage(
188 double_header_with_data_message)); 190 double_header_with_data_message));
191
192 IncomingMessage draft08_message;
193 draft08_message.data["content-encoding"] = "aes128gcm";
194 draft08_message.raw_data = "foo";
195 EXPECT_TRUE(encryption_provider()->IsEncryptedMessage(draft08_message));
189 } 196 }
190 197
191 TEST_F(GCMEncryptionProviderTest, VerifiesEncryptionHeaderParsing) { 198 TEST_F(GCMEncryptionProviderTest, VerifiesEncryptionHeaderParsing) {
192 // The Encryption header must be parsable and contain valid values. 199 // The Encryption header must be parsable and contain valid values.
193 // Note that this is more extensively tested in EncryptionHeaderParsersTest. 200 // Note that this is more extensively tested in EncryptionHeaderParsersTest.
194 201
195 IncomingMessage invalid_message; 202 IncomingMessage invalid_message;
196 invalid_message.data["encryption"] = kInvalidEncryptionHeader; 203 invalid_message.data["encryption"] = kInvalidEncryptionHeader;
197 invalid_message.data["crypto-key"] = kValidCryptoKeyHeader; 204 invalid_message.data["crypto-key"] = kValidCryptoKeyHeader;
198 invalid_message.raw_data = "foo"; 205 invalid_message.raw_data = "foo";
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 base::Bind(&base::DoNothing)); 447 base::Bind(&base::DoNothing));
441 448
442 base::RunLoop().RunUntilIdle(); 449 base::RunLoop().RunUntilIdle();
443 450
444 ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, false)); 451 ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_1, false));
445 ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, false)); 452 ASSERT_NO_FATAL_FAILURE(CheckHasKey(authorized_entity_2, false));
446 } 453 }
447 454
448 void GCMEncryptionProviderTest::TestEncryptionRoundTrip( 455 void GCMEncryptionProviderTest::TestEncryptionRoundTrip(
449 const std::string& app_id, 456 const std::string& app_id,
450 const std::string& authorized_entity) { 457 const std::string& authorized_entity,
458 GCMMessageCryptographer::Version version) {
451 // Performs a full round-trip of the encryption feature, including getting a 459 // Performs a full round-trip of the encryption feature, including getting a
452 // public/private key-pair and performing the cryptographic operations. This 460 // public/private key-pair and performing the cryptographic operations. This
453 // is more of an integration test than a unit test. 461 // is more of an integration test than a unit test.
454 462
455 KeyPair pair, server_pair; 463 KeyPair pair, server_pair;
456 std::string auth_secret, server_authentication; 464 std::string auth_secret, server_authentication;
457 465
458 // Retrieve the public/private key-pair immediately from the key store, given 466 // Retrieve the public/private key-pair immediately from the key store, given
459 // that the GCMEncryptionProvider will only share the public key with users. 467 // that the GCMEncryptionProvider will only share the public key with users.
460 // Also create a second pair, which will act as the server's keys. 468 // Also create a second pair, which will act as the server's keys.
(...skipping 27 matching lines...) Expand all
488 pair.private_key(), pair.public_key_x509(), server_pair.public_key(), 496 pair.private_key(), pair.public_key_x509(), server_pair.public_key(),
489 &shared_secret)); 497 &shared_secret));
490 498
491 IncomingMessage message; 499 IncomingMessage message;
492 size_t record_size; 500 size_t record_size;
493 501
494 message.sender_id = kExampleAuthorizedEntity; 502 message.sender_id = kExampleAuthorizedEntity;
495 503
496 // Encrypts the |kExampleMessage| using the generated shared key and the 504 // Encrypts the |kExampleMessage| using the generated shared key and the
497 // random |salt|, storing the result in |record_size| and the message. 505 // random |salt|, storing the result in |record_size| and the message.
498 GCMMessageCryptographer cryptographer( 506 GCMMessageCryptographer cryptographer(version);
499 GCMMessageCryptographer::Version::DRAFT_03);
500 507
508 std::string ciphertext;
501 ASSERT_TRUE(cryptographer.Encrypt( 509 ASSERT_TRUE(cryptographer.Encrypt(
502 pair.public_key(), server_pair.public_key(), shared_secret, auth_secret, 510 pair.public_key(), server_pair.public_key(), shared_secret, auth_secret,
503 salt, kExampleMessage, &record_size, &message.raw_data)); 511 salt, kExampleMessage, &record_size, &ciphertext));
504 512
505 std::string encoded_salt, encoded_key; 513 switch (version) {
514 case GCMMessageCryptographer::Version::DRAFT_03: {
515 std::string encoded_salt, encoded_key;
506 516
507 // Compile the incoming GCM message, including the required headers. 517 // Compile the incoming GCM message, including the required headers.
508 base::Base64UrlEncode( 518 base::Base64UrlEncode(salt, base::Base64UrlEncodePolicy::INCLUDE_PADDING,
509 salt, base::Base64UrlEncodePolicy::INCLUDE_PADDING, &encoded_salt); 519 &encoded_salt);
510 base::Base64UrlEncode( 520 base::Base64UrlEncode(server_pair.public_key(),
511 server_pair.public_key(), base::Base64UrlEncodePolicy::INCLUDE_PADDING, 521 base::Base64UrlEncodePolicy::INCLUDE_PADDING,
512 &encoded_key); 522 &encoded_key);
513 523
514 std::stringstream encryption_header; 524 std::stringstream encryption_header;
515 encryption_header << "rs=" << base::SizeTToString(record_size) << ";"; 525 encryption_header << "rs=" << base::SizeTToString(record_size) << ";";
516 encryption_header << "salt=" << encoded_salt; 526 encryption_header << "salt=" << encoded_salt;
517 527
518 message.data["encryption"] = encryption_header.str(); 528 message.data["encryption"] = encryption_header.str();
519 message.data["crypto-key"] = "dh=" + encoded_key; 529 message.data["crypto-key"] = "dh=" + encoded_key;
530 message.raw_data.swap(ciphertext);
531 break;
532 }
533 case GCMMessageCryptographer::Version::DRAFT_08: {
534 uint32_t rs = record_size;
535 uint8_t key_length = server_pair.public_key().size();
536
537 std::vector<char> payload(salt.size() + sizeof(rs) + sizeof(key_length) +
538 server_pair.public_key().size() +
539 ciphertext.size());
540
541 char* current = &payload.front();
542
543 memcpy(current, salt.data(), salt.size());
544 current += salt.size();
545
546 base::WriteBigEndian(current, rs);
547 current += sizeof(rs);
548
549 base::WriteBigEndian(current, key_length);
550 current += sizeof(key_length);
551
552 memcpy(current, server_pair.public_key().data(),
553 server_pair.public_key().size());
554 current += server_pair.public_key().size();
555
556 memcpy(current, ciphertext.data(), ciphertext.size());
557
558 message.data["content-encoding"] = "aes128gcm";
559 message.raw_data.assign(payload.begin(), payload.end());
560 break;
561 }
562 }
520 563
521 ASSERT_TRUE(encryption_provider()->IsEncryptedMessage(message)); 564 ASSERT_TRUE(encryption_provider()->IsEncryptedMessage(message));
522 565
523 // Decrypt the message, and expect everything to go wonderfully well. 566 // Decrypt the message, and expect everything to go wonderfully well.
524 ASSERT_NO_FATAL_FAILURE(Decrypt(message)); 567 ASSERT_NO_FATAL_FAILURE(Decrypt(message));
525 ASSERT_EQ(GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED, 568 ASSERT_EQ(version == GCMMessageCryptographer::Version::DRAFT_03
569 ? GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_03
570 : GCMEncryptionProvider::DECRYPTION_RESULT_DECRYPTED_DRAFT_08,
526 decryption_result()); 571 decryption_result());
527 572
528 EXPECT_TRUE(decrypted_message().decrypted); 573 EXPECT_TRUE(decrypted_message().decrypted);
529 EXPECT_EQ(kExampleMessage, decrypted_message().raw_data); 574 EXPECT_EQ(kExampleMessage, decrypted_message().raw_data);
530 } 575 }
531 576
532 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripGCMRegistration) { 577 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripGCMRegistration) {
533 // GCMEncryptionProvider::DecryptMessage should succeed when the message was 578 // GCMEncryptionProvider::DecryptMessage should succeed when the message was
534 // sent to a non-InstanceID GCM registration (empty authorized_entity). 579 // sent to a non-InstanceID GCM registration (empty authorized_entity).
535 ASSERT_NO_FATAL_FAILURE(TestEncryptionRoundTrip( 580 ASSERT_NO_FATAL_FAILURE(TestEncryptionRoundTrip(
536 kExampleAppId, "" /* empty authorized entity for non-InstanceID */)); 581 kExampleAppId, "" /* empty authorized entity for non-InstanceID */,
582 GCMMessageCryptographer::Version::DRAFT_03));
537 } 583 }
538 584
539 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripInstanceIDToken) { 585 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripInstanceIDToken) {
540 // GCMEncryptionProvider::DecryptMessage should succeed when the message was 586 // GCMEncryptionProvider::DecryptMessage should succeed when the message was
541 // sent to an InstanceID token (non-empty authorized_entity). 587 // sent to an InstanceID token (non-empty authorized_entity).
542 ASSERT_NO_FATAL_FAILURE( 588 ASSERT_NO_FATAL_FAILURE(
543 TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity)); 589 TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity,
590 GCMMessageCryptographer::Version::DRAFT_03));
591 }
592
593 TEST_F(GCMEncryptionProviderTest, EncryptionRoundTripDraft08) {
594 // GCMEncryptionProvider::DecryptMessage should succeed when the message was
595 // encrypted following raft-ietf-webpush-encryption-08.
596 ASSERT_NO_FATAL_FAILURE(
597 TestEncryptionRoundTrip(kExampleAppId, kExampleAuthorizedEntity,
598 GCMMessageCryptographer::Version::DRAFT_08));
544 } 599 }
545 600
546 } // namespace gcm 601 } // namespace gcm
OLDNEW
« no previous file with comments | « components/gcm_driver/crypto/gcm_encryption_provider.cc ('k') | components/gcm_driver/gcm_driver.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698