1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/quic/crypto/chacha20_poly1305_encrypter.h" 6 7 #include "net/quic/test_tools/quic_test_utils.h" 8 9 using base::StringPiece; 10 11 namespace { 12 13 // The test vectors come from draft-agl-tls-chacha20poly1305-04 Section 7. 14 15 // Each test vector consists of five strings of lowercase hexadecimal digits. 16 // The strings may be empty (zero length). A test vector with a NULL |key| 17 // marks the end of an array of test vectors. 18 struct TestVector { 19 const char* key; 20 const char* pt; 21 const char* iv; 22 const char* aad; 23 const char* ct; 24 }; 25 26 const TestVector test_vectors[] = { 27 { "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110" 28 "0a1007", 29 "86d09974840bded2a5ca", 30 "cd7cf67be39c794a", 31 "87e229d4500845a079c0", 32 "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475" // "3896e1d6" truncated. 33 }, 34 { NULL } 35 }; 36 37 } // namespace 38 39 namespace net { 40 namespace test { 41 42 // EncryptWithNonce wraps the |Encrypt| method of |encrypter| to allow passing 43 // in an nonce and also to allocate the buffer needed for the ciphertext. 44 QuicData* EncryptWithNonce(ChaCha20Poly1305Encrypter* encrypter, 45 StringPiece nonce, 46 StringPiece associated_data, 47 StringPiece plaintext) { 48 size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length()); 49 scoped_ptr<char[]> ciphertext(new char[ciphertext_size]); 50 51 if (!encrypter->Encrypt(nonce, associated_data, plaintext, 52 reinterpret_cast<unsigned char*>(ciphertext.get()))) { 53 return NULL; 54 } 55 56 return new QuicData(ciphertext.release(), ciphertext_size, true); 57 } 58 59 TEST(ChaCha20Poly1305EncrypterTest, Encrypt) { 60 if (!ChaCha20Poly1305Encrypter::IsSupported()) { 61 LOG(INFO) << "ChaCha20+Poly1305 not supported. Test skipped."; 62 return; 63 } 64 65 for (size_t i = 0; test_vectors[i].key != NULL; i++) { 66 // Decode the test vector. 67 string key; 68 string pt; 69 string iv; 70 string aad; 71 string ct; 72 ASSERT_TRUE(DecodeHexString(test_vectors[i].key, &key)); 73 ASSERT_TRUE(DecodeHexString(test_vectors[i].pt, &pt)); 74 ASSERT_TRUE(DecodeHexString(test_vectors[i].iv, &iv)); 75 ASSERT_TRUE(DecodeHexString(test_vectors[i].aad, &aad)); 76 ASSERT_TRUE(DecodeHexString(test_vectors[i].ct, &ct)); 77 78 ChaCha20Poly1305Encrypter encrypter; 79 ASSERT_TRUE(encrypter.SetKey(key)); 80 scoped_ptr<QuicData> encrypted(EncryptWithNonce( 81 &encrypter, iv, 82 // This deliberately tests that the encrypter can handle an AAD that 83 // is set to NULL, as opposed to a zero-length, non-NULL pointer. 84 StringPiece(aad.length() ? aad.data() : NULL, aad.length()), pt)); 85 ASSERT_TRUE(encrypted.get()); 86 87 test::CompareCharArraysWithHexError("ciphertext", encrypted->data(), 88 encrypted->length(), ct.data(), 89 ct.length()); 90 } 91 } 92 93 TEST(ChaCha20Poly1305EncrypterTest, GetMaxPlaintextSize) { 94 ChaCha20Poly1305Encrypter encrypter; 95 EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012)); 96 EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112)); 97 EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22)); 98 } 99 100 TEST(ChaCha20Poly1305EncrypterTest, GetCiphertextSize) { 101 ChaCha20Poly1305Encrypter encrypter; 102 EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000)); 103 EXPECT_EQ(112u, encrypter.GetCiphertextSize(100)); 104 EXPECT_EQ(22u, encrypter.GetCiphertextSize(10)); 105 } 106 107 } // namespace test 108 } // namespace net 109