1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
|
#ifndef CERT_TRANS_PROTO_SERIALIZER_H_
#define CERT_TRANS_PROTO_SERIALIZER_H_
#include <glog/logging.h>
#include <google/protobuf/repeated_field.h>
#include <stdint.h>
#include <functional>
#include <string>
#include "base/macros.h"
#include "proto/ct.pb.h"
#include "proto/tls_encoding.h"
typedef google::protobuf::RepeatedPtrField<ct::SthExtension>
repeated_sth_extension;
typedef google::protobuf::RepeatedPtrField<ct::SctExtension>
repeated_sct_extension;
cert_trans::serialization::SerializeResult CheckExtensionsFormat(
const std::string& extensions);
cert_trans::serialization::SerializeResult CheckKeyHashFormat(
const std::string& key_hash);
cert_trans::serialization::SerializeResult CheckSctExtensionsFormat(
const repeated_sct_extension& extension);
void WriteSctExtension(const repeated_sct_extension& extension,
std::string* output);
class TLSDeserializer {
public:
// We do not make a copy, so input must remain valid.
// TODO(pphaneuf): And so we should take a string *, not a string &
// (which could be to a temporary, and not valid once the
// constructor returns).
explicit TLSDeserializer(const std::string& input);
bool ReachedEnd() const {
return bytes_remaining_ == 0;
}
cert_trans::serialization::DeserializeResult ReadSCT(
ct::SignedCertificateTimestamp* sct);
cert_trans::serialization::DeserializeResult ReadList(
size_t max_total_length, size_t max_elem_length, repeated_string* out);
cert_trans::serialization::DeserializeResult ReadDigitallySigned(
ct::DigitallySigned* sig);
cert_trans::serialization::DeserializeResult ReadMerkleTreeLeaf(
ct::MerkleTreeLeaf* leaf);
bool ReadVarBytes(size_t max_length, std::string* result);
template <class T>
bool ReadUint(size_t bytes, T* result) {
if (bytes_remaining_ < bytes)
return false;
T res = 0;
for (size_t i = 0; i < bytes; ++i) {
res = (res << 8) | static_cast<unsigned char>(*current_pos_);
++current_pos_;
}
bytes_remaining_ -= bytes;
*result = res;
return true;
}
cert_trans::serialization::DeserializeResult ReadExtensions(
ct::TimestampedEntry* entry);
bool ReadFixedBytes(size_t bytes, std::string* result);
private:
static const size_t kV2ExtensionCountLengthInBytes;
static const size_t kV2ExtensionTypeLengthInBytes;
cert_trans::serialization::DeserializeResult ReadSctExtension(
repeated_sct_extension* extension);
cert_trans::serialization::DeserializeResult ReadMerkleTreeLeafV1(
ct::MerkleTreeLeaf* leaf);
cert_trans::serialization::DeserializeResult ReadMerkleTreeLeafV2(
ct::MerkleTreeLeaf* leaf);
cert_trans::serialization::DeserializeResult ReadSCTV1(
ct::SignedCertificateTimestamp* sct);
cert_trans::serialization::DeserializeResult ReadSCTV2(
ct::SignedCertificateTimestamp* sct);
bool ReadLengthPrefix(size_t max_length, size_t* result);
const char* current_pos_;
size_t bytes_remaining_;
DISALLOW_COPY_AND_ASSIGN(TLSDeserializer);
};
// A utility class for writing protocol buffer fields in canonical TLS style.
class Serializer {
public:
static const size_t kMaxV2ExtensionType;
static const size_t kMaxV2ExtensionsCount;
static const size_t kMaxExtensionsLength;
static const size_t kMaxSerializedSCTLength;
static const size_t kMaxSCTListLength;
static const size_t kLogEntryTypeLengthInBytes;
static const size_t kSignatureTypeLengthInBytes;
static const size_t kVersionLengthInBytes;
// Log Key ID
static const size_t kKeyIDLengthInBytes;
static const size_t kMerkleLeafTypeLengthInBytes;
// Public key hash from cert
static const size_t kKeyHashLengthInBytes;
static const size_t kTimestampLengthInBytes;
// API
// TODO(alcutter): typedef these function<> bits
static void ConfigureV1(
const std::function<std::string(const ct::LogEntry&)>& leaf_data,
const std::function<cert_trans::serialization::SerializeResult(
const ct::SignedCertificateTimestamp& sct, const ct::LogEntry& entry,
std::string* result)>& serialize_sct_sig_input,
const std::function<cert_trans::serialization::SerializeResult(
const ct::SignedCertificateTimestamp& sct, const ct::LogEntry& entry,
std::string* result)>& serialize_sct_merkle_leaf);
static void ConfigureV2(
const std::function<std::string(const ct::LogEntry&)>& leaf_data,
const std::function<cert_trans::serialization::SerializeResult(
const ct::SignedCertificateTimestamp& sct, const ct::LogEntry& entry,
std::string* result)>& serialize_sct_sig_input,
const std::function<cert_trans::serialization::SerializeResult(
const ct::SignedCertificateTimestamp& sct, const ct::LogEntry& entry,
std::string* result)>& serialize_sct_merkle_leaf);
static std::string LeafData(const ct::LogEntry& entry);
static cert_trans::serialization::SerializeResult SerializeSTHSignatureInput(
const ct::SignedTreeHead& sth, std::string* result);
static cert_trans::serialization::SerializeResult SerializeSCTMerkleTreeLeaf(
const ct::SignedCertificateTimestamp& sct, const ct::LogEntry& entry,
std::string* result);
static cert_trans::serialization::SerializeResult SerializeSCTSignatureInput(
const ct::SignedCertificateTimestamp& sct, const ct::LogEntry& entry,
std::string* result);
static cert_trans::serialization::SerializeResult
SerializeV1STHSignatureInput(uint64_t timestamp, int64_t tree_size,
const std::string& root_hash,
std::string* result);
static cert_trans::serialization::SerializeResult
SerializeV2STHSignatureInput(uint64_t timestamp, int64_t tree_size,
const std::string& root_hash,
const repeated_sth_extension& sth_extension,
const std::string& log_id, std::string* result);
// Random utils
static cert_trans::serialization::SerializeResult SerializeList(
const repeated_string& in, size_t max_elem_length,
size_t max_total_length, std::string* result);
static cert_trans::serialization::SerializeResult SerializeSCT(
const ct::SignedCertificateTimestamp& sct, std::string* result);
static cert_trans::serialization::SerializeResult SerializeSCTList(
const ct::SignedCertificateTimestampList& sct_list, std::string* result);
static cert_trans::serialization::SerializeResult SerializeDigitallySigned(
const ct::DigitallySigned& sig, std::string* result);
// TODO(ekasper): tests for these!
template <class T>
static std::string SerializeUint(T in, size_t bytes = sizeof(T)) {
std::string out;
cert_trans::serialization::WriteUint(in, bytes, &out);
return out;
}
private:
// This class is mostly a namespace for static methods.
// TODO(pphaneuf): Make this into normal functions in a namespace.
Serializer() = delete;
};
class Deserializer {
public:
static void Configure(
const std::function<cert_trans::serialization::DeserializeResult(
TLSDeserializer* d, ct::MerkleTreeLeaf* leaf)>&
read_merkle_tree_leaf_body);
static cert_trans::serialization::DeserializeResult DeserializeSCT(
const std::string& in, ct::SignedCertificateTimestamp* sct);
static cert_trans::serialization::DeserializeResult DeserializeSCTList(
const std::string& in, ct::SignedCertificateTimestampList* sct_list);
static cert_trans::serialization::DeserializeResult
DeserializeDigitallySigned(const std::string& in, ct::DigitallySigned* sig);
// FIXME(ekasper): for simplicity these reject if the list has empty
// elements (all our use cases are like this) but they should take in
// an arbitrary min bound instead.
static cert_trans::serialization::DeserializeResult DeserializeList(
const std::string& in, size_t max_total_length, size_t max_elem_length,
repeated_string* out);
static cert_trans::serialization::DeserializeResult
DeserializeMerkleTreeLeaf(const std::string& in, ct::MerkleTreeLeaf* leaf);
// TODO(pphaneuf): Maybe the users of this should just use
// TLSDeserializer directly?
template <class T>
static cert_trans::serialization::DeserializeResult DeserializeUint(
const std::string& in, size_t bytes, T* result) {
TLSDeserializer deserializer(in);
bool res = deserializer.ReadUint(bytes, result);
if (!res)
return cert_trans::serialization::DeserializeResult::INPUT_TOO_SHORT;
if (!deserializer.ReachedEnd())
return cert_trans::serialization::DeserializeResult::INPUT_TOO_LONG;
return cert_trans::serialization::DeserializeResult::OK;
}
private:
// This class is mostly a namespace for static methods.
// TODO(pphaneuf): Make this into normal functions in a namespace.
Deserializer() = delete;
// This should never do anything, but just in case...
DISALLOW_COPY_AND_ASSIGN(Deserializer);
};
#endif // CERT_TRANS_PROTO_SERIALIZER_H_
|