Coverage Report

Created: 2018-09-25 14:53

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