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

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

Issue 2716443002: Implement support for draft-ietf-webpush-encryption-08 (Closed)
Patch Set: Implement support for draft-ietf-webpush-encryption-08 Created 3 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_message_cryptographer.h" 5 #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/base64url.h" 9 #include "base/base64url.h"
10 #include "base/big_endian.h"
10 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_piece.h"
11 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
12 #include "components/gcm_driver/crypto/p256_key_util.h" 14 #include "components/gcm_driver/crypto/p256_key_util.h"
13 #include "crypto/random.h" 15 #include "crypto/random.h"
14 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
15 17
16 namespace gcm { 18 namespace gcm {
17 19
18 namespace { 20 namespace {
19 21
20 // Example plaintext data to use in the tests. 22 // Example plaintext data to use in the tests.
21 const char kExamplePlaintext[] = "Example plaintext"; 23 const char kExamplePlaintext[] = "Example plaintext";
22 24
23 // Expected sizes of the different input given to the cryptographer. 25 // Expected sizes of the different input given to the cryptographer.
26 constexpr size_t kUncompressedPointSize = 65;
24 constexpr size_t kEcdhSharedSecretSize = 32; 27 constexpr size_t kEcdhSharedSecretSize = 32;
25 constexpr size_t kAuthSecretSize = 16; 28 constexpr size_t kAuthSecretSize = 16;
26 constexpr size_t kSaltSize = 16; 29 constexpr size_t kSaltSize = 16;
27 30
28 // Keying material for both parties as P-256 EC points. Used to make sure that 31 // Keying material for both parties as P-256 EC points. Used to make sure that
29 // the test vectors are reproducible. 32 // the test vectors are reproducible.
30 const unsigned char kCommonSenderPublicKey[] = { 33 const unsigned char kCommonSenderPublicKey[] = {
31 0x04, 0x05, 0x3C, 0xA1, 0xB9, 0xA5, 0xAB, 0xB8, 0x2D, 0x88, 0x48, 34 0x04, 0x05, 0x3C, 0xA1, 0xB9, 0xA5, 0xAB, 0xB8, 0x2D, 0x88, 0x48,
32 0x82, 0xC9, 0x49, 0x19, 0x91, 0xD5, 0xFD, 0xD1, 0x92, 0xDB, 0xA7, 35 0x82, 0xC9, 0x49, 0x19, 0x91, 0xD5, 0xFD, 0xD1, 0x92, 0xDB, 0xA7,
33 0x7E, 0x70, 0x48, 0x37, 0x41, 0xCD, 0x90, 0x05, 0x80, 0xDF, 0x65, 36 0x7E, 0x70, 0x48, 0x37, 0x41, 0xCD, 0x90, 0x05, 0x80, 0xDF, 0x65,
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 0xAB, 0xAC, 0x37, 0x61, 0xF4, 0xCB, 0x98, 0xFF, 0x00, 0x51}, 181 0xAB, 0xAC, 0x37, 0x61, 0xF4, 0xCB, 0x98, 0xFF, 0x00, 0x51},
179 {0xAE, 0xDA, 0x86, 0xDF, 0x6B, 0x03, 0x88, 0xDE, 0x90, 0xBB, 0xB7, 0xA0, 182 {0xAE, 0xDA, 0x86, 0xDF, 0x6B, 0x03, 0x88, 0xDE, 0x90, 0xBB, 0xB7, 0xA0,
180 0x78, 0x91, 0x3A, 0x36}, 183 0x78, 0x91, 0x3A, 0x36},
181 {0x4C, 0x4E, 0x2A, 0x8D, 0x88, 0x82, 0xCF, 0xC2, 0xF9, 0x8A, 0xFD, 0x31, 184 {0x4C, 0x4E, 0x2A, 0x8D, 0x88, 0x82, 0xCF, 0xC2, 0xF9, 0x8A, 0xFD, 0x31,
182 0xF8, 0xD1, 0xF6, 0xB5}, 185 0xF8, 0xD1, 0xF6, 0xB5},
183 8, 186 8,
184 nullptr}}; 187 nullptr}};
185 188
186 } // namespace 189 } // namespace
187 190
188 class GCMMessageCryptographerTest : public ::testing::Test { 191 class GCMMessageCryptographerTestBase : public ::testing::Test {
189 public: 192 public:
190 void SetUp() override { 193 void SetUp() override {
191 cryptographer_ = base::MakeUnique<GCMMessageCryptographer>(
192 GCMMessageCryptographer::Version::DRAFT_03);
193
194 recipient_public_key_.assign( 194 recipient_public_key_.assign(
195 kCommonRecipientPublicKey, 195 kCommonRecipientPublicKey,
196 kCommonRecipientPublicKey + arraysize(kCommonRecipientPublicKey)); 196 kCommonRecipientPublicKey + arraysize(kCommonRecipientPublicKey));
197 sender_public_key_.assign( 197 sender_public_key_.assign(
198 kCommonSenderPublicKey, 198 kCommonSenderPublicKey,
199 kCommonSenderPublicKey + arraysize(kCommonSenderPublicKey)); 199 kCommonSenderPublicKey + arraysize(kCommonSenderPublicKey));
200 200
201 std::string recipient_private_key( 201 std::string recipient_private_key(
202 kCommonRecipientPrivateKey, 202 kCommonRecipientPrivateKey,
203 kCommonRecipientPrivateKey + arraysize(kCommonRecipientPrivateKey)); 203 kCommonRecipientPrivateKey + arraysize(kCommonRecipientPrivateKey));
204 204
205 // TODO(peter): Remove the dependency on the x509 keying material when 205 // TODO(peter): Remove the dependency on the x509 keying material when
206 // crbug.com/618025 has been resolved. 206 // crbug.com/618025 has been resolved.
207 std::string recipient_public_key_x509( 207 std::string recipient_public_key_x509(
208 kCommonRecipientPublicKeyX509, 208 kCommonRecipientPublicKeyX509,
209 kCommonRecipientPublicKeyX509 + 209 kCommonRecipientPublicKeyX509 +
210 arraysize(kCommonRecipientPublicKeyX509)); 210 arraysize(kCommonRecipientPublicKeyX509));
211 211
212 ASSERT_TRUE(ComputeSharedP256Secret( 212 ASSERT_TRUE(ComputeSharedP256Secret(
213 recipient_private_key, recipient_public_key_x509, sender_public_key_, 213 recipient_private_key, recipient_public_key_x509, sender_public_key_,
214 &ecdh_shared_secret_)); 214 &ecdh_shared_secret_));
215 215
216 auth_secret_.assign(kCommonAuthSecret, 216 auth_secret_.assign(kCommonAuthSecret,
217 kCommonAuthSecret + arraysize(kCommonAuthSecret)); 217 kCommonAuthSecret + arraysize(kCommonAuthSecret));
218 } 218 }
219 219
220 protected: 220 protected:
221 // Generates a cryptographically secure random salt of 16-octets in size, the
222 // required length as expected by the HKDF.
223 std::string GenerateRandomSalt() {
224 std::string salt;
225
226 crypto::RandBytes(base::WriteInto(&salt, kSaltSize + 1), kSaltSize);
227 return salt;
228 }
229
230 // Public keys of the recipient and sender as uncompressed P-256 EC points. 221 // Public keys of the recipient and sender as uncompressed P-256 EC points.
231 std::string recipient_public_key_; 222 std::string recipient_public_key_;
232 std::string sender_public_key_; 223 std::string sender_public_key_;
233 224
234 // Shared secret to use in transformations. Associated with the keys above. 225 // Shared secret to use in transformations. Associated with the keys above.
235 std::string ecdh_shared_secret_; 226 std::string ecdh_shared_secret_;
236 227
237 // Authentication secret to use in tests where no specific value is expected. 228 // Authentication secret to use in tests where no specific value is expected.
238 std::string auth_secret_; 229 std::string auth_secret_;
230 };
231
232 class GCMMessageCryptographerTest
233 : public GCMMessageCryptographerTestBase,
234 public testing::WithParamInterface<GCMMessageCryptographer::Version> {
235 public:
236 void SetUp() override {
237 GCMMessageCryptographerTestBase::SetUp();
238
239 cryptographer_ = base::MakeUnique<GCMMessageCryptographer>(GetParam());
240 }
241
242 protected:
243 // Generates a cryptographically secure random salt of 16-octets in size, the
244 // required length as expected by the HKDF.
245 std::string GenerateRandomSalt() {
246 std::string salt;
247
248 crypto::RandBytes(base::WriteInto(&salt, kSaltSize + 1), kSaltSize);
249 return salt;
250 }
239 251
240 // The GCMMessageCryptographer instance to use for the tests. 252 // The GCMMessageCryptographer instance to use for the tests.
241 std::unique_ptr<GCMMessageCryptographer> cryptographer_; 253 std::unique_ptr<GCMMessageCryptographer> cryptographer_;
242 }; 254 };
243 255
244 TEST_F(GCMMessageCryptographerTest, RoundTrip) { 256 TEST_P(GCMMessageCryptographerTest, RoundTrip) {
245 const std::string salt = GenerateRandomSalt(); 257 const std::string salt = GenerateRandomSalt();
246 258
247 size_t record_size = 0; 259 size_t record_size = 0;
248 260
249 std::string ciphertext, plaintext; 261 std::string ciphertext, plaintext;
250 ASSERT_TRUE(cryptographer_->Encrypt( 262 ASSERT_TRUE(cryptographer_->Encrypt(
251 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, 263 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
252 auth_secret_, salt, kExamplePlaintext, &record_size, &ciphertext)); 264 auth_secret_, salt, kExamplePlaintext, &record_size, &ciphertext));
253 265
254 EXPECT_GT(record_size, ciphertext.size() - 16); 266 EXPECT_GT(record_size, ciphertext.size() - 16);
255 EXPECT_GT(ciphertext.size(), 0u); 267 EXPECT_GT(ciphertext.size(), 0u);
256 268
257 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_, 269 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_,
258 ecdh_shared_secret_, auth_secret_, salt, 270 ecdh_shared_secret_, auth_secret_, salt,
259 ciphertext, record_size, &plaintext)); 271 ciphertext, record_size, &plaintext));
260 272
261 EXPECT_EQ(kExamplePlaintext, plaintext); 273 EXPECT_EQ(kExamplePlaintext, plaintext);
262 } 274 }
263 275
264 TEST_F(GCMMessageCryptographerTest, RoundTripEmptyMessage) { 276 TEST_P(GCMMessageCryptographerTest, RoundTripEmptyMessage) {
265 const std::string salt = GenerateRandomSalt(); 277 const std::string salt = GenerateRandomSalt();
266 const std::string message = ""; 278 const std::string message = "";
267 279
268 size_t record_size = 0; 280 size_t record_size = 0;
269 281
270 std::string ciphertext, plaintext; 282 std::string ciphertext, plaintext;
271 ASSERT_TRUE(cryptographer_->Encrypt(recipient_public_key_, sender_public_key_, 283 ASSERT_TRUE(cryptographer_->Encrypt(recipient_public_key_, sender_public_key_,
272 ecdh_shared_secret_, auth_secret_, salt, 284 ecdh_shared_secret_, auth_secret_, salt,
273 message, &record_size, &ciphertext)); 285 message, &record_size, &ciphertext));
274 286
275 EXPECT_GT(record_size, ciphertext.size() - 16); 287 EXPECT_GT(record_size, ciphertext.size() - 16);
276 EXPECT_GT(ciphertext.size(), 0u); 288 EXPECT_GT(ciphertext.size(), 0u);
277 289
278 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_, 290 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_,
279 ecdh_shared_secret_, auth_secret_, salt, 291 ecdh_shared_secret_, auth_secret_, salt,
280 ciphertext, record_size, &plaintext)); 292 ciphertext, record_size, &plaintext));
281 293
282 EXPECT_EQ(message, plaintext); 294 EXPECT_EQ(message, plaintext);
283 } 295 }
284 296
285 TEST_F(GCMMessageCryptographerTest, InvalidRecordSize) { 297 TEST_P(GCMMessageCryptographerTest, InvalidRecordSize) {
286 const std::string salt = GenerateRandomSalt(); 298 const std::string salt = GenerateRandomSalt();
287 299
288 size_t record_size = 0; 300 size_t record_size = 0;
289 301
290 std::string ciphertext, plaintext; 302 std::string ciphertext, plaintext;
291 ASSERT_TRUE(cryptographer_->Encrypt( 303 ASSERT_TRUE(cryptographer_->Encrypt(
292 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, 304 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
293 auth_secret_, salt, kExamplePlaintext, &record_size, &ciphertext)); 305 auth_secret_, salt, kExamplePlaintext, &record_size, &ciphertext));
294 306
295 EXPECT_GT(record_size, ciphertext.size() - 16); 307 EXPECT_GT(record_size, ciphertext.size() - 16);
296 308
297 EXPECT_FALSE(cryptographer_->Decrypt( 309 EXPECT_FALSE(cryptographer_->Decrypt(
298 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, 310 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
299 auth_secret_, salt, ciphertext, 0 /* record_size */, &plaintext)); 311 auth_secret_, salt, ciphertext, 0 /* record_size */, &plaintext));
300 312
301 EXPECT_FALSE(cryptographer_->Decrypt( 313 EXPECT_FALSE(cryptographer_->Decrypt(
302 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, 314 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
303 auth_secret_, salt, ciphertext, ciphertext.size() - 17, &plaintext)); 315 auth_secret_, salt, ciphertext, ciphertext.size() - 17, &plaintext));
304 316
305 EXPECT_TRUE(cryptographer_->Decrypt( 317 EXPECT_TRUE(cryptographer_->Decrypt(
306 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, 318 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
307 auth_secret_, salt, ciphertext, ciphertext.size() - 16, &plaintext)); 319 auth_secret_, salt, ciphertext, ciphertext.size() - 16, &plaintext));
308 } 320 }
309 321
310 TEST_F(GCMMessageCryptographerTest, InvalidRecordPadding) { 322 TEST_P(GCMMessageCryptographerTest, InvalidRecordPadding) {
311 std::string message = std::string(sizeof(uint16_t), '\0') + kExamplePlaintext; 323 std::string message;
324 switch (GetParam()) {
325 case GCMMessageCryptographer::Version::DRAFT_03:
326 message.append(sizeof(uint8_t), '\00'); // padding length octets
327 message.append(sizeof(uint8_t), '\01');
328
329 message.append(sizeof(uint8_t), '\00'); // padding octet
330 message.append(kExamplePlaintext);
331 break;
332 case GCMMessageCryptographer::Version::DRAFT_08:
333 message.append(kExamplePlaintext);
334 message.append(sizeof(uint8_t), '\x02'); // padding delimiter octet
335 message.append(sizeof(uint8_t), '\x00'); // padding octet
336 break;
337 }
312 338
313 const std::string salt = GenerateRandomSalt(); 339 const std::string salt = GenerateRandomSalt();
314 340
315 const std::string prk = 341 const std::string prk =
316 cryptographer_->encryption_scheme_->DerivePseudoRandomKey( 342 cryptographer_->encryption_scheme_->DerivePseudoRandomKey(
317 ecdh_shared_secret_, auth_secret_); 343 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
344 auth_secret_);
318 const std::string content_encryption_key = 345 const std::string content_encryption_key =
319 cryptographer_->DeriveContentEncryptionKey(recipient_public_key_, 346 cryptographer_->DeriveContentEncryptionKey(recipient_public_key_,
320 sender_public_key_, prk, salt); 347 sender_public_key_, prk, salt);
321 const std::string nonce = cryptographer_->DeriveNonce( 348 const std::string nonce = cryptographer_->DeriveNonce(
322 recipient_public_key_, sender_public_key_, prk, salt); 349 recipient_public_key_, sender_public_key_, prk, salt);
323 350
324 ASSERT_GT(message.size(), 1u); 351 ASSERT_GT(message.size(), 2u);
325 const size_t record_size = message.size() + 1; 352 const size_t record_size = message.size() + 1;
326 353
327 std::string ciphertext, plaintext; 354 std::string ciphertext, plaintext;
328 ASSERT_TRUE(cryptographer_->TransformRecord( 355 ASSERT_TRUE(cryptographer_->TransformRecord(
329 GCMMessageCryptographer::Direction::ENCRYPT, message, 356 GCMMessageCryptographer::Direction::ENCRYPT, message,
330 content_encryption_key, nonce, &ciphertext)); 357 content_encryption_key, nonce, &ciphertext));
331 358
332 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_, 359 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_,
333 ecdh_shared_secret_, auth_secret_, salt, 360 ecdh_shared_secret_, auth_secret_, salt,
334 ciphertext, record_size, &plaintext)); 361 ciphertext, record_size, &plaintext));
335 362
336 // Note that GCMMessageCryptographer::Decrypt removes the padding. 363 // Note that GCMMessageCryptographer::Decrypt removes the padding.
337 EXPECT_EQ(kExamplePlaintext, plaintext); 364 EXPECT_EQ(kExamplePlaintext, plaintext);
338 365
339 // Now run the same steps again, but say that there are four padding octets. 366 // Now run the same steps again, but have invalid padding length indicators.
340 // This should be rejected because the padding will not be all zeros. 367 // (Only applicable to draft-ietf-webpush-encryption-03.)
341 message[0] = 4; 368 if (GetParam() == GCMMessageCryptographer::Version::DRAFT_03) {
369 // Padding that will spill over in the payload.
370 {
371 message[1] = 4;
372
373 ASSERT_TRUE(cryptographer_->TransformRecord(
374 GCMMessageCryptographer::Direction::ENCRYPT, message,
375 content_encryption_key, nonce, &ciphertext));
376
377 ASSERT_FALSE(cryptographer_->Decrypt(
378 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
379 auth_secret_, salt, ciphertext, record_size, &plaintext));
380 }
381
382 // More padding octets than the length of the message.
383 {
384 message[1] = 64;
385
386 ASSERT_TRUE(cryptographer_->TransformRecord(
387 GCMMessageCryptographer::Direction::ENCRYPT, message,
388 content_encryption_key, nonce, &ciphertext));
389
390 ASSERT_FALSE(cryptographer_->Decrypt(
391 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
392 auth_secret_, salt, ciphertext, record_size, &plaintext));
393 }
394
395 // Correct the |message| to be valid again. (A single byte of padding.)
396 message[1] = 1;
397 }
398
399 // Run tests for a missing delimiter in the record.
400 // (Only applicable to draft-ietf-webpush-encryption-03.)
401 if (GetParam() == GCMMessageCryptographer::Version::DRAFT_08) {
402 message[message.size() - 2] = 0x00;
403
404 ASSERT_TRUE(cryptographer_->TransformRecord(
405 GCMMessageCryptographer::Direction::ENCRYPT, message,
406 content_encryption_key, nonce, &ciphertext));
407
408 ASSERT_FALSE(cryptographer_->Decrypt(
409 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
410 auth_secret_, salt, ciphertext, record_size, &plaintext));
411
412 // Correct the |message| to be valid again. (Proper padding delimiter.)
413 message[message.size() - 2] = 0x02;
414 }
415
416 // Finally run a test to make sure that we validate that all padding bytes are
417 // set to zeros. The position of the padding byte depends on the version.
418 switch (GetParam()) {
419 case GCMMessageCryptographer::Version::DRAFT_03:
420 message[2] = 0x80;
421 break;
422 case GCMMessageCryptographer::Version::DRAFT_08:
423 message[message.size() - 1] = 0x80;
424 break;
425 }
342 426
343 ASSERT_TRUE(cryptographer_->TransformRecord( 427 ASSERT_TRUE(cryptographer_->TransformRecord(
344 GCMMessageCryptographer::Direction::ENCRYPT, message, 428 GCMMessageCryptographer::Direction::ENCRYPT, message,
345 content_encryption_key, nonce, &ciphertext)); 429 content_encryption_key, nonce, &ciphertext));
346
347 ASSERT_FALSE(cryptographer_->Decrypt(
348 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
349 auth_secret_, salt, ciphertext, record_size, &plaintext));
350
351 // Do the same but changing the second octet indicating padding size, leaving
352 // the first octet at zero.
353 message[0] = 0;
354 message[1] = 4;
355
356 ASSERT_TRUE(cryptographer_->TransformRecord(
357 GCMMessageCryptographer::Direction::ENCRYPT, message,
358 content_encryption_key, nonce, &ciphertext));
359
360 ASSERT_FALSE(cryptographer_->Decrypt(
361 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
362 auth_secret_, salt, ciphertext, record_size, &plaintext));
363
364 // Run the same steps again, but say that there are more padding octets than
365 // the length of the message.
366 message[0] = 64;
367
368 EXPECT_GT(static_cast<size_t>(message[0]), message.size());
369 ASSERT_TRUE(cryptographer_->TransformRecord(
370 GCMMessageCryptographer::Direction::ENCRYPT, message,
371 content_encryption_key, nonce, &ciphertext));
372 430
373 ASSERT_FALSE(cryptographer_->Decrypt( 431 ASSERT_FALSE(cryptographer_->Decrypt(
374 recipient_public_key_, sender_public_key_, ecdh_shared_secret_, 432 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
375 auth_secret_, salt, ciphertext, record_size, &plaintext)); 433 auth_secret_, salt, ciphertext, record_size, &plaintext));
376 } 434 }
377 435
378 TEST_F(GCMMessageCryptographerTest, AuthSecretAffectsPRK) { 436 TEST_P(GCMMessageCryptographerTest, AuthSecretAffectsPRK) {
379 std::string first_auth_secret, second_auth_secret; 437 std::string first_auth_secret, second_auth_secret;
380 438
381 crypto::RandBytes(base::WriteInto(&first_auth_secret, kAuthSecretSize + 1), 439 crypto::RandBytes(base::WriteInto(&first_auth_secret, kAuthSecretSize + 1),
382 kAuthSecretSize); 440 kAuthSecretSize);
383 crypto::RandBytes(base::WriteInto(&second_auth_secret, kAuthSecretSize + 1), 441 crypto::RandBytes(base::WriteInto(&second_auth_secret, kAuthSecretSize + 1),
384 kAuthSecretSize); 442 kAuthSecretSize);
385 443
386 ASSERT_NE(cryptographer_->encryption_scheme_->DerivePseudoRandomKey( 444 ASSERT_NE(cryptographer_->encryption_scheme_->DerivePseudoRandomKey(
387 ecdh_shared_secret_, first_auth_secret), 445 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
446 first_auth_secret),
388 cryptographer_->encryption_scheme_->DerivePseudoRandomKey( 447 cryptographer_->encryption_scheme_->DerivePseudoRandomKey(
389 ecdh_shared_secret_, second_auth_secret)); 448 recipient_public_key_, sender_public_key_, ecdh_shared_secret_,
449 second_auth_secret));
390 450
391 std::string salt = GenerateRandomSalt(); 451 std::string salt = GenerateRandomSalt();
392 452
393 // Verify that the IKM actually gets used by the transformations. 453 // Verify that the IKM actually gets used by the transformations.
394 size_t first_record_size, second_record_size; 454 size_t first_record_size, second_record_size;
395 std::string first_ciphertext, second_ciphertext; 455 std::string first_ciphertext, second_ciphertext;
396 456
397 ASSERT_TRUE(cryptographer_->Encrypt(recipient_public_key_, sender_public_key_, 457 ASSERT_TRUE(cryptographer_->Encrypt(recipient_public_key_, sender_public_key_,
398 ecdh_shared_secret_, first_auth_secret, 458 ecdh_shared_secret_, first_auth_secret,
399 salt, kExamplePlaintext, 459 salt, kExamplePlaintext,
(...skipping 19 matching lines...) Expand all
419 479
420 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_, 480 ASSERT_TRUE(cryptographer_->Decrypt(recipient_public_key_, sender_public_key_,
421 ecdh_shared_secret_, second_auth_secret, 481 ecdh_shared_secret_, second_auth_secret,
422 salt, second_ciphertext, 482 salt, second_ciphertext,
423 second_record_size, &second_plaintext)); 483 second_record_size, &second_plaintext));
424 484
425 EXPECT_EQ(kExamplePlaintext, first_plaintext); 485 EXPECT_EQ(kExamplePlaintext, first_plaintext);
426 EXPECT_EQ(kExamplePlaintext, second_plaintext); 486 EXPECT_EQ(kExamplePlaintext, second_plaintext);
427 } 487 }
428 488
489 INSTANTIATE_TEST_CASE_P(
490 GCMMessageCryptographerTestBase,
491 GCMMessageCryptographerTest,
492 ::testing::Values(GCMMessageCryptographer::Version::DRAFT_03,
493 GCMMessageCryptographer::Version::DRAFT_08));
494
429 class GCMMessageCryptographerTestVectorTest 495 class GCMMessageCryptographerTestVectorTest
430 : public GCMMessageCryptographerTest {}; 496 : public GCMMessageCryptographerTestBase {};
431 497
432 TEST_F(GCMMessageCryptographerTestVectorTest, EncryptionVectorsDraft03) { 498 TEST_F(GCMMessageCryptographerTestVectorTest, EncryptionVectorsDraft03) {
499 GCMMessageCryptographer cryptographer(
500 GCMMessageCryptographer::Version::DRAFT_03);
501
433 std::string ecdh_shared_secret, auth_secret, salt, ciphertext, output; 502 std::string ecdh_shared_secret, auth_secret, salt, ciphertext, output;
434 size_t record_size = 0; 503 size_t record_size = 0;
435 504
436 for (size_t i = 0; i < arraysize(kEncryptionTestVectorsDraft03); ++i) { 505 for (size_t i = 0; i < arraysize(kEncryptionTestVectorsDraft03); ++i) {
437 SCOPED_TRACE(i); 506 SCOPED_TRACE(i);
438 507
439 ecdh_shared_secret.assign( 508 ecdh_shared_secret.assign(
440 kEncryptionTestVectorsDraft03[i].ecdh_shared_secret, 509 kEncryptionTestVectorsDraft03[i].ecdh_shared_secret,
441 kEncryptionTestVectorsDraft03[i].ecdh_shared_secret + 510 kEncryptionTestVectorsDraft03[i].ecdh_shared_secret +
442 kEcdhSharedSecretSize); 511 kEcdhSharedSecretSize);
443 512
444 auth_secret.assign( 513 auth_secret.assign(
445 kEncryptionTestVectorsDraft03[i].auth_secret, 514 kEncryptionTestVectorsDraft03[i].auth_secret,
446 kEncryptionTestVectorsDraft03[i].auth_secret + kAuthSecretSize); 515 kEncryptionTestVectorsDraft03[i].auth_secret + kAuthSecretSize);
447 516
448 salt.assign(kEncryptionTestVectorsDraft03[i].salt, 517 salt.assign(kEncryptionTestVectorsDraft03[i].salt,
449 kEncryptionTestVectorsDraft03[i].salt + kSaltSize); 518 kEncryptionTestVectorsDraft03[i].salt + kSaltSize);
450 519
451 ASSERT_TRUE(cryptographer_->Encrypt( 520 ASSERT_TRUE(cryptographer.Encrypt(recipient_public_key_, sender_public_key_,
452 recipient_public_key_, sender_public_key_, ecdh_shared_secret, 521 ecdh_shared_secret, auth_secret, salt,
453 auth_secret, salt, kEncryptionTestVectorsDraft03[i].input, &record_size, 522 kEncryptionTestVectorsDraft03[i].input,
454 &ciphertext)); 523 &record_size, &ciphertext));
455 524
456 base::Base64UrlEncode(ciphertext, base::Base64UrlEncodePolicy::OMIT_PADDING, 525 base::Base64UrlEncode(ciphertext, base::Base64UrlEncodePolicy::OMIT_PADDING,
457 &output); 526 &output);
458 527
459 EXPECT_EQ(kEncryptionTestVectorsDraft03[i].record_size, record_size); 528 EXPECT_EQ(kEncryptionTestVectorsDraft03[i].record_size, record_size);
460 EXPECT_EQ(kEncryptionTestVectorsDraft03[i].output, output); 529 EXPECT_EQ(kEncryptionTestVectorsDraft03[i].output, output);
461 } 530 }
462 } 531 }
463 532
464 TEST_F(GCMMessageCryptographerTestVectorTest, DecryptionVectorsDraft03) { 533 TEST_F(GCMMessageCryptographerTestVectorTest, DecryptionVectorsDraft03) {
534 GCMMessageCryptographer cryptographer(
535 GCMMessageCryptographer::Version::DRAFT_03);
536
465 std::string input, ecdh_shared_secret, auth_secret, salt, plaintext; 537 std::string input, ecdh_shared_secret, auth_secret, salt, plaintext;
466 for (size_t i = 0; i < arraysize(kDecryptionTestVectorsDraft03); ++i) { 538 for (size_t i = 0; i < arraysize(kDecryptionTestVectorsDraft03); ++i) {
467 SCOPED_TRACE(i); 539 SCOPED_TRACE(i);
468 540
469 ASSERT_TRUE(base::Base64UrlDecode( 541 ASSERT_TRUE(base::Base64UrlDecode(
470 kDecryptionTestVectorsDraft03[i].input, 542 kDecryptionTestVectorsDraft03[i].input,
471 base::Base64UrlDecodePolicy::IGNORE_PADDING, &input)); 543 base::Base64UrlDecodePolicy::IGNORE_PADDING, &input));
472 544
473 ecdh_shared_secret.assign( 545 ecdh_shared_secret.assign(
474 kDecryptionTestVectorsDraft03[i].ecdh_shared_secret, 546 kDecryptionTestVectorsDraft03[i].ecdh_shared_secret,
475 kDecryptionTestVectorsDraft03[i].ecdh_shared_secret + 547 kDecryptionTestVectorsDraft03[i].ecdh_shared_secret +
476 kEcdhSharedSecretSize); 548 kEcdhSharedSecretSize);
477 549
478 auth_secret.assign( 550 auth_secret.assign(
479 kDecryptionTestVectorsDraft03[i].auth_secret, 551 kDecryptionTestVectorsDraft03[i].auth_secret,
480 kDecryptionTestVectorsDraft03[i].auth_secret + kAuthSecretSize); 552 kDecryptionTestVectorsDraft03[i].auth_secret + kAuthSecretSize);
481 553
482 salt.assign(kDecryptionTestVectorsDraft03[i].salt, 554 salt.assign(kDecryptionTestVectorsDraft03[i].salt,
483 kDecryptionTestVectorsDraft03[i].salt + kSaltSize); 555 kDecryptionTestVectorsDraft03[i].salt + kSaltSize);
484 556
485 const bool has_output = kDecryptionTestVectorsDraft03[i].output; 557 const bool has_output = kDecryptionTestVectorsDraft03[i].output;
486 const bool result = cryptographer_->Decrypt( 558 const bool result = cryptographer.Decrypt(
487 recipient_public_key_, sender_public_key_, ecdh_shared_secret, 559 recipient_public_key_, sender_public_key_, ecdh_shared_secret,
488 auth_secret, salt, input, kDecryptionTestVectorsDraft03[i].record_size, 560 auth_secret, salt, input, kDecryptionTestVectorsDraft03[i].record_size,
489 &plaintext); 561 &plaintext);
490 562
491 if (!has_output) { 563 if (!has_output) {
492 EXPECT_FALSE(result); 564 EXPECT_FALSE(result);
493 continue; 565 continue;
494 } 566 }
495 567
496 EXPECT_TRUE(result); 568 EXPECT_TRUE(result);
497 EXPECT_EQ(kDecryptionTestVectorsDraft03[i].output, plaintext); 569 EXPECT_EQ(kDecryptionTestVectorsDraft03[i].output, plaintext);
498 } 570 }
499 } 571 }
500 572
501 class GCMMessageCryptographerReferenceTest : public ::testing::Test { 573 class GCMMessageCryptographerReferenceTest : public ::testing::Test {
502 protected: 574 protected:
503 // Computes the shared secret between the sender and the receiver. The sender 575 // Computes the shared secret between the sender and the receiver. The sender
504 // must have a key-pair containing a X.509 SubjectPublicKeyInfo block and a 576 // must have a key-pair containing a X.509 SubjectPublicKeyInfo block and a
505 // ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo block, whereas the receiver 577 // ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo block, whereas the receiver
506 // must have a public key in uncompressed EC point format. 578 // must have a public key in uncompressed EC point format.
507 void ComputeSharedSecret(const char* encoded_sender_private_key, 579 void ComputeSharedSecret(
508 const char* encoded_sender_public_key_x509, 580 const base::StringPiece& encoded_sender_private_key,
509 const char* encoded_receiver_public_key, 581 const base::StringPiece& encoded_sender_public_key_x509,
510 std::string* shared_secret) const { 582 const base::StringPiece& encoded_receiver_public_key,
583 std::string* shared_secret) const {
511 std::string sender_private_key, sender_public_key_x509, receiver_public_key; 584 std::string sender_private_key, sender_public_key_x509, receiver_public_key;
512 ASSERT_TRUE(base::Base64UrlDecode( 585 ASSERT_TRUE(base::Base64UrlDecode(
513 encoded_sender_private_key, 586 encoded_sender_private_key,
514 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_private_key)); 587 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_private_key));
515 ASSERT_TRUE(base::Base64UrlDecode( 588 ASSERT_TRUE(base::Base64UrlDecode(
516 encoded_sender_public_key_x509, 589 encoded_sender_public_key_x509,
517 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_public_key_x509)); 590 base::Base64UrlDecodePolicy::IGNORE_PADDING, &sender_public_key_x509));
518 ASSERT_TRUE(base::Base64UrlDecode( 591 ASSERT_TRUE(base::Base64UrlDecode(
519 encoded_receiver_public_key, 592 encoded_receiver_public_key,
520 base::Base64UrlDecodePolicy::IGNORE_PADDING, &receiver_public_key)); 593 base::Base64UrlDecodePolicy::IGNORE_PADDING, &receiver_public_key));
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 ASSERT_EQ(kCiphertext, encoded_ciphertext); 681 ASSERT_EQ(kCiphertext, encoded_ciphertext);
609 682
610 // And verify that decrypting themessageyields the plaintext again. 683 // And verify that decrypting themessageyields the plaintext again.
611 ASSERT_TRUE(cryptographer.Decrypt(recipient_public_key, sender_public_key, 684 ASSERT_TRUE(cryptographer.Decrypt(recipient_public_key, sender_public_key,
612 sender_shared_secret, auth_secret, salt, 685 sender_shared_secret, auth_secret, salt,
613 ciphertext, record_size, &plaintext)); 686 ciphertext, record_size, &plaintext));
614 687
615 ASSERT_EQ(kPlaintext, plaintext); 688 ASSERT_EQ(kPlaintext, plaintext);
616 } 689 }
617 690
691 // Reference test included for the Version::DRAFT_08 implementation.
692 // https://tools.ietf.org/html/draft-ietf-webpush-encryption-08
693 // https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-07
694 TEST_F(GCMMessageCryptographerReferenceTest, ReferenceDraft08) {
695 // The 16-byte prearranged secret between the sender and receiver.
696 const char kAuthSecret[] = "BTBZMqHH6r4Tts7J_aSIgg";
697
698 // The keying material used by the sender to encrypt the |kCiphertext|.
699 const char kSenderPrivate[] =
700 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIScUGT5GSrLoCAggABIGQMr4LCZNVg8uqAo5MSUrI5cCV"
701 "AyQzjG7jdSXooDx_yPXgwMskoNzKhBXIG0AZF7MBimdXFTg_wlv38empWRr_-x4fnQiIBKya"
702 "pt6uBOfYVuE_nnhqudqvSxiiv6hikBvxS2zabgph8-vFPQG10uUv8xkAO6vPdtTABCUzCXQU"
703 "p1QmuP471ZdaNAMuCPmxry-C";
704 const char kSenderPublicX509[] =
705 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE_jP0qw3qcZFNtVgj9ztUlI9BMG2SBzLbuaWa"
706 "UyhkgiAOWXp7e8JguhwieZhYCZLpOXMALzASooro8Gu7eOXsDw";
707
708 // The keying material used by the recipient to decrypt the |kCiphertext|.
709 const char kRecipientPrivate[] =
710 "MIGxMBwGCiqGSIb3DQEMAQMwDgQIFMj5PQ6zlvwCAggABIGQfr9ZUZd5kr5Wf3AnThoNI8mr"
711 "V3dkpfaKWc725soIIny8V1l_-8AkfbsisM7VpEmZMWKhjSoCKtq970vb-27xUGUCtxy6Mhij"
712 "r4suUqirpM1noA1oKd0O0ap7_zHG4X6j2iA-4UPC0T4lSIscgmRZJWKQeA_7U0pUfryhTolM"
713 "o175tTl399amT66tOGI2wn3O";
714 const char kRecipientPublicKeyUncompressed[] =
715 "BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZ"
716 "GH6SRpkNtoIAiw4";
717 const char kRecipientPublicX509[] =
718 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJXGyvs3942BVGq8e0PTNNmwRzr5VX4m8t7GG"
719 "pTM5FzFo7OLr4BhZe9MEebhuPI-OztV3ylkYfpJGmQ22ggCLDg";
720
721 // The plain text of the message, as well as the encrypted reference message.
722 const char kPlaintext[] = "When I grow up, I want to be a watermelon";
723 const char kReferenceMessage[] =
724 "DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_"
725 "c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_"
726 "yl95bQpu6cVPTpK4Mqgkf1CXztLVBSt2Ks3oZwbuwXPXLWyouBWLVWGNWQexSgSxsj_"
727 "Qulcy4a-fN";
728
729 std::string message;
730 ASSERT_TRUE(base::Base64UrlDecode(kReferenceMessage,
731 base::Base64UrlDecodePolicy::IGNORE_PADDING,
732 &message));
733
734 // TODO(peter): Break out the following in a separate message parser class so
735 // that it can be reused by the GCMEncryptionProvider (on the receiving path)
736 // and the gcm_crypto_test_helpers.cc file (on the sending path) too.
737 //
738 // The message contains a binary header in the following format:
739 // [ salt(16) | record_size(4) | sender_public_key_len(1) |
740 // sender_public_key(sender_public_key_len) ]
741 //
742 // For Web Push Encryption, which uses a P-256 sender key as uncompressed
743 // P-256 EC points, the length of the sender key is 65 bytes, making the
744 // total, fixed length of the header 86 bytes.
745 //
746 // The regular AEAD_AES_128_GCM ciphertext follows immediately after this. The
747 // minimum overhead for a single record is 18 bytes. This means that an
748 // incoming message must be at least 104 bytes in size.
749 ASSERT_GE(message.size(), 104u);
750
751 const char* current = &message.front();
752
753 uint32_t record_size;
754 uint8_t sender_public_key_length;
755
756 base::StringPiece salt(current, kSaltSize);
757 current += kSaltSize;
758
759 base::ReadBigEndian(current, &record_size);
760 current += sizeof(record_size);
761
762 base::ReadBigEndian(current, &sender_public_key_length);
763 current += sizeof(sender_public_key_length);
764
765 ASSERT_EQ(sender_public_key_length, kUncompressedPointSize);
766
767 base::StringPiece sender_public_key(current, sender_public_key_length);
768 current += sender_public_key_length;
769
770 base::StringPiece ciphertext(
771 current,
772 message.size() - kSaltSize - sizeof(record_size) -
773 sizeof(sender_public_key_length) - sender_public_key_length);
774
775 std::string sender_shared_secret, receiver_shared_secret;
776
777 // Compute the shared secrets between the sender and receiver's keys.
778 ASSERT_NO_FATAL_FAILURE(ComputeSharedSecret(kSenderPrivate, kSenderPublicX509,
779 kRecipientPublicKeyUncompressed,
780 &sender_shared_secret));
781
782 // Compute the shared secret based on the sender's public key, which isn't a
783 // constant but instead is included in the message's binary header.
784 std::string sender_private_key, sender_public_key_x509;
785 ASSERT_TRUE(base::Base64UrlDecode(kRecipientPrivate,
786 base::Base64UrlDecodePolicy::IGNORE_PADDING,
787 &sender_private_key));
788 ASSERT_TRUE(base::Base64UrlDecode(kRecipientPublicX509,
789 base::Base64UrlDecodePolicy::IGNORE_PADDING,
790 &sender_public_key_x509));
791
792 ASSERT_TRUE(ComputeSharedP256Secret(sender_private_key,
793 sender_public_key_x509, sender_public_key,
794 &receiver_shared_secret));
795
796 ASSERT_GT(sender_shared_secret.size(), 0u);
797 ASSERT_EQ(sender_shared_secret, receiver_shared_secret);
798
799 // Decode the public keys of both parties and the auth secret.
800 std::string recipient_public_key, auth_secret;
801 ASSERT_TRUE(base::Base64UrlDecode(kRecipientPublicKeyUncompressed,
802 base::Base64UrlDecodePolicy::IGNORE_PADDING,
803 &recipient_public_key));
804 ASSERT_TRUE(base::Base64UrlDecode(
805 kAuthSecret, base::Base64UrlDecodePolicy::IGNORE_PADDING, &auth_secret));
806
807 // Attempt to decrypt the message using a GCMMessageCryptographer for this
808 // version of the draft, and then re-encrypt it agian to make sure it matches.
809 GCMMessageCryptographer cryptographer(
810 GCMMessageCryptographer::Version::DRAFT_08);
811
812 std::string plaintext;
813
814 ASSERT_TRUE(cryptographer.Decrypt(recipient_public_key, sender_public_key,
815 sender_shared_secret, auth_secret, salt,
816 ciphertext, record_size, &plaintext));
817 ASSERT_EQ(kPlaintext, plaintext);
818
819 size_t record_size2;
820 std::string ciphertext2;
821
822 ASSERT_TRUE(cryptographer.Encrypt(recipient_public_key, sender_public_key,
823 sender_shared_secret, auth_secret, salt,
824 kPlaintext, &record_size2, &ciphertext2));
825
826 EXPECT_GE(record_size2, record_size);
827 EXPECT_EQ(ciphertext2, ciphertext);
828 }
829
618 } // namespace gcm 830 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698