CTSerializationTest.cpp 8.4 KB

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