| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "net/quic/crypto/aes_128_gcm_12_decrypter.h" | 5 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h" |
| 6 | 6 |
| 7 #include "net/quic/test_tools/quic_test_utils.h" | 7 #include "net/quic/test_tools/quic_test_utils.h" |
| 8 | 8 |
| 9 using base::StringPiece; | 9 using base::StringPiece; |
| 10 | 10 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 238 |
| 239 const TestVector* const test_group_array[] = { | 239 const TestVector* const test_group_array[] = { |
| 240 test_group_0, | 240 test_group_0, |
| 241 test_group_1, | 241 test_group_1, |
| 242 test_group_2, | 242 test_group_2, |
| 243 test_group_3, | 243 test_group_3, |
| 244 test_group_4, | 244 test_group_4, |
| 245 test_group_5, | 245 test_group_5, |
| 246 }; | 246 }; |
| 247 | 247 |
| 248 // Returns true if |ch| is a lowercase hexadecimal digit. | |
| 249 bool IsHexDigit(char ch) { | |
| 250 return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f'); | |
| 251 } | |
| 252 | |
| 253 // Converts a lowercase hexadecimal digit to its integer value. | |
| 254 int HexDigitToInt(char ch) { | |
| 255 if ('0' <= ch && ch <= '9') { | |
| 256 return ch - '0'; | |
| 257 } | |
| 258 return ch - 'a' + 10; | |
| 259 } | |
| 260 | |
| 261 // |in| is a string consisting of lowercase hexadecimal digits, where | |
| 262 // every two digits represent one byte. |out| is a buffer of size |max_len|. | |
| 263 // Converts |in| to bytes and stores the bytes in the |out| buffer. The | |
| 264 // number of bytes converted is returned in |*out_len|. Returns true on | |
| 265 // success, false on failure. | |
| 266 bool DecodeHexString(const char* in, | |
| 267 char* out, | |
| 268 size_t* out_len, | |
| 269 size_t max_len) { | |
| 270 if (!in) { | |
| 271 *out_len = (size_t)-1; | |
| 272 return true; | |
| 273 } | |
| 274 *out_len = 0; | |
| 275 while (*in != '\0') { | |
| 276 if (!IsHexDigit(*in) || !IsHexDigit(*(in + 1))) { | |
| 277 return false; | |
| 278 } | |
| 279 if (*out_len >= max_len) { | |
| 280 return false; | |
| 281 } | |
| 282 out[*out_len] = HexDigitToInt(*in) * 16 + HexDigitToInt(*(in + 1)); | |
| 283 (*out_len)++; | |
| 284 in += 2; | |
| 285 } | |
| 286 return true; | |
| 287 } | |
| 288 | |
| 289 } // namespace | 248 } // namespace |
| 290 | 249 |
| 291 namespace net { | 250 namespace net { |
| 292 namespace test { | 251 namespace test { |
| 293 | 252 |
| 294 // DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing | 253 // DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing |
| 295 // in an nonce and also to allocate the buffer needed for the plaintext. | 254 // in an nonce and also to allocate the buffer needed for the plaintext. |
| 296 QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter, | 255 QuicData* DecryptWithNonce(Aes128Gcm12Decrypter* decrypter, |
| 297 StringPiece nonce, | 256 StringPiece nonce, |
| 298 StringPiece associated_data, | 257 StringPiece associated_data, |
| 299 StringPiece ciphertext) { | 258 StringPiece ciphertext) { |
| 300 size_t plaintext_size = ciphertext.length(); | 259 size_t plaintext_size = ciphertext.length(); |
| 301 scoped_ptr<char[]> plaintext(new char[plaintext_size]); | 260 scoped_ptr<char[]> plaintext(new char[plaintext_size]); |
| 302 | 261 |
| 303 if (!decrypter->Decrypt(nonce, associated_data, ciphertext, | 262 if (!decrypter->Decrypt(nonce, associated_data, ciphertext, |
| 304 reinterpret_cast<unsigned char*>(plaintext.get()), | 263 reinterpret_cast<unsigned char*>(plaintext.get()), |
| 305 &plaintext_size)) { | 264 &plaintext_size)) { |
| 306 return NULL; | 265 return NULL; |
| 307 } | 266 } |
| 308 return new QuicData(plaintext.release(), plaintext_size, true); | 267 return new QuicData(plaintext.release(), plaintext_size, true); |
| 309 } | 268 } |
| 310 | 269 |
| 311 TEST(Aes128Gcm12DecrypterTest, Decrypt) { | 270 TEST(Aes128Gcm12DecrypterTest, Decrypt) { |
| 312 if (!Aes128Gcm12Decrypter::IsSupported()) { | 271 if (!Aes128Gcm12Decrypter::IsSupported()) { |
| 313 LOG(INFO) << "AES GCM not supported. Test skipped."; | 272 LOG(INFO) << "AES GCM not supported. Test skipped."; |
| 314 return; | 273 return; |
| 315 } | 274 } |
| 316 | 275 |
| 317 char key[1024]; | 276 string key; |
| 318 size_t key_len; | 277 string iv; |
| 319 char iv[1024]; | 278 string ct; |
| 320 size_t iv_len; | 279 string aad; |
| 321 char ct[1024]; | 280 string tag; |
| 322 size_t ct_len; | 281 string pt; |
| 323 char aad[1024]; | |
| 324 size_t aad_len; | |
| 325 char tag[1024]; | |
| 326 size_t tag_len; | |
| 327 char pt[1024]; | |
| 328 size_t pt_len; | |
| 329 | 282 |
| 330 for (size_t i = 0; i < arraysize(test_group_array); i++) { | 283 for (size_t i = 0; i < arraysize(test_group_array); i++) { |
| 331 SCOPED_TRACE(i); | 284 SCOPED_TRACE(i); |
| 332 const TestVector* test_vector = test_group_array[i]; | 285 const TestVector* test_vector = test_group_array[i]; |
| 333 const TestGroupInfo& test_info = test_group_info[i]; | 286 const TestGroupInfo& test_info = test_group_info[i]; |
| 334 for (size_t j = 0; test_vector[j].key != NULL; j++) { | 287 for (size_t j = 0; test_vector[j].key != NULL; j++) { |
| 288 // If not present then decryption is expected to fail. |
| 289 bool has_pt = test_vector[j].pt; |
| 290 |
| 335 // Decode the test vector. | 291 // Decode the test vector. |
| 336 ASSERT_TRUE( | 292 ASSERT_TRUE(DecodeHexString(test_vector[j].key, &key)); |
| 337 DecodeHexString(test_vector[j].key, key, &key_len, sizeof(key))); | 293 ASSERT_TRUE(DecodeHexString(test_vector[j].iv, &iv)); |
| 338 ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len, sizeof(iv))); | 294 ASSERT_TRUE(DecodeHexString(test_vector[j].ct, &ct)); |
| 339 ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len, sizeof(ct))); | 295 ASSERT_TRUE(DecodeHexString(test_vector[j].aad, &aad)); |
| 340 ASSERT_TRUE( | 296 ASSERT_TRUE(DecodeHexString(test_vector[j].tag, &tag)); |
| 341 DecodeHexString(test_vector[j].aad, aad, &aad_len, sizeof(aad))); | 297 if (has_pt) |
| 342 ASSERT_TRUE( | 298 ASSERT_TRUE(DecodeHexString(test_vector[j].pt, &pt)); |
| 343 DecodeHexString(test_vector[j].tag, tag, &tag_len, sizeof(tag))); | |
| 344 ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len, sizeof(pt))); | |
| 345 | 299 |
| 346 // The test vector's lengths should look sane. Note that the lengths | 300 // The test vector's lengths should look sane. Note that the lengths |
| 347 // in |test_info| are in bits. | 301 // in |test_info| are in bits. |
| 348 EXPECT_EQ(test_info.key_len, key_len * 8); | 302 EXPECT_EQ(test_info.key_len, key.size() * 8); |
| 349 EXPECT_EQ(test_info.iv_len, iv_len * 8); | 303 EXPECT_EQ(test_info.iv_len, iv.size() * 8); |
| 350 EXPECT_EQ(test_info.pt_len, ct_len * 8); | 304 EXPECT_EQ(test_info.pt_len, pt.size() * 8); |
| 351 EXPECT_EQ(test_info.aad_len, aad_len * 8); | 305 EXPECT_EQ(test_info.aad_len, aad.size() * 8); |
| 352 EXPECT_EQ(test_info.tag_len, tag_len * 8); | 306 EXPECT_EQ(test_info.tag_len, tag.size() * 8); |
| 353 if (pt_len != static_cast<size_t>(-1)) { | 307 if (has_pt) |
| 354 EXPECT_EQ(test_info.pt_len, pt_len * 8); | 308 EXPECT_EQ(test_info.pt_len, pt.size() * 8); |
| 355 } | |
| 356 | 309 |
| 357 // The test vectors have 16 byte authenticators but this code only uses | 310 // The test vectors have 16 byte authenticators but this code only uses |
| 358 // the first 12. | 311 // the first 12. |
| 359 ASSERT_LE(static_cast<size_t>(Aes128Gcm12Decrypter::kAuthTagSize), | 312 ASSERT_LE(static_cast<size_t>(Aes128Gcm12Decrypter::kAuthTagSize), |
| 360 tag_len); | 313 tag.size()); |
| 361 tag_len = Aes128Gcm12Decrypter::kAuthTagSize; | 314 string ciphertext = |
| 315 ct + tag.substr(0, Aes128Gcm12Decrypter::kAuthTagSize); |
| 362 | 316 |
| 363 Aes128Gcm12Decrypter decrypter; | 317 Aes128Gcm12Decrypter decrypter; |
| 364 ASSERT_TRUE(decrypter.SetKey(StringPiece(key, key_len))); | 318 ASSERT_TRUE(decrypter.SetKey(key)); |
| 365 string ciphertext(ct, ct_len); | 319 |
| 366 ciphertext.append(tag, tag_len); | |
| 367 scoped_ptr<QuicData> decrypted(DecryptWithNonce( | 320 scoped_ptr<QuicData> decrypted(DecryptWithNonce( |
| 368 &decrypter, StringPiece(iv, iv_len), | 321 &decrypter, iv, |
| 369 // OpenSSL fails if NULL is set as the AAD, as opposed to a | 322 // OpenSSL fails if NULL is set as the AAD, as opposed to a |
| 370 // zero-length, non-NULL pointer. | 323 // zero-length, non-NULL pointer. |
| 371 StringPiece(aad_len ? aad : NULL, aad_len), ciphertext)); | 324 aad.size() ? aad : StringPiece(), ciphertext)); |
| 372 if (!decrypted.get()) { | 325 if (!decrypted.get()) { |
| 373 EXPECT_EQ((size_t)-1, pt_len); | 326 EXPECT_FALSE(has_pt); |
| 374 continue; | 327 continue; |
| 375 } | 328 } |
| 376 ASSERT_NE((size_t)-1, pt_len); | 329 EXPECT_TRUE(has_pt); |
| 377 | 330 |
| 378 ASSERT_EQ(pt_len, decrypted->length()); | 331 ASSERT_EQ(pt.size(), decrypted->length()); |
| 379 test::CompareCharArraysWithHexError("plaintext", decrypted->data(), | 332 test::CompareCharArraysWithHexError("plaintext", decrypted->data(), |
| 380 pt_len, pt, pt_len); | 333 pt.size(), pt.data(), pt.size()); |
| 381 } | 334 } |
| 382 } | 335 } |
| 383 } | 336 } |
| 384 | 337 |
| 385 } // namespace test | 338 } // namespace test |
| 386 } // namespace net | 339 } // namespace net |
| OLD | NEW |