Add MTC draft plants-07 support (for pki/). Bug: 452986180 Change-Id: Ibb4ada5b22ff2f58eda58819d5301a1067474c97 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/103827 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: Matt Mueller <mattm@google.com>
diff --git a/gen/sources.bzl b/gen/sources.bzl index e8139a7..a9710a0 100644 --- a/gen/sources.bzl +++ b/gen/sources.bzl
@@ -2370,6 +2370,14 @@ "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone-no_ca_signer.pem", "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone.pem", "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem", "pki/testdata/path_builder_unittest/multi-root-A-by-B.pem", "pki/testdata/path_builder_unittest/multi-root-B-by-C.pem", "pki/testdata/path_builder_unittest/multi-root-B-by-F.pem",
diff --git a/gen/sources.cmake b/gen/sources.cmake index a860125..0d23dbf 100644 --- a/gen/sources.cmake +++ b/gen/sources.cmake
@@ -2428,6 +2428,14 @@ pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone-no_ca_signer.pem pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone.pem pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf.pem + pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem pki/testdata/path_builder_unittest/multi-root-A-by-B.pem pki/testdata/path_builder_unittest/multi-root-B-by-C.pem pki/testdata/path_builder_unittest/multi-root-B-by-F.pem
diff --git a/gen/sources.gni b/gen/sources.gni index 4116102..fddc5fd 100644 --- a/gen/sources.gni +++ b/gen/sources.gni
@@ -2370,6 +2370,14 @@ "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone-no_ca_signer.pem", "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone.pem", "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem", "pki/testdata/path_builder_unittest/multi-root-A-by-B.pem", "pki/testdata/path_builder_unittest/multi-root-B-by-C.pem", "pki/testdata/path_builder_unittest/multi-root-B-by-F.pem",
diff --git a/gen/sources.json b/gen/sources.json index 8c909de..04ee3b7 100644 --- a/gen/sources.json +++ b/gen/sources.json
@@ -2350,6 +2350,14 @@ "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone-no_ca_signer.pem", "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone.pem", "pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem", + "pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem", "pki/testdata/path_builder_unittest/multi-root-A-by-B.pem", "pki/testdata/path_builder_unittest/multi-root-B-by-C.pem", "pki/testdata/path_builder_unittest/multi-root-B-by-F.pem",
diff --git a/gen/sources.mk b/gen/sources.mk index 742a62b..e5bd510 100644 --- a/gen/sources.mk +++ b/gen/sources.mk
@@ -2342,6 +2342,14 @@ pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone-no_ca_signer.pem \ pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf-standalone.pem \ pki/testdata/path_builder_unittest/mtc_plants04/mtc-leaf.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem \ + pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem \ pki/testdata/path_builder_unittest/multi-root-A-by-B.pem \ pki/testdata/path_builder_unittest/multi-root-B-by-C.pem \ pki/testdata/path_builder_unittest/multi-root-B-by-F.pem \
diff --git a/pki/path_builder_unittest.cc b/pki/path_builder_unittest.cc index 6a3a9f9..536faec 100644 --- a/pki/path_builder_unittest.cc +++ b/pki/path_builder_unittest.cc
@@ -2523,18 +2523,65 @@ std::map<std::vector<uint8_t>, MTCCosigner> cosigners_; }; -class PathBuilderMTCPlants04Test : public PathBuilderSimpleChainTest { +class PathBuilderMTCTest + : public PathBuilderSimpleChainTest, + public ::testing::WithParamInterface<MTCAnchor::MtcSpecVersion> { public: - PathBuilderMTCPlants04Test() = default; + PathBuilderMTCTest() = default; protected: + MTCAnchor::MtcSpecVersion spec_version() const { return GetParam(); } + + std::string TestDataDir() const { + switch (spec_version()) { + case MTCAnchor::kPlants04: + return "mtc_plants04/"; + case MTCAnchor::kPlants07: + return "mtc_plants07/"; + } + abort(); + } + + std::string_view ExpectedSubtreeHashBase64() const { + switch (spec_version()) { + case MTCAnchor::kPlants04: + return "ir6iVcgTrbuHdXB3lKGny6VKSlE1OB5Q+LrtdFH+qIE="; + case MTCAnchor::kPlants07: + return "K/o/0tKQMz/Qdk+F3U9ViXjhYBCgb675l9vH7atcQxQ="; + } + abort(); + } + + std::shared_ptr<const MTCAnchor> CreateMTCAnchor( + Span<const uint8_t> ca_id, SignatureAlgorithm ca_signature_algorithm, + UniquePtr<CRYPTO_BUFFER> ca_key, + std::vector<LogTrustedSubtrees> log_trusted_subtrees) const { + switch (spec_version()) { + case MTCAnchor::kPlants04: + return std::make_shared<MTCAnchor>(ca_id, ca_signature_algorithm, + std::move(ca_key), + std::move(log_trusted_subtrees)); + case MTCAnchor::kPlants07: + return MTCAnchor::CreatePlants07(ca_id, ca_signature_algorithm, + std::move(ca_key), + std::move(log_trusted_subtrees)); + } + abort(); + } + + ::testing::AssertionResult ReadMTCTestCert( + const std::string &file_name, + std::shared_ptr<const ParsedCertificate> *result) const { + return ReadTestCert(TestDataDir() + file_name, result); + } + void SetUp() override { PathBuilderSimpleChainTest::SetUp(); // Set up the MTCAnchor. std::string subtree_hash; - ASSERT_TRUE(string_util::Base64Decode( - "ir6iVcgTrbuHdXB3lKGny6VKSlE1OB5Q+LrtdFH+qIE=", &subtree_hash)); + ASSERT_TRUE( + string_util::Base64Decode(ExpectedSubtreeHashBase64(), &subtree_hash)); TrustedSubtree subtree; ASSERT_EQ(subtree_hash.size(), subtree.hash.size()); memcpy(subtree.hash.data(), subtree_hash.data(), subtree_hash.size()); @@ -2564,29 +2611,33 @@ ExportPublicKeyFromSeed(kCaPrivateKeySeed2); ASSERT_TRUE(spki2); - mtc_anchor_ = std::make_shared<MTCAnchor>( - MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, UpRef(spki), subtrees); - ASSERT_EQ(mtc_anchor_->spec_version(), MTCAnchor::kPlants04); + mtc_anchor_ = CreateMTCAnchor(MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, + UpRef(spki), subtrees); + ASSERT_TRUE(mtc_anchor_); + ASSERT_EQ(mtc_anchor_->spec_version(), spec_version()); - mtc_anchor_wrong_key_ = std::make_shared<MTCAnchor>( + mtc_anchor_wrong_key_ = CreateMTCAnchor( MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, UpRef(spki2), subtrees); - ASSERT_EQ(mtc_anchor_wrong_key_->spec_version(), MTCAnchor::kPlants04); + ASSERT_TRUE(mtc_anchor_wrong_key_); + ASSERT_EQ(mtc_anchor_wrong_key_->spec_version(), spec_version()); - mtc_anchor_wrong_subtree_hash_ = std::make_shared<MTCAnchor>( + mtc_anchor_wrong_subtree_hash_ = CreateMTCAnchor( MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, UpRef(spki), subtrees2); - ASSERT_EQ(mtc_anchor_wrong_subtree_hash_->spec_version(), - MTCAnchor::kPlants04); + ASSERT_TRUE(mtc_anchor_wrong_subtree_hash_); + ASSERT_EQ(mtc_anchor_wrong_subtree_hash_->spec_version(), spec_version()); - mtc_anchor_no_subtrees_ = std::make_shared<MTCAnchor>( - MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, UpRef(spki), - std::vector<LogTrustedSubtrees>()); - ASSERT_EQ(mtc_anchor_no_subtrees_->spec_version(), MTCAnchor::kPlants04); + mtc_anchor_no_subtrees_ = + CreateMTCAnchor(MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, + UpRef(spki), std::vector<LogTrustedSubtrees>()); + ASSERT_TRUE(mtc_anchor_no_subtrees_); + ASSERT_EQ(mtc_anchor_no_subtrees_->spec_version(), spec_version()); - mtc_anchor_no_subtrees_wrong_key_ = std::make_shared<MTCAnchor>( - MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, UpRef(spki2), - std::vector<LogTrustedSubtrees>()); + mtc_anchor_no_subtrees_wrong_key_ = + CreateMTCAnchor(MakeSpan(kCaId), SignatureAlgorithm::kMldsa44, + UpRef(spki2), std::vector<LogTrustedSubtrees>()); + ASSERT_TRUE(mtc_anchor_no_subtrees_wrong_key_); ASSERT_EQ(mtc_anchor_no_subtrees_wrong_key_->spec_version(), - MTCAnchor::kPlants04); + spec_version()); } CertPathBuilder::Result RunPathBuilder( @@ -2610,19 +2661,31 @@ return path_builder.Run(); } - std::shared_ptr<MTCAnchor> mtc_anchor_; - std::shared_ptr<MTCAnchor> mtc_anchor_wrong_key_; - std::shared_ptr<MTCAnchor> mtc_anchor_wrong_subtree_hash_; - std::shared_ptr<MTCAnchor> mtc_anchor_no_subtrees_; - std::shared_ptr<MTCAnchor> mtc_anchor_no_subtrees_wrong_key_; + std::shared_ptr<const MTCAnchor> mtc_anchor_; + std::shared_ptr<const MTCAnchor> mtc_anchor_wrong_key_; + std::shared_ptr<const MTCAnchor> mtc_anchor_wrong_subtree_hash_; + std::shared_ptr<const MTCAnchor> mtc_anchor_no_subtrees_; + std::shared_ptr<const MTCAnchor> mtc_anchor_no_subtrees_wrong_key_; }; -TEST_F(PathBuilderMTCPlants04Test, Verification) { +INSTANTIATE_TEST_SUITE_P( + All, PathBuilderMTCTest, + ::testing::Values(MTCAnchor::kPlants04, MTCAnchor::kPlants07), + [](const testing::TestParamInfo<MTCAnchor::MtcSpecVersion> ¶m_info) { + switch (param_info.param) { + case MTCAnchor::kPlants04: + return "Plants04"; + case MTCAnchor::kPlants07: + return "Plants07"; + } + abort(); + }); + +TEST_P(PathBuilderMTCTest, Verification) { std::shared_ptr<const ParsedCertificate> signatureless_leaf; - ASSERT_TRUE(ReadTestCert("mtc_plants04/mtc-leaf.pem", &signatureless_leaf)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf.pem", &signatureless_leaf)); std::shared_ptr<const ParsedCertificate> standalone_leaf; - ASSERT_TRUE( - ReadTestCert("mtc_plants04/mtc-leaf-standalone.pem", &standalone_leaf)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf-standalone.pem", &standalone_leaf)); TrustStoreInMemory trust_store_with_subtrees; ASSERT_TRUE(trust_store_with_subtrees.AddMTCTrustAnchor(mtc_anchor_)); @@ -2716,8 +2779,8 @@ // Cert with multiple cosigners (including valid CA cosigner) should validate // successfully, ignoring the unknown cosigners. std::shared_ptr<const ParsedCertificate> standalone_leaf_3_cosigners; - ASSERT_TRUE(ReadTestCert("mtc_plants04/mtc-leaf-standalone-3cosigners.pem", - &standalone_leaf_3_cosigners)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf-standalone-3cosigners.pem", + &standalone_leaf_3_cosigners)); result = RunPathBuilder(standalone_leaf_3_cosigners, &trust_store_no_subtrees, nullptr, &no_cosigners_delegate); EXPECT_TRUE(result.HasValidPath()); @@ -2733,8 +2796,8 @@ // Cert with a cosigner but no CA cosigner should fail: std::shared_ptr<const ParsedCertificate> standalone_leaf_no_ca_signer; - ASSERT_TRUE(ReadTestCert("mtc_plants04/mtc-leaf-standalone-no_ca_signer.pem", - &standalone_leaf_no_ca_signer)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf-standalone-no_ca_signer.pem", + &standalone_leaf_no_ca_signer)); result = RunPathBuilder(standalone_leaf_no_ca_signer, &trust_store_no_subtrees, nullptr, &no_cosigners_delegate); @@ -2745,9 +2808,8 @@ // Cert with a duplicate CA cosigner should fail: std::shared_ptr<const ParsedCertificate> standalone_leaf_duplicate_ca_signer; - ASSERT_TRUE( - ReadTestCert("mtc_plants04/mtc-leaf-standalone-duplicate_ca_signer.pem", - &standalone_leaf_duplicate_ca_signer)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf-standalone-duplicate_ca_signer.pem", + &standalone_leaf_duplicate_ca_signer)); result = RunPathBuilder(standalone_leaf_duplicate_ca_signer, &trust_store_no_subtrees, nullptr, &no_cosigners_delegate); @@ -2758,9 +2820,8 @@ // Cert with a cosigners in non-sorted order should fail: std::shared_ptr<const ParsedCertificate> standalone_leaf_cosigner_wrong_order; - ASSERT_TRUE( - ReadTestCert("mtc_plants04/mtc-leaf-standalone-cosigner_wrong_order.pem", - &standalone_leaf_cosigner_wrong_order)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf-standalone-cosigner_wrong_order.pem", + &standalone_leaf_cosigner_wrong_order)); result = RunPathBuilder(standalone_leaf_cosigner_wrong_order, &trust_store_no_subtrees, nullptr, &no_cosigners_delegate); @@ -2770,7 +2831,7 @@ cert_errors::kVerifySignedDataFailed)); } -TEST_F(PathBuilderMTCPlants04Test, CosignatureVerification) { +TEST_P(PathBuilderMTCTest, CosignatureVerification) { static constexpr uint8_t kCosignerId1[] = {0x81, 0xfd, 0x59, 0x00}; static constexpr uint8_t kCosignerPrivateKeySeed1[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, @@ -2795,8 +2856,8 @@ mtc_anchor_no_subtrees_wrong_key_)); std::shared_ptr<const ParsedCertificate> standalone_leaf_3_cosigners; - ASSERT_TRUE(ReadTestCert("mtc_plants04/mtc-leaf-standalone-3cosigners.pem", - &standalone_leaf_3_cosigners)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf-standalone-3cosigners.pem", + &standalone_leaf_3_cosigners)); CertPathBuilder::Result result; { @@ -2861,10 +2922,9 @@ // If the CA key is correct but the cosigners fail to validate, it should // be called with empty valid cosigners list: - EXPECT_CALL( - wrong_cosigner_keys_delegate, - IsCosignatureVerificationResultAcceptable( - mtc_anchor_no_subtrees_.get(), ElementsAre())) + EXPECT_CALL(wrong_cosigner_keys_delegate, + IsCosignatureVerificationResultAcceptable( + mtc_anchor_no_subtrees_.get(), ElementsAre())) .WillOnce(Return(true)); result = RunPathBuilder(standalone_leaf_3_cosigners, &trust_store_no_subtrees, @@ -2889,8 +2949,7 @@ // list: EXPECT_CALL(wrong_ca1_cosigner_key_delegate, IsCosignatureVerificationResultAcceptable( - mtc_anchor_no_subtrees_.get(), - ElementsAre(cosigner_id_2))) + mtc_anchor_no_subtrees_.get(), ElementsAre(cosigner_id_2))) .WillOnce(Return(true)); result = RunPathBuilder(standalone_leaf_3_cosigners, &trust_store_no_subtrees, @@ -2927,10 +2986,10 @@ } } -TEST_F(PathBuilderMTCPlants04Test, CheckPathAfterVerification) { +TEST_P(PathBuilderMTCTest, CheckPathAfterVerification) { // Set up MTC leaf and its trust anchor. std::shared_ptr<const ParsedCertificate> mtc_leaf; - ASSERT_TRUE(ReadTestCert("mtc_plants04/mtc-leaf.pem", &mtc_leaf)); + ASSERT_TRUE(ReadMTCTestCert("mtc-leaf.pem", &mtc_leaf)); TrustStoreInMemory in_memory; ASSERT_TRUE(in_memory.AddMTCTrustAnchor(mtc_anchor_)); @@ -2961,11 +3020,11 @@ << error.DiagnosticString(); } -TEST_F(PathBuilderMTCPlants04Test, PathLength) { +TEST_P(PathBuilderMTCTest, PathLength) { std::shared_ptr<const ParsedCertificate> leaf; - ASSERT_TRUE(ReadTestCert("mtc_plants04/leaf.pem", &leaf)); + ASSERT_TRUE(ReadMTCTestCert("leaf.pem", &leaf)); std::shared_ptr<const ParsedCertificate> ica; - ASSERT_TRUE(ReadTestCert("mtc_plants04/mtc-ica.pem", &ica)); + ASSERT_TRUE(ReadMTCTestCert("mtc-ica.pem", &ica)); // Test that verifying leaf succeeds using ica as the trusted root. {
diff --git a/pki/signature_algorithm.cc b/pki/signature_algorithm.cc index 0c39013..89db338 100644 --- a/pki/signature_algorithm.cc +++ b/pki/signature_algorithm.cc
@@ -157,6 +157,14 @@ // In dotted notation: 2.16.840.1.101.3.4.3.19 const uint8_t kOidAlgMldsa87[] = {OBJ_ENC_ML_DSA_87}; +// From draft-ietf-plants-merkle-tree-certs-07: +// +// id-alg-mtcProof OBJECT IDENTIFIER ::= { +// iso(1) identified-organization(3) dod(6) internet(1) security(5) +// mechanisms(5) pkix(7) algorithms(6) 67 } +const uint8_t kOidAlgMtcProof[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, + 0x43}; + // From draft-ietf-plants-merkle-tree-certs-04: // // id-alg-mtcProof OBJECT IDENTIFIER ::= { @@ -439,6 +447,9 @@ return ParseRsaPss(params); } + if (oid == der::Input(kOidAlgMtcProof) && params.empty()) { + return SignatureAlgorithm::kMtcProof; + } if (oid == der::Input(kOidAlgMtcProofDraftPlants04) && params.empty()) { return SignatureAlgorithm::kMtcProofDraftPlants04; } @@ -485,6 +496,7 @@ // RFC 5929 (nor other references) does not define digests to use for these // signature algorithms: case SignatureAlgorithm::kMtcProofDraftPlants04: + case SignatureAlgorithm::kMtcProof: case SignatureAlgorithm::kMldsa44: case SignatureAlgorithm::kMldsa65: case SignatureAlgorithm::kMldsa87:
diff --git a/pki/signature_algorithm.h b/pki/signature_algorithm.h index 7069237..5059dcd 100644 --- a/pki/signature_algorithm.h +++ b/pki/signature_algorithm.h
@@ -56,6 +56,7 @@ kRsaPssSha384, kRsaPssSha512, kMtcProofDraftPlants04, + kMtcProof, kMldsa44, kMldsa65, kMldsa87,
diff --git a/pki/simple_path_builder_delegate.cc b/pki/simple_path_builder_delegate.cc index dc572a6..2a96ab0 100644 --- a/pki/simple_path_builder_delegate.cc +++ b/pki/simple_path_builder_delegate.cc
@@ -102,6 +102,7 @@ case SignatureAlgorithm::kRsaPssSha384: case SignatureAlgorithm::kRsaPssSha512: case SignatureAlgorithm::kMtcProofDraftPlants04: + case SignatureAlgorithm::kMtcProof: case SignatureAlgorithm::kMldsa44: case SignatureAlgorithm::kMldsa65: case SignatureAlgorithm::kMldsa87:
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/README.md b/pki/testdata/path_builder_unittest/mtc_plants07/README.md new file mode 100644 index 0000000..a9f8028 --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/README.md
@@ -0,0 +1,40 @@ +# MTC test certs + +This directory contains the following certs: + +- `mtc-leaf.pem` + - signatureless MTC issued by an MTC CA +- `mtc-leaf-standalone.pem` + - standalone MTC issued by an MTC CA +- `mtc-leaf-standalone-3cosigners.pem` + - standalone MTC containing the CA cosignature and two other cosignatures. +- `mtc-leaf-standalone-no_ca_signer.pem` + - MTC containing one cosignature, but no CA cosignature. +- `mtc-leaf-standalone-duplicate_ca_signer.pem` + - standalone MTC containing two duplicate CA cosignatures. +- `mtc-leaf-standalone-cosigner_wrong_order.pem` + - standalone MTC containing the CA cosignature and another cosignature, but + the cosignatures are not in sorted order. +- `mtc-ica.pem` + - signatureless MTC issued by the same MTC CA + - its BasicConstraints has `cA=TRUE` +- `leaf.pem` + - classical ECDSA cert (SPKI) with ECDSA `signatureAlgorithm` + - issued by `mtc-ica.pem` + +## (Re)generating test certs + +Generating these certs is done in two steps. + +The first step is to generate a keypair for the ICA and use the private key to +sign the leaf cert: + +1. Run `go run generate_leaf.go` +2. Copy the certificate PEM to `leaf.pem` +3. Copy the ICA SPKI base64 to the first `PublicKey` entry in `mtc-config.json` + +The next step is to generate the MTCs: + +1. Run `generate_mtcs.sh` +2. Copy the subtree range and hash from the script output into +PathBuilderMTCPlants07Test::SetUp.
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/generate_leaf.go b/pki/testdata/path_builder_unittest/mtc_plants07/generate_leaf.go new file mode 100644 index 0000000..b63e467 --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/generate_leaf.go
@@ -0,0 +1,73 @@ +package main + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "encoding/pem" + "fmt" + "math/big" + "os" + "time" +) + +func do() error { + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return err + } + leafKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return err + } + icaTempl := &x509.Certificate{ + Subject: pkix.Name{CommonName: "ICA 1"}, + IsCA: true, + SerialNumber: big.NewInt(1), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + NotBefore: time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC), + NotAfter: time.Date(2030, time.December, 31, 23, 59, 59, 0, time.UTC), + } + ica, err := x509.CreateCertificate(rand.Reader, icaTempl, icaTempl, key.Public(), key) + if err != nil { + return err + } + icaCert, err := x509.ParseCertificate(ica) + if err != nil { + return err + } + + leafTempl := &x509.Certificate{ + Subject: pkix.Name{CommonName: "Leaf 1"}, + SerialNumber: big.NewInt(1), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + NotBefore: time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC), + NotAfter: time.Date(2030, time.December, 31, 23, 59, 59, 0, time.UTC), + DNSNames: []string{"example.com"}, + } + + cert, err := x509.CreateCertificate(rand.Reader, leafTempl, icaTempl, leafKey.Public(), key) + if err != nil { + return err + } + + pemBlock := &pem.Block{Type: "CERTIFICATE", Bytes: cert} + pem.Encode(os.Stdout, pemBlock) + ica_spki := base64.StdEncoding.EncodeToString(icaCert.RawSubjectPublicKeyInfo) + fmt.Printf("ICA SPKI: %s\n", ica_spki) + return nil +} + +func main() { + if err := do(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v", err) + os.Exit(1) + } +}
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/generate_mtcs.sh b/pki/testdata/path_builder_unittest/mtc_plants07/generate_mtcs.sh new file mode 100755 index 0000000..ab0279d --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/generate_mtcs.sh
@@ -0,0 +1,17 @@ +#!/bin/bash + +set -e -x + +mkdir out + +go run github.com/ietf-plants-wg/merkle-tree-certs/demo@bfb754ff821153176667a9b9a06f08703f134728 generate -config=mtc-config.json -out=out + +mv -v out/cert_0_0.pem mtc-ica.pem +mv -v out/cert_1_0.pem mtc-leaf.pem +mv -v out/cert_1_1.pem mtc-leaf-standalone.pem +mv -v out/cert_1_2.pem mtc-leaf-standalone-3cosigners.pem +mv -v out/cert_1_3.pem mtc-leaf-standalone-no_ca_signer.pem +mv -v out/cert_1_4.pem mtc-leaf-standalone-duplicate_ca_signer.pem +mv -v out/cert_1_5.pem mtc-leaf-standalone-cosigner_wrong_order.pem +rm -r out +
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem b/pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem new file mode 100644 index 0000000..ebbd09f --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/leaf.pem
@@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBXDCCAQOgAwIBAgIBATAKBggqhkjOPQQDAjAQMQ4wDAYDVQQDEwVJQ0EgMTAe +Fw0yMDAxMDEwMDAwMDBaFw0zMDEyMzEyMzU5NTlaMBExDzANBgNVBAMTBkxlYWYg +MTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHhYrp7qxXYTNqUCG36ka6f7GCgR +fKd0j7dnYU5oDXmFFfzML2c072nZWLCN3touQ8rqWYEvzu0q5FchiXPTi22jTTBL +MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8E +AjAAMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMAoGCCqGSM49BAMCA0cAMEQCIFLN +Ah9IrTtUwJuH6NbthNNE3+SxbZLl0wz7PiBgqvmZAiAO/aT4xctesdxvFGC24s2+ +ewkyTiCBiq2bej/yub5bog== +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-config.json b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-config.json new file mode 100644 index 0000000..2be9e85 --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-config.json
@@ -0,0 +1,98 @@ +{ + "Version": "plants-07", + "ID": "32473.1", + "LogNumber": 1, + "Cosigners": [ + { + "CosignerID": "32473.0", + "SignatureAlgorithm": "mldsa44", + "PrivateKey": "MDQCAQAwCwYJYIZIAWUDBAMRBCKAIKqqqqqqqqqqqqqqqqqqqqqqoRERERERERERERERERER" + }, + { + "CosignerID": "32473.1", + "SignatureAlgorithm": "mldsa44", + "PrivateKey": "MDQCAQAwCwYJYIZIAWUDBAMRBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4f" + }, + { + "CosignerID": "32473.2", + "SignatureAlgorithm": "mldsa44", + "PrivateKey": "MDQCAQAwCwYJYIZIAWUDBAMRBCKAIKqqqqqqqqqqqqqqqqqqqqoiIiIiIiIiIiIiIiIiIiIi" + } + ], + "Entries": [ + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyXLJquJMGPkBDu854pXQbva4Gqn48F6tH5GW9NQpNJCAzCveJVZpSrriRUt6ira3Nags4ZYniXDDa7VkvaMflA==", + "Subject": { + "CommonName": "ICA 1" + }, + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "ExtKeyUsage": ["ServerAuth"], + "KeyUsage": ["CertSign"], + "IsCA": true, + "Certificates": [ + { + "SubtreeStart": 0, + "SubtreeEnd": 10 + } + ] + }, + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "DNSNames": [ + "a.example", + "*.blah.a.example" + ], + "KeyUsage": [ + "DigitalSignature" + ], + "ExtKeyUsage": [ + "ServerAuth" + ], + "IsCA": false, + "Certificates": [ + { + "SubtreeStart": 0, + "SubtreeEnd": 10 + }, + { + "SubtreeStart": 0, + "SubtreeEnd": 10, + "Cosigners": ["32473.1"] + }, + { + "SubtreeStart": 0, + "SubtreeEnd": 10, + "Cosigners": ["32473.0", "32473.1", "32473.2"] + }, + { + "SubtreeStart": 0, + "SubtreeEnd": 10, + "Cosigners": ["32473.0"] + }, + { + "SubtreeStart": 0, + "SubtreeEnd": 10, + "Cosigners": ["32473.1", "32473.1"] + }, + { + "SubtreeStart": 0, + "SubtreeEnd": 10, + "Cosigners": ["32473.1", "32473.0"], + "DontSortCosigners": true + } + ] + }, + { + "Repeat": 8, + "Subject": { + "CommonName": "Filler certificates" + }, + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z" + } + ] +}
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem new file mode 100644 index 0000000..646f902 --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-ica.pem
@@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +MIIBoDCB+qADAgECAgcBAAAAAAAAMAoGCCsGAQUFBwZDMBQxEjAQBggrBgEFBQcZ +Aw0Egf1ZATAeFw0yMDAxMDEwMDAwMDBaFw0zMDEyMzEyMzU5NTlaMBAxDjAMBgNV +BAMTBUlDQSAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyXLJquJMGPkBDu85 +4pXQbva4Gqn48F6tH5GW9NQpNJCAzCveJVZpSrriRUt6ira3Nags4ZYniXDDa7Vk +vaMflKM7MDkwDgYDVR0PAQH/BAQDAgIEMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMB +MA8GA1UdEwEB/wQFMAMBAf8wCgYIKwYBBQUHBkMDgZQAAAAAAAAAAAAAAAAAAAoA +gHkQsPSVSH1NbrQtzhQyHRykjDOtOT3ckUNhMoYMUWU/GI69fyymmRVhvRkwqGam +Lo+JDcfM8kRQrULqAsqFuYpuEpe0evFYQYcztOY7Ghgz7l1uDB0iKvgVA2WU9Lo+ ++RiOvX8sppkVYb0ZMKhmpi6PiQ3HzPJEUK1C6gLKhbmKAAAA +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem new file mode 100644 index 0000000..bf6770a --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-3cosigners.pem
@@ -0,0 +1,166 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem new file mode 100644 index 0000000..26f9eaa --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-cosigner_wrong_order.pem
@@ -0,0 +1,116 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +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 +AAAAAAAAAAAAAAAAAAAAAA0YKTk= +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem new file mode 100644 index 0000000..02e2316 --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-duplicate_ca_signer.pem
@@ -0,0 +1,116 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +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 +JywtRmlwe4SQmcPEzNHg5w8oP1A= +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem new file mode 100644 index 0000000..fe5f71c --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone-no_ca_signer.pem
@@ -0,0 +1,65 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem new file mode 100644 index 0000000..3224354 --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf-standalone.pem
@@ -0,0 +1,65 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem new file mode 100644 index 0000000..abece8c --- /dev/null +++ b/pki/testdata/path_builder_unittest/mtc_plants07/mtc-leaf.pem
@@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE PROPERTIES----- +AB0AAAAEgf1ZAQABABEADw6B/VmB/VkBAQICAIAAgA== +-----END CERTIFICATE PROPERTIES----- +-----BEGIN CERTIFICATE----- +MIIBuTCCARKgAwIBAgIHAQAAAAAAATAKBggrBgEFBQcGQzAUMRIwEAYIKwYBBQUH +GQMNBIH9WQEwHhcNMjAwMTAxMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjAAMFkwEwYH +KoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jA +f53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0VqNjMGEwDgYDVR0P +AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMCkGA1UdEQEB/wQfMB2C +CWEuZXhhbXBsZYIQKi5ibGFoLmEuZXhhbXBsZTAMBgNVHRMBAf8EAjAAMAoGCCsG +AQUFBwZDA4GUAAAAAAAAAAAAAAAAAAAKAIDw5CImd39w1A3b50VG3MnElMl/EfGu +Pyecuq9uj4O8FhiOvX8sppkVYb0ZMKhmpi6PiQ3HzPJEUK1C6gLKhbmKbhKXtHrx +WEGHM7TmOxoYM+5dbgwdIir4FQNllPS6PvkYjr1/LKaZFWG9GTCoZqYuj4kNx8zy +RFCtQuoCyoW5igAAAA== +-----END CERTIFICATE-----
diff --git a/pki/trust_store.cc b/pki/trust_store.cc index ef2b683..a649a80 100644 --- a/pki/trust_store.cc +++ b/pki/trust_store.cc
@@ -18,6 +18,7 @@ #include <cassert> #include <cstdint> #include <cstring> +#include <memory> #include <optional> #include <string> #include <utility> @@ -197,7 +198,29 @@ SignatureAlgorithm ca_signature_algorithm, UniquePtr<CRYPTO_BUFFER> ca_key, std::vector<LogTrustedSubtrees> log_trusted_subtrees) - : ca_id_(ca_id.begin(), ca_id.end()), + : MTCAnchor(Token(), kPlants04, ca_id, ca_signature_algorithm, + std::move(ca_key), std::move(log_trusted_subtrees)) {} + +std::shared_ptr<const MTCAnchor> MTCAnchor::CreatePlants07( + Span<const uint8_t> ca_id, SignatureAlgorithm ca_signature_algorithm, + UniquePtr<CRYPTO_BUFFER> ca_key, + std::vector<LogTrustedSubtrees> log_trusted_subtrees) { + std::shared_ptr<const MTCAnchor> mtc_anchor = std::make_shared<MTCAnchor>( + Token(), kPlants07, ca_id, ca_signature_algorithm, std::move(ca_key), + std::move(log_trusted_subtrees)); + if (!mtc_anchor->IsValid()) { + return nullptr; + } + return mtc_anchor; +} + +MTCAnchor::MTCAnchor(Token, MtcSpecVersion spec_version, + Span<const uint8_t> ca_id, + SignatureAlgorithm ca_signature_algorithm, + UniquePtr<CRYPTO_BUFFER> ca_key, + std::vector<LogTrustedSubtrees> log_trusted_subtrees) + : spec_version_(spec_version), + ca_id_(ca_id.begin(), ca_id.end()), ca_signature_algorithm_(ca_signature_algorithm), ca_key_(std::move(ca_key)), trusted_subtrees_(std::move(log_trusted_subtrees)) { @@ -325,27 +348,48 @@ BSSL_CHECK(CBB_add_asn1(&subject_seq, &subject_set, CBS_ASN1_SET)); BSSL_CHECK(CBB_add_asn1(&subject_set, &subject_log, CBS_ASN1_SEQUENCE)); - // Section 5.1: Use OID 1.3.6.1.4.1.44363.47.1 as the attribute type for the - // CA ID's name. Note that this is the early experimentation OID in the - // draft rather than the real value of `id-rdna-trustAnchorID`. - static uint8_t tai_attr_oid[] = {0x2b, 0x06, 0x01, 0x04, 0x01, - 0x82, 0xda, 0x4b, 0x2f, 0x01}; - BSSL_CHECK(CBB_add_asn1_element(&subject_log, CBS_ASN1_OBJECT, tai_attr_oid, - sizeof(tai_attr_oid))); + if (spec_version() == kPlants04) { + // Section 5.1: Use OID 1.3.6.1.4.1.44363.47.1 as the attribute type for the + // CA ID's name. Note that this is the early experimentation OID in the + // draft rather than the real value of `id-rdna-trustAnchorID`. + static const uint8_t tai_attr_oid[] = {0x2b, 0x06, 0x01, 0x04, 0x01, + 0x82, 0xda, 0x4b, 0x2f, 0x01}; + BSSL_CHECK(CBB_add_asn1_element(&subject_log, CBS_ASN1_OBJECT, tai_attr_oid, + sizeof(tai_attr_oid))); - // Section 5.1's note for initial experimentation also says to use UTF8String - // to represent the attribute's value rather than RELATIVE-OID. + // Section 5.1's note for initial experimentation also says to use + // UTF8String to represent the attribute's value rather than RELATIVE-OID. - // Convert the relative OID `ca_id` to a string. This can fail. - CBS ca_id_oid(ca_id); - bssl::UniquePtr<char> ca_id_text(CBS_asn1_relative_oid_to_text(&ca_id_oid)); - if (!ca_id_text) { - return; + // Convert the relative OID `ca_id` to a string. This can fail. + CBS ca_id_oid(ca_id); + bssl::UniquePtr<char> ca_id_text(CBS_asn1_relative_oid_to_text(&ca_id_oid)); + if (!ca_id_text) { + return; + } + BSSL_CHECK(CBB_add_asn1_element( + &subject_log, CBS_ASN1_UTF8STRING, + reinterpret_cast<const uint8_t *>(ca_id_text.get()), + strlen(ca_id_text.get()))); + } else { + // A CA ID determines a PKIX distinguished name (Section 4.1.2.4 of + // [RFC5280]) that can be used in the issuer or subject field of an X.509 + // TBSCertificate. This distinguished name has a single relative + // distinguished name, which has a single attribute. The attribute has type + // id-rdna-trustAnchorID, defined below: + // + // id-rdna-trustAnchorID OBJECT IDENTIFIER ::= { + // iso(1) identified-organization(3) dod(6) internet(1) security(5) + // mechanisms(5) pkix(7) rdna(25) 3 } + static const uint8_t tai_attr_oid[] = {0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x19, 0x03}; + BSSL_CHECK(CBB_add_asn1_element(&subject_log, CBS_ASN1_OBJECT, tai_attr_oid, + sizeof(tai_attr_oid))); + + // The attribute's value is a RELATIVE-OID containing the trust anchor ID's + // ASN.1 representation. + BSSL_CHECK(CBB_add_asn1_element(&subject_log, CBS_ASN1_RELATIVE_OID, + ca_id.data(), ca_id.size())); } - BSSL_CHECK( - CBB_add_asn1_element(&subject_log, CBS_ASN1_UTF8STRING, - reinterpret_cast<const uint8_t *>(ca_id_text.get()), - strlen(ca_id_text.get()))); // subjectPublicKeyInfo BSSL_CHECK(CBB_add_asn1_element(&tbs_cert, CBS_ASN1_SEQUENCE, nullptr, 0));
diff --git a/pki/trust_store.h b/pki/trust_store.h index 0a58f63..b61759b 100644 --- a/pki/trust_store.h +++ b/pki/trust_store.h
@@ -152,7 +152,16 @@ public: enum MtcSpecVersion { // draft-ietf-plants-merkle-tree-certs-04 - kPlants04 + kPlants04, + + // draft-ietf-plants-merkle-tree-certs-07 + kPlants07 + }; + + class Token { + private: + explicit Token() = default; + friend MTCAnchor; }; // Create an MTCAnchor with spec version kPlants04 for a trusted CA with @@ -166,20 +175,39 @@ UniquePtr<CRYPTO_BUFFER> ca_key, std::vector<LogTrustedSubtrees> log_trusted_subtrees); + // Create an MTCAnchor with spec version kPlants07 for a trusted CA with + // `ca_id` containing the DER encoding of the relative OID of the CA's ID. + // `ca_signature_algorithm` and `ca_key` configure the CA cosigner key. + // `ca_key` should be a DER-encoded SubjectPublicKeyInfo. + // The `log_trusted_subtrees` must be sorted by log number, and each + // `trusted_subtrees` within must be sorted by their subtree ranges. + // Returns nullptr on error. + static std::shared_ptr<const MTCAnchor> CreatePlants07( + Span<const uint8_t> ca_id, SignatureAlgorithm ca_signature_algorithm, + UniquePtr<CRYPTO_BUFFER> ca_key, + std::vector<LogTrustedSubtrees> log_trusted_subtrees); + + // This constructor is conceptually private, but needs to be public for + // make_shared to work. Uses the "passkey idiom" to prevent callers outside + // of the class from calling it. + // Outside callers should use the Create* static method(s). + MTCAnchor(Token, MtcSpecVersion spec_version, Span<const uint8_t> ca_id, + SignatureAlgorithm ca_signature_algorithm, + UniquePtr<CRYPTO_BUFFER> ca_key, + std::vector<LogTrustedSubtrees> log_trusted_subtrees); + // Returns whether this MTCAnchor represents a valid anchor. This function // exists because the c'tor inputs could be invalid. + // TODO(mattm): remove public constructor and remove or private the IsValid + // method. bool IsValid() const; - MtcSpecVersion spec_version() const { return kPlants04; } - Span<const uint8_t> ca_id() const { - return ca_id_; - } + MtcSpecVersion spec_version() const { return spec_version_; } + Span<const uint8_t> ca_id() const { return ca_id_; } SignatureAlgorithm ca_signature_algorithm() const { return ca_signature_algorithm_; } - const CRYPTO_BUFFER* ca_key() const { - return ca_key_.get(); - } + const CRYPTO_BUFFER *ca_key() const { return ca_key_.get(); } // TODO(nharper): Move this function to TrustAnchor. der::Input NormalizedSubject() const; // TODO(nharper): Remove this function in favor of TrustAnchor's version. @@ -194,6 +222,7 @@ private: void CreateSyntheticCert(Span<const uint8_t> ca_id); + MtcSpecVersion spec_version_; std::vector<uint8_t> ca_id_; SignatureAlgorithm ca_signature_algorithm_; UniquePtr<CRYPTO_BUFFER> ca_key_;
diff --git a/pki/verify_certificate_chain.cc b/pki/verify_certificate_chain.cc index eb651ab..285ff15 100644 --- a/pki/verify_certificate_chain.cc +++ b/pki/verify_certificate_chain.cc
@@ -1129,32 +1129,32 @@ } } -static bool VerifyMTCProofSignaturePlants04( +static bool VerifyMTCProofSignature( const CBS *cosigner_id, Span<const uint8_t> log_id_text, uint64_t start, uint64_t end, const TreeHash &expected_subtree_hash, Span<const uint8_t> signature, SignatureAlgorithm signature_algorithm, const CRYPTO_BUFFER *key_bytes, SignatureVerifyCache *cache) { - ScopedCBB cosigned_message; + ScopedCBB cosigned_subtree; // `cosigner_name` and `log_origin` are the only variable-length parts of - // `CosignedMessage`. Allocate the initial buffer size with 48 bytes for those + // `CosignedSubtree`. Allocate the initial buffer size with 48 bytes for those // (16 byte prefix + 32 bytes for the text representation of the // relative-oid.) - if (!CBB_init(cosigned_message.get(), 12 + 48 + 8 + 48 + 8 + 8 + 32)) { + if (!CBB_init(cosigned_subtree.get(), 12 + 48 + 8 + 48 + 8 + 8 + 32)) { return false; } // Section 7.2 step 12: // Signatures are verified as described in Section 5.3.1. For each signature - // verification, the CosignedMessage structure is constructed as follows: + // verification, the CosignedSubtree structure is constructed as follows: // // Section 5.3.1: // uint8 label[12] = "subtree/v1\n\0"; // (C string constants implicitly have a null terminator, so it's not // explicitly included here:) static constexpr uint8_t kLabel[12] = "subtree/v1\n"; - if (!CBB_add_bytes(cosigned_message.get(), kLabel, sizeof(kLabel))) { + if (!CBB_add_bytes(cosigned_subtree.get(), kLabel, sizeof(kLabel))) { return false; } - // Section 7.2: Set the CosignedMessage's cosigner_name based on the cosigner + // Section 7.2: Set the CosignedSubtree's cosigner_name based on the cosigner // ID as described in Section 5.3.1. // Section 5.3.1: opaque cosigner_name<1..2^8-1>; static constexpr uint8_t kTaiPrefix[16] = {'o', 'i', 'd', '/', '1', '.', @@ -1168,54 +1168,54 @@ Span<const uint8_t> cosigner_id_text = StringAsBytes(cosigner_id_text_buf.get()); CBB cosigner_name; - if (!CBB_add_u8_length_prefixed(cosigned_message.get(), &cosigner_name) || + if (!CBB_add_u8_length_prefixed(cosigned_subtree.get(), &cosigner_name) || !CBB_add_bytes(&cosigner_name, kTaiPrefix, sizeof(kTaiPrefix)) || !CBB_add_bytes(&cosigner_name, cosigner_id_text.data(), cosigner_id_text.size())) { return false; } - // Section 7.2: Set the CosignedMessage's timestamp to zero. + // Section 7.2: Set the CosignedSubtree's timestamp to zero. // Section 5.3.1: uint64 timestamp; - if (!CBB_add_u64(cosigned_message.get(), 0u)) { + if (!CBB_add_u64(cosigned_subtree.get(), 0u)) { return false; } - // Section 7.2: Set the CosignedMessage's log_origin based on log_id as + // Section 7.2: Set the CosignedSubtree's log_origin based on log_id as // described in Section 5.3.1. // Section 5.3.1: opaque log_origin<1..2^8-1>; CBB log_origin; - if (!CBB_add_u8_length_prefixed(cosigned_message.get(), &log_origin) || + if (!CBB_add_u8_length_prefixed(cosigned_subtree.get(), &log_origin) || !CBB_add_bytes(&log_origin, kTaiPrefix, sizeof(kTaiPrefix)) || !CBB_add_bytes(&log_origin, log_id_text.data(), log_id_text.size())) { return false; } - // Section 7.2: Set the CosignedMessage's start and end to the MTCProof's + // Section 7.2: Set the CosignedSubtree's start and end to the MTCProof's // start and end, respectively. // Section 5.3.1: uint64 start; // Section 5.3.1: uint64 end; - if (!CBB_add_u64(cosigned_message.get(), start) || - !CBB_add_u64(cosigned_message.get(), end)) { + if (!CBB_add_u64(cosigned_subtree.get(), start) || + !CBB_add_u64(cosigned_subtree.get(), end)) { return false; } - // Section 7.2: Set the CosignedMessage's subtree_hash to + // Section 7.2: Set the CosignedSubtree's subtree_hash to // expected_subtree_hash. // Section 5.3.1: HashValue subtree_hash; - if (!CBB_add_bytes(cosigned_message.get(), expected_subtree_hash.data(), + if (!CBB_add_bytes(cosigned_subtree.get(), expected_subtree_hash.data(), expected_subtree_hash.size())) { return false; } - if (!CBB_flush(cosigned_message.get())) { + if (!CBB_flush(cosigned_subtree.get())) { return false; } return VerifySignedData( signature_algorithm, - Span<const uint8_t>(CBB_data(cosigned_message.get()), - CBB_len(cosigned_message.get())), + Span<const uint8_t>(CBB_data(cosigned_subtree.get()), + CBB_len(cosigned_subtree.get())), der::BitString(signature, 0), Span(CRYPTO_BUFFER_data(key_bytes), CRYPTO_BUFFER_len(key_bytes)), cache); } @@ -1237,18 +1237,28 @@ // The MTC verified successfully. kSuccess, }; -// This function implements draft-ietf-plants-merkle-tree-certs-04 section 7.2: +// This function implements draft-ietf-plants-merkle-tree-certs-07 section 7.2: // Verifying Certificate Signatures. static VerifyMTCResult VerifyMTC(const ParsedCertificate &cert, const MTCAnchor *mtc_anchor, VerifyCertificateChainDelegate *delegate) { - // Step 1: Check that the TBSCertificate's signature field is id-alg-mtcProof - // (kMtcProofDraftPlants04) with omitted parameters. - if (cert.signature_algorithm() != - SignatureAlgorithm::kMtcProofDraftPlants04) { - // When we parse the signature algorithm, we check that the parameters are - // omitted. - return VerifyMTCResult::kFailed; + if (mtc_anchor->spec_version() == MTCAnchor::kPlants04) { + // Step 1: Check that the TBSCertificate's signature field is + // id-alg-mtcProof (kMtcProofDraftPlants04) with omitted parameters. + if (cert.signature_algorithm() != + SignatureAlgorithm::kMtcProofDraftPlants04) { + // When we parse the signature algorithm, we check that the parameters are + // omitted. + return VerifyMTCResult::kFailed; + } + } else { + // Step 1: Check that the TBSCertificate's signature field is + // id-alg-mtcProof with omitted parameters. + if (cert.signature_algorithm() != SignatureAlgorithm::kMtcProof) { + // When we parse the signature algorithm, we check that the parameters are + // omitted. + return VerifyMTCResult::kFailed; + } } // Step 2: Decode the signatureValue as an MTCProof. @@ -1258,9 +1268,21 @@ if (cert.signature_value().unused_bits() != 0 || !CBS_get_u16_length_prefixed(&mtc_proof, &extensions) || !CBS_get_u48(&mtc_proof, &start) || !CBS_get_u48(&mtc_proof, &end) || - !CBS_get_u16_length_prefixed(&mtc_proof, &inclusion_proof) || - !CBS_get_u16_length_prefixed(&mtc_proof, &signatures) || - CBS_len(&mtc_proof) != 0) { + !CBS_get_u16_length_prefixed(&mtc_proof, &inclusion_proof)) { + return VerifyMTCResult::kFailed; + } + + if (mtc_anchor->spec_version() == MTCAnchor::kPlants04) { + if (!CBS_get_u16_length_prefixed(&mtc_proof, &signatures)) { + return VerifyMTCResult::kFailed; + } + } else { + if (!CBS_get_u24_length_prefixed(&mtc_proof, &signatures)) { + return VerifyMTCResult::kFailed; + } + } + + if (CBS_len(&mtc_proof) != 0) { return VerifyMTCResult::kFailed; } @@ -1497,7 +1519,7 @@ // could first find and verify the CA signature before bothering to check // any of the other ones. if (cosigner_id == mtc_anchor->ca_id()) { - found_valid_ca_signature = VerifyMTCProofSignaturePlants04( + found_valid_ca_signature = VerifyMTCProofSignature( &cbs_cosigner_id, StringAsBytes(log_id_text), start, end, expected_subtree_hash.value(), signature, mtc_anchor->ca_signature_algorithm(), mtc_anchor->ca_key(), @@ -1510,7 +1532,7 @@ } else { auto cosigner = delegate->GetMTCCosigner(cosigner_id); bool this_cosignature_was_valid = false; - if (cosigner && VerifyMTCProofSignaturePlants04( + if (cosigner && VerifyMTCProofSignature( &cbs_cosigner_id, StringAsBytes(log_id_text), start, end, expected_subtree_hash.value(), signature, cosigner->signature_algorithm, cosigner->key.get(),
diff --git a/pki/verify_signed_data.cc b/pki/verify_signed_data.cc index 541c98ca..6caa753 100644 --- a/pki/verify_signed_data.cc +++ b/pki/verify_signed_data.cc
@@ -239,6 +239,7 @@ break; case SignatureAlgorithm::kMtcProofDraftPlants04: + case SignatureAlgorithm::kMtcProof: // This function can't verify MTC proofs. return false;