ct_serialization.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. // Copyright 2013 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. #include "net/cert/ct_serialization.h"
  5. #include "base/logging.h"
  6. #include "base/numerics/checked_math.h"
  7. #include "crypto/sha2.h"
  8. #include "net/cert/merkle_tree_leaf.h"
  9. #include "net/cert/signed_certificate_timestamp.h"
  10. #include "net/cert/signed_tree_head.h"
  11. #include "third_party/boringssl/src/include/openssl/bytestring.h"
  12. namespace net::ct {
  13. namespace {
  14. const size_t kLogIdLength = crypto::kSHA256Length;
  15. enum SignatureType {
  16. SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP = 0,
  17. TREE_HASH = 1,
  18. };
  19. // Reads a variable-length SCT list that has been TLS encoded.
  20. // The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
  21. // |max_list_length| contains the overall length of the encoded list.
  22. // |max_item_length| contains the maximum length of a single item.
  23. // On success, returns true and updates |*out| with the encoded list.
  24. bool ReadSCTList(CBS* in, std::vector<base::StringPiece>* out) {
  25. std::vector<base::StringPiece> result;
  26. CBS sct_list_data;
  27. if (!CBS_get_u16_length_prefixed(in, &sct_list_data))
  28. return false;
  29. while (CBS_len(&sct_list_data) != 0) {
  30. CBS sct_list_item;
  31. if (!CBS_get_u16_length_prefixed(&sct_list_data, &sct_list_item) ||
  32. CBS_len(&sct_list_item) == 0) {
  33. return false;
  34. }
  35. result.emplace_back(reinterpret_cast<const char*>(CBS_data(&sct_list_item)),
  36. CBS_len(&sct_list_item));
  37. }
  38. result.swap(*out);
  39. return true;
  40. }
  41. // Checks and converts a hash algorithm.
  42. // |in| is the numeric representation of the algorithm.
  43. // If the hash algorithm value is in a set of known values, fills in |out| and
  44. // returns true. Otherwise, returns false.
  45. bool ConvertHashAlgorithm(unsigned in, DigitallySigned::HashAlgorithm* out) {
  46. switch (in) {
  47. case DigitallySigned::HASH_ALGO_NONE:
  48. case DigitallySigned::HASH_ALGO_MD5:
  49. case DigitallySigned::HASH_ALGO_SHA1:
  50. case DigitallySigned::HASH_ALGO_SHA224:
  51. case DigitallySigned::HASH_ALGO_SHA256:
  52. case DigitallySigned::HASH_ALGO_SHA384:
  53. case DigitallySigned::HASH_ALGO_SHA512:
  54. break;
  55. default:
  56. return false;
  57. }
  58. *out = static_cast<DigitallySigned::HashAlgorithm>(in);
  59. return true;
  60. }
  61. // Checks and converts a signing algorithm.
  62. // |in| is the numeric representation of the algorithm.
  63. // If the signing algorithm value is in a set of known values, fills in |out|
  64. // and returns true. Otherwise, returns false.
  65. bool ConvertSignatureAlgorithm(
  66. unsigned in,
  67. DigitallySigned::SignatureAlgorithm* out) {
  68. switch (in) {
  69. case DigitallySigned::SIG_ALGO_ANONYMOUS:
  70. case DigitallySigned::SIG_ALGO_RSA:
  71. case DigitallySigned::SIG_ALGO_DSA:
  72. case DigitallySigned::SIG_ALGO_ECDSA:
  73. break;
  74. default:
  75. return false;
  76. }
  77. *out = static_cast<DigitallySigned::SignatureAlgorithm>(in);
  78. return true;
  79. }
  80. // Writes a SignedEntryData of type X.509 cert to |*output|.
  81. // |input| is the SignedEntryData containing the certificate.
  82. // Returns true if the leaf_certificate in the SignedEntryData does not exceed
  83. // kMaxAsn1CertificateLength and so can be written to |output|.
  84. bool EncodeAsn1CertSignedEntry(const SignedEntryData& input, CBB* output) {
  85. CBB child;
  86. return CBB_add_u24_length_prefixed(output, &child) &&
  87. CBB_add_bytes(
  88. &child,
  89. reinterpret_cast<const uint8_t*>(input.leaf_certificate.data()),
  90. input.leaf_certificate.size()) &&
  91. CBB_flush(output);
  92. }
  93. // Writes a SignedEntryData of type PreCertificate to |*output|.
  94. // |input| is the SignedEntryData containing the TBSCertificate and issuer key
  95. // hash. Returns true if the TBSCertificate component in the SignedEntryData
  96. // does not exceed kMaxTbsCertificateLength and so can be written to |output|.
  97. bool EncodePrecertSignedEntry(const SignedEntryData& input, CBB* output) {
  98. CBB child;
  99. return CBB_add_bytes(
  100. output,
  101. reinterpret_cast<const uint8_t*>(input.issuer_key_hash.data),
  102. kLogIdLength) &&
  103. CBB_add_u24_length_prefixed(output, &child) &&
  104. CBB_add_bytes(
  105. &child,
  106. reinterpret_cast<const uint8_t*>(input.tbs_certificate.data()),
  107. input.tbs_certificate.size()) &&
  108. CBB_flush(output);
  109. }
  110. } // namespace
  111. bool EncodeDigitallySigned(const DigitallySigned& input, CBB* output_cbb) {
  112. CBB child;
  113. return CBB_add_u8(output_cbb, input.hash_algorithm) &&
  114. CBB_add_u8(output_cbb, input.signature_algorithm) &&
  115. CBB_add_u16_length_prefixed(output_cbb, &child) &&
  116. CBB_add_bytes(
  117. &child,
  118. reinterpret_cast<const uint8_t*>(input.signature_data.data()),
  119. input.signature_data.size()) &&
  120. CBB_flush(output_cbb);
  121. }
  122. bool EncodeDigitallySigned(const DigitallySigned& input,
  123. std::string* output) {
  124. bssl::ScopedCBB output_cbb;
  125. if (!CBB_init(output_cbb.get(), 64) ||
  126. !EncodeDigitallySigned(input, output_cbb.get()) ||
  127. !CBB_flush(output_cbb.get())) {
  128. return false;
  129. }
  130. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  131. CBB_len(output_cbb.get()));
  132. return true;
  133. }
  134. bool DecodeDigitallySigned(CBS* input, DigitallySigned* output) {
  135. uint8_t hash_algo;
  136. uint8_t sig_algo;
  137. CBS sig_data;
  138. if (!CBS_get_u8(input, &hash_algo) || !CBS_get_u8(input, &sig_algo) ||
  139. !CBS_get_u16_length_prefixed(input, &sig_data)) {
  140. return false;
  141. }
  142. DigitallySigned result;
  143. if (!ConvertHashAlgorithm(hash_algo, &result.hash_algorithm) ||
  144. !ConvertSignatureAlgorithm(sig_algo, &result.signature_algorithm)) {
  145. return false;
  146. }
  147. result.signature_data.assign(
  148. reinterpret_cast<const char*>(CBS_data(&sig_data)), CBS_len(&sig_data));
  149. *output = result;
  150. return true;
  151. }
  152. bool DecodeDigitallySigned(base::StringPiece* input, DigitallySigned* output) {
  153. CBS input_cbs;
  154. CBS_init(&input_cbs, reinterpret_cast<const uint8_t*>(input->data()),
  155. input->size());
  156. bool result = DecodeDigitallySigned(&input_cbs, output);
  157. input->remove_prefix(input->size() - CBS_len(&input_cbs));
  158. return result;
  159. }
  160. static bool EncodeSignedEntry(const SignedEntryData& input, CBB* output) {
  161. if (!CBB_add_u16(output, input.type)) {
  162. return false;
  163. }
  164. switch (input.type) {
  165. case SignedEntryData::LOG_ENTRY_TYPE_X509:
  166. return EncodeAsn1CertSignedEntry(input, output);
  167. case SignedEntryData::LOG_ENTRY_TYPE_PRECERT:
  168. return EncodePrecertSignedEntry(input, output);
  169. }
  170. return false;
  171. }
  172. bool EncodeSignedEntry(const SignedEntryData& input, std::string* output) {
  173. bssl::ScopedCBB output_cbb;
  174. if (!CBB_init(output_cbb.get(), 64) ||
  175. !EncodeSignedEntry(input, output_cbb.get()) ||
  176. !CBB_flush(output_cbb.get())) {
  177. return false;
  178. }
  179. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  180. CBB_len(output_cbb.get()));
  181. return true;
  182. }
  183. static bool ReadTimeSinceEpoch(CBS* input, base::Time* output) {
  184. uint64_t time_since_epoch = 0;
  185. if (!CBS_get_u64(input, &time_since_epoch))
  186. return false;
  187. base::CheckedNumeric<int64_t> time_since_epoch_signed = time_since_epoch;
  188. if (!time_since_epoch_signed.IsValid()) {
  189. return false;
  190. }
  191. *output = base::Time::UnixEpoch() +
  192. base::Milliseconds(int64_t{time_since_epoch_signed.ValueOrDie()});
  193. return true;
  194. }
  195. static bool WriteTimeSinceEpoch(const base::Time& timestamp, CBB* output) {
  196. base::TimeDelta time_since_epoch = timestamp - base::Time::UnixEpoch();
  197. return CBB_add_u64(output, time_since_epoch.InMilliseconds());
  198. }
  199. bool EncodeTreeLeaf(const MerkleTreeLeaf& leaf, std::string* output) {
  200. bssl::ScopedCBB output_cbb;
  201. CBB child;
  202. if (!CBB_init(output_cbb.get(), 64) ||
  203. !CBB_add_u8(output_cbb.get(), 0) || // version: 1
  204. !CBB_add_u8(output_cbb.get(), 0) || // type: timestamped entry
  205. !WriteTimeSinceEpoch(leaf.timestamp, output_cbb.get()) ||
  206. !EncodeSignedEntry(leaf.signed_entry, output_cbb.get()) ||
  207. !CBB_add_u16_length_prefixed(output_cbb.get(), &child) ||
  208. !CBB_add_bytes(&child,
  209. reinterpret_cast<const uint8_t*>(leaf.extensions.data()),
  210. leaf.extensions.size()) ||
  211. !CBB_flush(output_cbb.get())) {
  212. return false;
  213. }
  214. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  215. CBB_len(output_cbb.get()));
  216. return true;
  217. }
  218. bool EncodeV1SCTSignedData(const base::Time& timestamp,
  219. const std::string& serialized_log_entry,
  220. const std::string& extensions,
  221. std::string* output) {
  222. bssl::ScopedCBB output_cbb;
  223. CBB child;
  224. if (!CBB_init(output_cbb.get(), 64) ||
  225. !CBB_add_u8(output_cbb.get(), SignedCertificateTimestamp::V1) ||
  226. !CBB_add_u8(output_cbb.get(), SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP) ||
  227. !WriteTimeSinceEpoch(timestamp, output_cbb.get()) ||
  228. // NOTE: serialized_log_entry must already be serialized and contain the
  229. // length as the prefix.
  230. !CBB_add_bytes(
  231. output_cbb.get(),
  232. reinterpret_cast<const uint8_t*>(serialized_log_entry.data()),
  233. serialized_log_entry.size()) ||
  234. !CBB_add_u16_length_prefixed(output_cbb.get(), &child) ||
  235. !CBB_add_bytes(&child,
  236. reinterpret_cast<const uint8_t*>(extensions.data()),
  237. extensions.size()) ||
  238. !CBB_flush(output_cbb.get())) {
  239. return false;
  240. }
  241. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  242. CBB_len(output_cbb.get()));
  243. return true;
  244. }
  245. bool EncodeTreeHeadSignature(const SignedTreeHead& signed_tree_head,
  246. std::string* output) {
  247. bssl::ScopedCBB output_cbb;
  248. if (!CBB_init(output_cbb.get(), 64) ||
  249. !CBB_add_u8(output_cbb.get(), signed_tree_head.version) ||
  250. !CBB_add_u8(output_cbb.get(), TREE_HASH) ||
  251. !WriteTimeSinceEpoch(signed_tree_head.timestamp, output_cbb.get()) ||
  252. !CBB_add_u64(output_cbb.get(), signed_tree_head.tree_size) ||
  253. !CBB_add_bytes(
  254. output_cbb.get(),
  255. reinterpret_cast<const uint8_t*>(signed_tree_head.sha256_root_hash),
  256. kSthRootHashLength)) {
  257. return false;
  258. }
  259. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  260. CBB_len(output_cbb.get()));
  261. return true;
  262. }
  263. bool DecodeSCTList(base::StringPiece input,
  264. std::vector<base::StringPiece>* output) {
  265. std::vector<base::StringPiece> result;
  266. CBS input_cbs;
  267. CBS_init(&input_cbs, reinterpret_cast<const uint8_t*>(input.data()),
  268. input.size());
  269. if (!ReadSCTList(&input_cbs, &result) || CBS_len(&input_cbs) != 0 ||
  270. result.empty()) {
  271. return false;
  272. }
  273. output->swap(result);
  274. return true;
  275. }
  276. bool DecodeSignedCertificateTimestamp(
  277. base::StringPiece* input,
  278. scoped_refptr<SignedCertificateTimestamp>* output) {
  279. auto result = base::MakeRefCounted<SignedCertificateTimestamp>();
  280. uint8_t version;
  281. CBS input_cbs;
  282. CBS_init(&input_cbs, reinterpret_cast<const uint8_t*>(input->data()),
  283. input->size());
  284. if (!CBS_get_u8(&input_cbs, &version) ||
  285. version != SignedCertificateTimestamp::V1) {
  286. return false;
  287. }
  288. result->version = SignedCertificateTimestamp::V1;
  289. CBS log_id;
  290. CBS extensions;
  291. if (!CBS_get_bytes(&input_cbs, &log_id, kLogIdLength) ||
  292. !ReadTimeSinceEpoch(&input_cbs, &result->timestamp) ||
  293. !CBS_get_u16_length_prefixed(&input_cbs, &extensions) ||
  294. !DecodeDigitallySigned(&input_cbs, &result->signature)) {
  295. return false;
  296. }
  297. result->log_id.assign(reinterpret_cast<const char*>(CBS_data(&log_id)),
  298. CBS_len(&log_id));
  299. result->extensions.assign(
  300. reinterpret_cast<const char*>(CBS_data(&extensions)),
  301. CBS_len(&extensions));
  302. output->swap(result);
  303. input->remove_prefix(input->size() - CBS_len(&input_cbs));
  304. return true;
  305. }
  306. bool EncodeSignedCertificateTimestamp(
  307. const scoped_refptr<ct::SignedCertificateTimestamp>& input,
  308. std::string* output) {
  309. // This function only supports serialization of V1 SCTs.
  310. DCHECK_EQ(SignedCertificateTimestamp::V1, input->version);
  311. DCHECK_EQ(kLogIdLength, input->log_id.size());
  312. bssl::ScopedCBB output_cbb;
  313. CBB child;
  314. if (!CBB_init(output_cbb.get(), 64) ||
  315. !CBB_add_u8(output_cbb.get(), input->version) ||
  316. !CBB_add_bytes(output_cbb.get(),
  317. reinterpret_cast<const uint8_t*>(input->log_id.data()),
  318. kLogIdLength) ||
  319. !WriteTimeSinceEpoch(input->timestamp, output_cbb.get()) ||
  320. !CBB_add_u16_length_prefixed(output_cbb.get(), &child) ||
  321. !CBB_add_bytes(&child,
  322. reinterpret_cast<const uint8_t*>(input->extensions.data()),
  323. input->extensions.size()) ||
  324. !EncodeDigitallySigned(input->signature, output_cbb.get()) ||
  325. !CBB_flush(output_cbb.get())) {
  326. return false;
  327. }
  328. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  329. CBB_len(output_cbb.get()));
  330. return true;
  331. }
  332. bool EncodeSCTListForTesting(const base::StringPiece& sct,
  333. std::string* output) {
  334. bssl::ScopedCBB encoded_sct, output_cbb;
  335. CBB encoded_sct_child, output_child;
  336. if (!CBB_init(encoded_sct.get(), 64) || !CBB_init(output_cbb.get(), 64) ||
  337. !CBB_add_u16_length_prefixed(encoded_sct.get(), &encoded_sct_child) ||
  338. !CBB_add_bytes(&encoded_sct_child,
  339. reinterpret_cast<const uint8_t*>(sct.data()),
  340. sct.size()) ||
  341. !CBB_flush(encoded_sct.get()) ||
  342. !CBB_add_u16_length_prefixed(output_cbb.get(), &output_child) ||
  343. !CBB_add_bytes(&output_child, CBB_data(encoded_sct.get()),
  344. CBB_len(encoded_sct.get())) ||
  345. !CBB_flush(output_cbb.get())) {
  346. return false;
  347. }
  348. output->append(reinterpret_cast<const char*>(CBB_data(output_cbb.get())),
  349. CBB_len(output_cbb.get()));
  350. return true;
  351. }
  352. } // namespace net::ct