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

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

Issue 1707513002: Add various UMA histograms for measuring GCM crypto performance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gcm-remove-info
Patch Set: android fix Created 4 years, 10 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/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
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
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
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
OLDNEW
« no previous file with comments | « components/gcm_driver/crypto/gcm_encryption_provider.cc ('k') | components/gcm_driver/crypto/gcm_key_store.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698