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