1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "CTSerialization.h"
8 #include "CTTestUtils.h"
9 #include "gtest/gtest.h"
10 #include "mozilla/Move.h"
11 
12 namespace mozilla { namespace ct {
13 
14 using namespace pkix;
15 
16 class CTSerializationTest : public ::testing::Test
17 {
18 public:
SetUp()19   void SetUp() override
20   {
21     mTestDigitallySigned = GetTestDigitallySigned();
22     mTestSignatureData = GetTestDigitallySignedData();
23   }
24 
25 protected:
26   Buffer mTestDigitallySigned;
27   Buffer mTestSignatureData;
28 };
29 
TEST_F(CTSerializationTest,DecodesDigitallySigned)30 TEST_F(CTSerializationTest, DecodesDigitallySigned)
31 {
32   Input digitallySigned = InputForBuffer(mTestDigitallySigned);
33   Reader digitallySignedReader(digitallySigned);
34 
35   DigitallySigned parsed;
36   ASSERT_EQ(Success,
37     DecodeDigitallySigned(digitallySignedReader, parsed));
38   EXPECT_TRUE(digitallySignedReader.AtEnd());
39 
40   EXPECT_EQ(DigitallySigned::HashAlgorithm::SHA256,
41             parsed.hashAlgorithm);
42   EXPECT_EQ(DigitallySigned::SignatureAlgorithm::ECDSA,
43             parsed.signatureAlgorithm);
44   EXPECT_EQ(mTestSignatureData, parsed.signatureData);
45 }
46 
TEST_F(CTSerializationTest,FailsToDecodePartialDigitallySigned)47 TEST_F(CTSerializationTest, FailsToDecodePartialDigitallySigned)
48 {
49   Input partial;
50   ASSERT_EQ(Success,
51     partial.Init(mTestDigitallySigned.begin(),
52       mTestDigitallySigned.length() - 5));
53   Reader partialReader(partial);
54 
55   DigitallySigned parsed;
56 
57   EXPECT_NE(Success, DecodeDigitallySigned(partialReader, parsed));
58 }
59 
TEST_F(CTSerializationTest,EncodesDigitallySigned)60 TEST_F(CTSerializationTest, EncodesDigitallySigned)
61 {
62   DigitallySigned digitallySigned;
63   digitallySigned.hashAlgorithm =
64     DigitallySigned::HashAlgorithm::SHA256;
65   digitallySigned.signatureAlgorithm =
66     DigitallySigned::SignatureAlgorithm::ECDSA;
67   digitallySigned.signatureData = cloneBuffer(mTestSignatureData);
68 
69   Buffer encoded;
70 
71   ASSERT_EQ(Success, EncodeDigitallySigned(digitallySigned, encoded));
72   EXPECT_EQ(mTestDigitallySigned, encoded);
73 }
74 
TEST_F(CTSerializationTest,EncodesLogEntryForX509Cert)75 TEST_F(CTSerializationTest, EncodesLogEntryForX509Cert)
76 {
77   LogEntry entry;
78   GetX509CertLogEntry(entry);
79 
80   Buffer encoded;
81   ASSERT_EQ(Success, EncodeLogEntry(entry, encoded));
82   EXPECT_EQ((718U + 5U), encoded.length());
83   // First two bytes are log entry type. Next, length:
84   // Length is 718 which is 512 + 206, which is 0x2ce
85   Buffer expectedPrefix;
86   MOZ_RELEASE_ASSERT(expectedPrefix.append("\0\0\0\x2\xCE", 5));
87   Buffer encodedPrefix;
88   MOZ_RELEASE_ASSERT(encodedPrefix.
89     append(encoded.begin(), encoded.begin() + 5));
90   EXPECT_EQ(expectedPrefix, encodedPrefix);
91 }
92 
TEST_F(CTSerializationTest,EncodesLogEntryForPrecert)93 TEST_F(CTSerializationTest, EncodesLogEntryForPrecert)
94 {
95   LogEntry entry;
96   GetPrecertLogEntry(entry);
97 
98   Buffer encoded;
99   ASSERT_EQ(Success, EncodeLogEntry(entry, encoded));
100   // log entry type + issuer key + length + tbsCertificate
101   EXPECT_EQ((2U + 32U + 3U + entry.tbsCertificate.length()), encoded.length());
102 
103   // First two bytes are log entry type.
104   Buffer expectedPrefix;
105   MOZ_RELEASE_ASSERT(expectedPrefix.append("\0\x1", 2));
106   Buffer encodedPrefix;
107   MOZ_RELEASE_ASSERT(encodedPrefix.
108     append(encoded.begin(), encoded.begin() + 2));
109   EXPECT_EQ(expectedPrefix, encodedPrefix);
110 
111   // Next is the issuer key (32 bytes).
112   Buffer encodedKeyHash;
113   MOZ_RELEASE_ASSERT(encodedKeyHash.
114     append(encoded.begin() + 2, encoded.begin() + 2 + 32));
115   EXPECT_EQ(GetDefaultIssuerKeyHash(), encodedKeyHash);
116 }
117 
TEST_F(CTSerializationTest,EncodesV1SCTSignedData)118 TEST_F(CTSerializationTest, EncodesV1SCTSignedData)
119 {
120   uint64_t timestamp = UINT64_C(0x139fe353cf5);
121   const uint8_t DUMMY_BYTES[] = { 0x61, 0x62, 0x63 }; // abc
122   Input dummyEntry(DUMMY_BYTES);
123   Input emptyExtensions;
124   Buffer encoded;
125   ASSERT_EQ(Success, EncodeV1SCTSignedData(
126     timestamp, dummyEntry, emptyExtensions, encoded));
127   EXPECT_EQ((size_t) 15, encoded.length());
128 
129   const uint8_t EXPECTED_BYTES[] = {
130     0x00, // version
131     0x00, // signature type
132     0x00, 0x00, 0x01, 0x39, 0xFE, 0x35, 0x3C, 0xF5, // timestamp
133     0x61, 0x62, 0x63, // log signature
134     0x00, 0x00 // extensions (empty)
135   };
136   Buffer expectedBuffer;
137   MOZ_RELEASE_ASSERT(
138     expectedBuffer.append(EXPECTED_BYTES, sizeof(EXPECTED_BYTES)));
139   EXPECT_EQ(expectedBuffer, encoded);
140 }
141 
TEST_F(CTSerializationTest,DecodesSCTList)142 TEST_F(CTSerializationTest, DecodesSCTList)
143 {
144   // Two items in the list: "abc", "def"
145   const uint8_t ENCODED[] = {
146     0x00, 0x0a, 0x00, 0x03, 0x61, 0x62, 0x63, 0x00, 0x03, 0x64, 0x65, 0x66
147   };
148   const uint8_t DECODED_1[] = { 0x61, 0x62, 0x63 };
149   const uint8_t DECODED_2[] = { 0x64, 0x65, 0x66 };
150 
151   Reader listReader;
152   ASSERT_EQ(Success, DecodeSCTList(Input(ENCODED), listReader));
153 
154   Input decoded1;
155   ASSERT_EQ(Success, ReadSCTListItem(listReader, decoded1));
156 
157   Input decoded2;
158   ASSERT_EQ(Success, ReadSCTListItem(listReader, decoded2));
159 
160   EXPECT_TRUE(listReader.AtEnd());
161   EXPECT_TRUE(InputsAreEqual(decoded1, Input(DECODED_1)));
162   EXPECT_TRUE(InputsAreEqual(decoded2, Input(DECODED_2)));
163 }
164 
TEST_F(CTSerializationTest,FailsDecodingInvalidSCTList)165 TEST_F(CTSerializationTest, FailsDecodingInvalidSCTList)
166 {
167   // A list with one item that's too short (the second one)
168   const uint8_t ENCODED[] = {
169     0x00, 0x0a, 0x00, 0x03, 0x61, 0x62, 0x63, 0x00, 0x05, 0x64, 0x65, 0x66
170   };
171 
172   Reader listReader;
173   ASSERT_EQ(Success, DecodeSCTList(Input(ENCODED), listReader));
174   Input decoded1;
175   EXPECT_EQ(Success, ReadSCTListItem(listReader, decoded1));
176   Input decoded2;
177   EXPECT_NE(Success, ReadSCTListItem(listReader, decoded2));
178 }
179 
TEST_F(CTSerializationTest,EncodesSCTList)180 TEST_F(CTSerializationTest, EncodesSCTList)
181 {
182   const uint8_t SCT_1[] = { 0x61, 0x62, 0x63 };
183   const uint8_t SCT_2[] = { 0x64, 0x65, 0x66 };
184 
185   Vector<Input> list;
186   ASSERT_TRUE(list.append(Move(Input(SCT_1))));
187   ASSERT_TRUE(list.append(Move(Input(SCT_2))));
188 
189   Buffer encodedList;
190   ASSERT_EQ(Success, EncodeSCTList(list, encodedList));
191 
192   Reader listReader;
193   ASSERT_EQ(Success, DecodeSCTList(InputForBuffer(encodedList), listReader));
194 
195   Input decoded1;
196   ASSERT_EQ(Success, ReadSCTListItem(listReader, decoded1));
197   EXPECT_TRUE(InputsAreEqual(decoded1, Input(SCT_1)));
198 
199   Input decoded2;
200   ASSERT_EQ(Success, ReadSCTListItem(listReader, decoded2));
201   EXPECT_TRUE(InputsAreEqual(decoded2, Input(SCT_2)));
202 
203   EXPECT_TRUE(listReader.AtEnd());
204 }
205 
TEST_F(CTSerializationTest,DecodesSignedCertificateTimestamp)206 TEST_F(CTSerializationTest, DecodesSignedCertificateTimestamp)
207 {
208   Buffer encodedSctBuffer = GetTestSignedCertificateTimestamp();
209   Input encodedSctInput = InputForBuffer(encodedSctBuffer);
210   Reader encodedSctReader(encodedSctInput);
211 
212   SignedCertificateTimestamp sct;
213   ASSERT_EQ(Success,
214     DecodeSignedCertificateTimestamp(encodedSctReader, sct));
215   EXPECT_EQ(SignedCertificateTimestamp::Version::V1, sct.version);
216   EXPECT_EQ(GetTestPublicKeyId(), sct.logId);
217   const uint64_t expectedTime = 1365181456089;
218   EXPECT_EQ(expectedTime, sct.timestamp);
219   const size_t expectedSignatureLength = 71;
220   EXPECT_EQ(expectedSignatureLength, sct.signature.signatureData.length());
221   EXPECT_TRUE(sct.extensions.empty());
222 }
223 
TEST_F(CTSerializationTest,FailsDecodingInvalidSignedCertificateTimestamp)224 TEST_F(CTSerializationTest, FailsDecodingInvalidSignedCertificateTimestamp)
225 {
226   SignedCertificateTimestamp sct;
227 
228   // Invalid version
229   const uint8_t INVALID_VERSION_BYTES[] = { 0x02, 0x00 };
230   Input invalidVersionSctInput(INVALID_VERSION_BYTES);
231   Reader invalidVersionSctReader(invalidVersionSctInput);
232   EXPECT_EQ(Result::ERROR_BAD_DER,
233     DecodeSignedCertificateTimestamp(invalidVersionSctReader, sct));
234 
235   // Valid version, invalid length (missing data)
236   const uint8_t INVALID_LENGTH_BYTES[] = { 0x00, 0x0a, 0x0b, 0x0c };
237   Input invalidLengthSctInput(INVALID_LENGTH_BYTES);
238   Reader invalidLengthSctReader(invalidLengthSctInput);
239   EXPECT_EQ(Result::ERROR_BAD_DER,
240     DecodeSignedCertificateTimestamp(invalidLengthSctReader, sct));
241 }
242 
TEST_F(CTSerializationTest,EncodesValidSignedTreeHead)243 TEST_F(CTSerializationTest, EncodesValidSignedTreeHead)
244 {
245   SignedTreeHead signedTreeHead;
246   GetSampleSignedTreeHead(signedTreeHead);
247 
248   Buffer encoded;
249   ASSERT_EQ(Success,
250     EncodeTreeHeadSignature(signedTreeHead, encoded));
251   // Expected size is 50 bytes:
252   // Byte 0 is version, byte 1 is signature type
253   // Bytes 2-9 are timestamp
254   // Bytes 10-17 are tree size
255   // Bytes 18-49 are sha256 root hash
256   ASSERT_EQ(50u, encoded.length());
257   const uint8_t EXPECTED_BYTES_PREFIX[] = {
258     0x00, // version
259     0x01, // signature type
260     0x00, 0x00, 0x01, 0x45, 0x3c, 0x5f, 0xb8, 0x35, // timestamp
261     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15  // tree size
262     // sha256 root hash should follow
263   };
264   Buffer expectedBuffer;
265   MOZ_RELEASE_ASSERT(expectedBuffer.append(EXPECTED_BYTES_PREFIX, 18));
266   Buffer hash = GetSampleSTHSHA256RootHash();
267   MOZ_RELEASE_ASSERT(expectedBuffer.append(hash.begin(), hash.length()));
268   EXPECT_EQ(expectedBuffer, encoded);
269 }
270 
271 } }  // namespace mozilla::ct
272