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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/ct_serialization.h" 5 #include "net/cert/ct_serialization.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_util.h"
14 #include "net/cert/merkle_consistency_proof.h"
12 15
13 namespace net { 16 namespace net {
14 17
15 namespace ct { 18 namespace ct {
16 19
17 namespace { 20 namespace {
18 21
19 // Note: length is always specified in bytes. 22 // Note: length is always specified in bytes.
20 // Signed Certificate Timestamp (SCT) Version length 23 // Signed Certificate Timestamp (SCT) Version length
21 const size_t kVersionLength = 1; 24 const size_t kVersionLength = 1;
(...skipping 11 matching lines...) Expand all
33 const size_t kLogEntryTypeLength = 2; 36 const size_t kLogEntryTypeLength = 2;
34 const size_t kAsn1CertificateLengthBytes = 3; 37 const size_t kAsn1CertificateLengthBytes = 3;
35 const size_t kTbsCertificateLengthBytes = 3; 38 const size_t kTbsCertificateLengthBytes = 3;
36 39
37 const size_t kSCTListLengthBytes = 2; 40 const size_t kSCTListLengthBytes = 2;
38 const size_t kSerializedSCTLengthBytes = 2; 41 const size_t kSerializedSCTLengthBytes = 2;
39 42
40 // Members of digitally-signed struct of a STH 43 // Members of digitally-signed struct of a STH
41 const size_t kTreeSizeLength = 8; 44 const size_t kTreeSizeLength = 8;
42 45
46 // Members of a V1 Consistency Proof
47 const size_t kSha256HashLength = 32;
48 const size_t kConsistencyPathLengthBytes = 8;
49
50 // Length of the version field in a TransItem struct
51 const size_t kTransItemVersionLength = 1;
52
53 // Length of the type field in a TransItem{V1,V2} struct
54 const size_t kTransTypeLength = 1;
55
43 enum SignatureType { 56 enum SignatureType {
44 SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP = 0, 57 SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP = 0,
45 TREE_HASH = 1, 58 TREE_HASH = 1,
46 }; 59 };
47 60
48 // Reads a TLS-encoded variable length unsigned integer from |in|. 61 // Reads a TLS-encoded variable length unsigned integer from |in|.
49 // The integer is expected to be in big-endian order, which is used by TLS. 62 // The integer is expected to be in big-endian order, which is used by TLS.
50 // The bytes read from |in| are discarded (i.e. |in|'s prefix removed) 63 // The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
51 // |length| indicates the size (in bytes) of the integer. On success, returns 64 // |length| indicates the size (in bytes) of the integer. On success, returns
52 // true and stores the result in |*out|. 65 // true and stores the result in |*out|.
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 output); 318 output);
306 WriteUint(kSignatureTypeLength, SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP, 319 WriteUint(kSignatureTypeLength, SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP,
307 output); 320 output);
308 WriteTimeSinceEpoch(timestamp, output); 321 WriteTimeSinceEpoch(timestamp, output);
309 // NOTE: serialized_log_entry must already be serialized and contain the 322 // NOTE: serialized_log_entry must already be serialized and contain the
310 // length as the prefix. 323 // length as the prefix.
311 WriteEncodedBytes(serialized_log_entry, output); 324 WriteEncodedBytes(serialized_log_entry, output);
312 return WriteVariableBytes(kExtensionsLengthBytes, extensions, output); 325 return WriteVariableBytes(kExtensionsLengthBytes, extensions, output);
313 } 326 }
314 327
328 // TODO(robpercival): This could probably be named better, since the one thing
329 // this doesn't encode is the signature. Perhaps just EncodeTreeHead, or
330 // EncodeTreeHeadForSignature?
315 void EncodeTreeHeadSignature(const SignedTreeHead& signed_tree_head, 331 void EncodeTreeHeadSignature(const SignedTreeHead& signed_tree_head,
316 std::string* output) { 332 std::string* output) {
317 WriteUint(kVersionLength, signed_tree_head.version, output); 333 WriteUint(kVersionLength, signed_tree_head.version, output);
318 WriteUint(kSignatureTypeLength, TREE_HASH, output); 334 WriteUint(kSignatureTypeLength, TREE_HASH, output);
319 WriteTimeSinceEpoch(signed_tree_head.timestamp, output); 335 WriteTimeSinceEpoch(signed_tree_head.timestamp, output);
320 WriteUint(kTreeSizeLength, signed_tree_head.tree_size, output); 336 WriteUint(kTreeSizeLength, signed_tree_head.tree_size, output);
321 WriteEncodedBytes( 337 WriteEncodedBytes(
322 base::StringPiece(signed_tree_head.sha256_root_hash, kSthRootHashLength), 338 base::StringPiece(signed_tree_head.sha256_root_hash, kSthRootHashLength),
323 output); 339 output);
324 } 340 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 log_id.CopyToString(&result->log_id); 386 log_id.CopyToString(&result->log_id);
371 extensions.CopyToString(&result->extensions); 387 extensions.CopyToString(&result->extensions);
372 result->timestamp = 388 result->timestamp =
373 base::Time::UnixEpoch() + 389 base::Time::UnixEpoch() +
374 base::TimeDelta::FromMilliseconds(static_cast<int64_t>(timestamp)); 390 base::TimeDelta::FromMilliseconds(static_cast<int64_t>(timestamp));
375 391
376 output->swap(result); 392 output->swap(result);
377 return true; 393 return true;
378 } 394 }
379 395
396 bool EncodeSignedCertificateTimestamp(const SignedCertificateTimestamp& input,
397 std::string* output) {
398 WriteUint(kVersionLength, input.version, output);
399 DCHECK_EQ(kLogIdLength, WriteEncodedBytes(input.log_id, output));
400 WriteTimeSinceEpoch(input.timestamp, output);
401
402 if (!WriteVariableBytes(kExtensionsLengthBytes, input.extensions, output) ||
403 !EncodeDigitallySigned(input.signature, output)) {
404 return false;
405 }
406
407 return true;
408 }
409
380 bool EncodeSCTListForTesting(const base::StringPiece& sct, 410 bool EncodeSCTListForTesting(const base::StringPiece& sct,
381 std::string* output) { 411 std::string* output) {
382 std::string encoded_sct; 412 std::string encoded_sct;
383 return WriteVariableBytes(kSerializedSCTLengthBytes, sct, &encoded_sct) && 413 return WriteVariableBytes(kSerializedSCTLengthBytes, sct, &encoded_sct) &&
384 WriteVariableBytes(kSCTListLengthBytes, encoded_sct, output); 414 WriteVariableBytes(kSCTListLengthBytes, encoded_sct, output);
385 } 415 }
386 416
417 bool DecodeSignedTreeHead(base::StringPiece* input, SignedTreeHead* output) {
418 base::StringPiece log_id;
419 base::StringPiece sha256_root_hash;
420 if (!ReadFixedBytes(kLogIdLength, input, &log_id) ||
421 !ReadTimeSinceEpoch(input, &output->timestamp) ||
422 !ReadUint(kTreeSizeLength, input, &output->tree_size) ||
423 !ReadFixedBytes(kSthRootHashLength, input, &sha256_root_hash)) {
424 return false;
425 }
426
427 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
428 log_id.copy(output->sha256_root_hash, kSthRootHashLength);
429 return true;
430 }
431
432 bool EncodeSignedTreeHead(const SignedTreeHead& input, std::string* output) {
433 DCHECK_EQ(kLogIdLength, WriteEncodedBytes(input.log_id, output));
434 WriteTimeSinceEpoch(input.timestamp, output);
435 WriteUint(kTreeSizeLength, input.tree_size, output);
436
437 base::StringPiece root_hash(input.sha256_root_hash, kSthRootHashLength);
438 WriteEncodedBytes(root_hash, output);
439
440 if (!EncodeDigitallySigned(input.signature, output)) {
441 return false;
442 }
443
444 return true;
445 }
446
447 bool DecodeConsistencyProof(base::StringPiece* input,
448 MerkleConsistencyProof* output) {
449 base::StringPiece log_id;
450 if (!ReadFixedBytes(kLogIdLength, input, &log_id)) {
451 return false;
452 }
453 log_id.CopyToString(&output->log_id);
454
455 if (!ReadUint(kTreeSizeLength, input, &output->first_tree_size)) {
456 return false;
457 }
458
459 if (!ReadUint(kTreeSizeLength, input, &output->second_tree_size)) {
460 return false;
461 }
462
463 base::StringPiece consistency_path;
464 if (!ReadVariableBytes(kConsistencyPathLengthBytes, input,
465 &consistency_path)) {
466 return false;
467 }
468
469 for (size_t i = 0; i < consistency_path.size() / kSha256HashLength; ++i) {
470 base::StringPiece node_hash =
471 consistency_path.substr(kSha256HashLength * i, kSha256HashLength);
472
473 output->nodes.push_back(node_hash.as_string());
474 }
475
476 return true;
477 }
478
479 bool EncodeConsistencyProof(const MerkleConsistencyProof& input,
480 std::string* output) {
481 WriteEncodedBytes(input.log_id, output);
482 WriteUint(kTreeSizeLength, input.first_tree_size, output);
483 WriteUint(kTreeSizeLength, input.second_tree_size, output);
484
485 std::string consistency_path = base::JoinString(input.nodes, "");
486 if (!WriteVariableBytes(kConsistencyPathLengthBytes, consistency_path,
487 output)) {
488 return false;
489 }
490
491 return true;
492 }
493
494 bool DecodeTransItem(base::StringPiece* input, TransItem* output) {
495 unsigned version;
496 if (!ReadUint(kTransItemVersionLength, input, &version)) {
497 return false;
498 }
499
500 switch (static_cast<TransItem::Version>(version)) {
501 case TransItem::Version::V1: {
502 scoped_ptr<TransItemV1> item(new TransItemV1());
503 if (!DecodeTransItem(input, item.get())) {
504 return false;
505 }
506 output->Set(std::move(item));
507 return true;
508 }
509 }
510
511 return false;
512 }
513
514 bool DecodeTransItem(base::StringPiece* input, TransItemV1* output) {
515 unsigned type;
516 if (!ReadUint(kTransTypeLength, input, &type)) {
517 return false;
518 }
519
520 switch (static_cast<TransType>(type)) {
521 case TransType::X509_SCT: {
522 scoped_refptr<SignedCertificateTimestamp> sct;
523 if (!DecodeSignedCertificateTimestamp(input, &sct)) {
524 return false;
525 }
526 output->SetX509Sct(sct);
527 return true;
528 }
529 case TransType::SIGNED_TREE_HEAD: {
530 SignedTreeHead sth;
531 if (!DecodeSignedTreeHead(input, &sth)) {
532 return false;
533 }
534 output->SetSignedTreeHead(sth);
535 return true;
536 }
537 case TransType::CONSISTENCY_PROOF: {
538 net::ct::MerkleConsistencyProof proof;
539 if (!DecodeConsistencyProof(input, &proof)) {
540 return false;
541 }
542 output->SetConsistencyProof(proof);
543 return true;
544 }
545 }
546
547 return false;
548 }
549
550 bool EncodeTransItem(const TransItem& input, std::string* output) {
551 WriteUint(kTransItemVersionLength, static_cast<uint8_t>(input.version()),
552 output);
553
554 switch (input.version()) {
555 case TransItem::Version::V1:
556 return EncodeTransItem(input.v1(), output);
557 }
558
559 return false;
560 }
561
562 bool EncodeTransItem(const TransItemV1& input, std::string* output) {
563 WriteUint(kTransTypeLength, static_cast<uint8_t>(input.type()), output);
564
565 switch (input.type()) {
566 case TransType::X509_SCT:
567 return EncodeSignedCertificateTimestamp(*input.x509_sct(), output);
568 case TransType::SIGNED_TREE_HEAD:
569 return EncodeSignedTreeHead(input.signed_tree_head(), output);
570 case TransType::CONSISTENCY_PROOF:
571 return EncodeConsistencyProof(input.consistency_proof(), output);
572 }
573
574 return false;
575 }
576
387 } // namespace ct 577 } // namespace ct
388 578
389 } // namespace net 579 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698