Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Unified Diff: net/cert/ct_serialization.cc

Issue 1576513002: Serialisation code for Certificate Transparency data (Closed) Base URL: ssh://caladan.lon.corp.google.com/usr/local/google/eranm/opensource_clients/chrome/src@sth_consistency_validation_2
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/cert/ct_serialization.cc
diff --git a/net/cert/ct_serialization.cc b/net/cert/ct_serialization.cc
index 235d37e65ad1fc8106a05d602c3c9f04b4e61a48..2beacc681f4ecc5442fb94e2790c163341533dff 100644
--- a/net/cert/ct_serialization.cc
+++ b/net/cert/ct_serialization.cc
@@ -9,6 +9,9 @@
#include <limits>
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
+#include "net/cert/merkle_consistency_proof.h"
namespace net {
@@ -40,6 +43,16 @@ const size_t kSerializedSCTLengthBytes = 2;
// Members of digitally-signed struct of a STH
const size_t kTreeSizeLength = 8;
+// Members of a V1 Consistency Proof
+const size_t kSha256HashLength = 32;
+const size_t kConsistencyPathLengthBytes = 8;
+
+// Length of the version field in a TransItem struct
+const size_t kTransItemVersionLength = 1;
+
+// Length of the type field in a TransItem{V1,V2} struct
+const size_t kTransTypeLength = 1;
+
enum SignatureType {
SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP = 0,
TREE_HASH = 1,
@@ -312,6 +325,9 @@ bool EncodeV1SCTSignedData(const base::Time& timestamp,
return WriteVariableBytes(kExtensionsLengthBytes, extensions, output);
}
+// TODO(robpercival): This could probably be named better, since the one thing
+// this doesn't encode is the signature. Perhaps just EncodeTreeHead, or
+// EncodeTreeHeadForSignature?
void EncodeTreeHeadSignature(const SignedTreeHead& signed_tree_head,
std::string* output) {
WriteUint(kVersionLength, signed_tree_head.version, output);
@@ -377,6 +393,20 @@ bool DecodeSignedCertificateTimestamp(
return true;
}
+bool EncodeSignedCertificateTimestamp(const SignedCertificateTimestamp& input,
+ std::string* output) {
+ WriteUint(kVersionLength, input.version, output);
+ DCHECK_EQ(kLogIdLength, WriteEncodedBytes(input.log_id, output));
+ WriteTimeSinceEpoch(input.timestamp, output);
+
+ if (!WriteVariableBytes(kExtensionsLengthBytes, input.extensions, output) ||
+ !EncodeDigitallySigned(input.signature, output)) {
+ return false;
+ }
+
+ return true;
+}
+
bool EncodeSCTListForTesting(const base::StringPiece& sct,
std::string* output) {
std::string encoded_sct;
@@ -384,6 +414,166 @@ bool EncodeSCTListForTesting(const base::StringPiece& sct,
WriteVariableBytes(kSCTListLengthBytes, encoded_sct, output);
}
+bool DecodeSignedTreeHead(base::StringPiece* input, SignedTreeHead* output) {
+ base::StringPiece log_id;
+ base::StringPiece sha256_root_hash;
+ if (!ReadFixedBytes(kLogIdLength, input, &log_id) ||
+ !ReadTimeSinceEpoch(input, &output->timestamp) ||
+ !ReadUint(kTreeSizeLength, input, &output->tree_size) ||
+ !ReadFixedBytes(kSthRootHashLength, input, &sha256_root_hash)) {
+ return false;
+ }
+
+ log_id.CopyToString(&output->log_id);
Eran Messeri 2016/01/14 12:46:45 A common pattern in this file is to decode to a te
+ log_id.copy(output->sha256_root_hash, kSthRootHashLength);
+ return true;
+}
+
+bool EncodeSignedTreeHead(const SignedTreeHead& input, std::string* output) {
+ DCHECK_EQ(kLogIdLength, WriteEncodedBytes(input.log_id, output));
+ WriteTimeSinceEpoch(input.timestamp, output);
+ WriteUint(kTreeSizeLength, input.tree_size, output);
+
+ base::StringPiece root_hash(input.sha256_root_hash, kSthRootHashLength);
+ WriteEncodedBytes(root_hash, output);
+
+ if (!EncodeDigitallySigned(input.signature, output)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool DecodeConsistencyProof(base::StringPiece* input,
+ MerkleConsistencyProof* output) {
+ base::StringPiece log_id;
+ if (!ReadFixedBytes(kLogIdLength, input, &log_id)) {
+ return false;
+ }
+ log_id.CopyToString(&output->log_id);
+
+ if (!ReadUint(kTreeSizeLength, input, &output->first_tree_size)) {
+ return false;
+ }
+
+ if (!ReadUint(kTreeSizeLength, input, &output->second_tree_size)) {
+ return false;
+ }
+
+ base::StringPiece consistency_path;
+ if (!ReadVariableBytes(kConsistencyPathLengthBytes, input,
+ &consistency_path)) {
+ return false;
+ }
+
+ for (size_t i = 0; i < consistency_path.size() / kSha256HashLength; ++i) {
+ base::StringPiece node_hash =
+ consistency_path.substr(kSha256HashLength * i, kSha256HashLength);
+
+ output->nodes.push_back(node_hash.as_string());
+ }
+
+ return true;
+}
+
+bool EncodeConsistencyProof(const MerkleConsistencyProof& input,
+ std::string* output) {
+ WriteEncodedBytes(input.log_id, output);
+ WriteUint(kTreeSizeLength, input.first_tree_size, output);
+ WriteUint(kTreeSizeLength, input.second_tree_size, output);
+
+ std::string consistency_path = base::JoinString(input.nodes, "");
+ if (!WriteVariableBytes(kConsistencyPathLengthBytes, consistency_path,
+ output)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool DecodeTransItem(base::StringPiece* input, TransItem* output) {
+ unsigned version;
+ if (!ReadUint(kTransItemVersionLength, input, &version)) {
+ return false;
+ }
+
+ switch (static_cast<TransItem::Version>(version)) {
+ case TransItem::Version::V1: {
+ scoped_ptr<TransItemV1> item(new TransItemV1());
+ if (!DecodeTransItem(input, item.get())) {
+ return false;
+ }
+ output->Set(std::move(item));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool DecodeTransItem(base::StringPiece* input, TransItemV1* output) {
+ unsigned type;
+ if (!ReadUint(kTransTypeLength, input, &type)) {
+ return false;
+ }
+
+ switch (static_cast<TransType>(type)) {
+ case TransType::X509_SCT: {
+ scoped_refptr<SignedCertificateTimestamp> sct;
+ if (!DecodeSignedCertificateTimestamp(input, &sct)) {
+ return false;
+ }
+ output->SetX509Sct(sct);
+ return true;
+ }
+ case TransType::SIGNED_TREE_HEAD: {
+ SignedTreeHead sth;
+ if (!DecodeSignedTreeHead(input, &sth)) {
+ return false;
+ }
+ output->SetSignedTreeHead(sth);
+ return true;
+ }
+ case TransType::CONSISTENCY_PROOF: {
+ net::ct::MerkleConsistencyProof proof;
+ if (!DecodeConsistencyProof(input, &proof)) {
+ return false;
+ }
+ output->SetConsistencyProof(proof);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool EncodeTransItem(const TransItem& input, std::string* output) {
+ WriteUint(kTransItemVersionLength, static_cast<uint8_t>(input.version()),
+ output);
+
+ switch (input.version()) {
+ case TransItem::Version::V1:
+ return EncodeTransItem(input.v1(), output);
+ }
+
+ return false;
+}
+
+bool EncodeTransItem(const TransItemV1& input, std::string* output) {
+ WriteUint(kTransTypeLength, static_cast<uint8_t>(input.type()), output);
+
+ switch (input.type()) {
+ case TransType::X509_SCT:
+ return EncodeSignedCertificateTimestamp(*input.x509_sct(), output);
+ case TransType::SIGNED_TREE_HEAD:
+ return EncodeSignedTreeHead(input.signed_tree_head(), output);
+ case TransType::CONSISTENCY_PROOF:
+ return EncodeConsistencyProof(input.consistency_proof(), output);
+ }
+
+ return false;
+}
+
} // namespace ct
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698