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_decrypter.h" 6 7#include "net/quic/test_tools/quic_test_utils.h" 8 9using base::StringPiece; 10 11namespace { 12 13// The test vectors come from draft-agl-tls-chacha20poly1305-04 Section 7. 14 15// Each test vector consists of six 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. 18struct TestVector { 19 // Input: 20 const char* key; 21 const char* iv; 22 const char* aad; 23 const char* ct; 24 25 // Expected output: 26 const char* pt; // An empty string "" means decryption succeeded and 27 // the plaintext is zero-length. NULL means decryption 28 // failed. 29}; 30 31const TestVector test_vectors[] = { 32 { "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110" 33 "0a1007", 34 "cd7cf67be39c794a", 35 "87e229d4500845a079c0", 36 "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475", // "3896e1d6" truncated. 37 "86d09974840bded2a5ca" 38 }, 39 // Modify the ciphertext (ChaCha20 encryption output). 40 { "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110" 41 "0a1007", 42 "cd7cf67be39c794a", 43 "87e229d4500845a079c0", 44 "f3e446f7ede9a19b62a4677dabf4e3d24b876bb28475", // "3896e1d6" truncated. 45 NULL // FAIL 46 }, 47 // Modify the ciphertext (Poly1305 authenticator). 48 { "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110" 49 "0a1007", 50 "cd7cf67be39c794a", 51 "87e229d4500845a079c0", 52 "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28476", // "3896e1d6" truncated. 53 NULL // FAIL 54 }, 55 // Modify the associated data. 56 { "4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd110" 57 "0a1007", 58 "dd7cf67be39c794a", 59 "87e229d4500845a079c0", 60 "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475", // "3896e1d6" truncated. 61 NULL // FAIL 62 }, 63 { NULL } 64}; 65 66} // namespace 67 68namespace net { 69namespace test { 70 71// DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing 72// in an nonce and also to allocate the buffer needed for the plaintext. 73QuicData* DecryptWithNonce(ChaCha20Poly1305Decrypter* decrypter, 74 StringPiece nonce, 75 StringPiece associated_data, 76 StringPiece ciphertext) { 77 size_t plaintext_size = ciphertext.length(); 78 scoped_ptr<char[]> plaintext(new char[plaintext_size]); 79 80 if (!decrypter->Decrypt(nonce, associated_data, ciphertext, 81 reinterpret_cast<unsigned char*>(plaintext.get()), 82 &plaintext_size)) { 83 return NULL; 84 } 85 return new QuicData(plaintext.release(), plaintext_size, true); 86} 87 88TEST(ChaCha20Poly1305DecrypterTest, Decrypt) { 89 if (!ChaCha20Poly1305Decrypter::IsSupported()) { 90 LOG(INFO) << "ChaCha20+Poly1305 not supported. Test skipped."; 91 return; 92 } 93 94 for (size_t i = 0; test_vectors[i].key != NULL; i++) { 95 // If not present then decryption is expected to fail. 96 bool has_pt = test_vectors[i].pt; 97 98 // Decode the test vector. 99 string key; 100 string iv; 101 string aad; 102 string ct; 103 string pt; 104 ASSERT_TRUE(DecodeHexString(test_vectors[i].key, &key)); 105 ASSERT_TRUE(DecodeHexString(test_vectors[i].iv, &iv)); 106 ASSERT_TRUE(DecodeHexString(test_vectors[i].aad, &aad)); 107 ASSERT_TRUE(DecodeHexString(test_vectors[i].ct, &ct)); 108 if (has_pt) { 109 ASSERT_TRUE(DecodeHexString(test_vectors[i].pt, &pt)); 110 } 111 112 ChaCha20Poly1305Decrypter decrypter; 113 ASSERT_TRUE(decrypter.SetKey(key)); 114 scoped_ptr<QuicData> decrypted(DecryptWithNonce( 115 &decrypter, iv, 116 // This deliberately tests that the decrypter can handle an AAD that 117 // is set to NULL, as opposed to a zero-length, non-NULL pointer. 118 StringPiece(aad.length() ? aad.data() : NULL, aad.length()), ct)); 119 if (!decrypted.get()) { 120 EXPECT_FALSE(has_pt); 121 continue; 122 } 123 EXPECT_TRUE(has_pt); 124 125 ASSERT_EQ(pt.length(), decrypted->length()); 126 test::CompareCharArraysWithHexError("plaintext", decrypted->data(), 127 pt.length(), pt.data(), pt.length()); 128 } 129} 130 131} // namespace test 132} // namespace net 133