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> &param_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-----
+MIILNTCCARKgAwIBAgIHAQAAAAAAATAKBggrBgEFBQcGQzAUMRIwEAYIKwYBBQUH
+GQMNBIH9WQEwHhcNMjAwMTAxMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjAAMFkwEwYH
+KoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jA
+f53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0VqNjMGEwDgYDVR0P
+AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMCkGA1UdEQEB/wQfMB2C
+CWEuZXhhbXBsZYIQKi5ibGFoLmEuZXhhbXBsZTAMBgNVHRMBAf8EAjAAMAoGCCsG
+AQUFBwZDA4IKDwAAAAAAAAAAAAAAAAAACgCA8OQiJnd/cNQN2+dFRtzJxJTJfxHx
+rj8nnLqvbo+DvBYYjr1/LKaZFWG9GTCoZqYuj4kNx8zyRFCtQuoCyoW5im4Sl7R6
+8VhBhzO05jsaGDPuXW4MHSIq+BUDZZT0uj75GI69fyymmRVhvRkwqGamLo+JDcfM
+8kRQrULqAsqFuYoACXsEgf1ZAAl0n/Q6dY/AKknO+34wpi0fWG9viQCxKPNPKaPa
+y0M7Q/Qmts00Y3fYGcILXWAE3LWwYKtiRi/AADyhOCMAPlIzuJQSeaKfNMO5uDDO
+qTVmNEEpHh6tcNXP9SI31z9xC8w19U7FpGGsQduEy88xCd+vUARwASqqqZJIKuvo
++GBnWHtt8X2hyABHa3mw28uNj76Hl1+y9seKkYqvU8Tr86U+vzYcbvbSJ2jbO48C
+4Q1aVoO/W/VLR1kYTmFcm0sH3mwK2atT3zDeeZvehJ+GbkNMKUMLn4A739He7LKv
+cp5xsN4/ARK5US7oaga94t8wnIyt1k1V4uFzPFftUC5BlnfDQXFRSCjA6VwUIlmy
+WZT3/e+ndKdeEepdqLmrSYPsgyb2V/I6XxkcI/Xp8jKDrvUfPK3i4/rYjF5Ik18E
+4Pebwll265JyDBYQZ8dmyWRIF1SR8BkYN8XspjNsZoVSRZqBcLE5BViaAjDF3ngy
+gmkR+0ufqWpZJcH6gABjvcS8v7wTLaef+JVBuEVZ8A1iwMJZEPjVipeJDFhZvbzL
+h6XpmB2R83WNaWAHo/42OmK6/nkSRB7eiWescsZ/itDn6XLsFtV+xcjOY3khTwb0
+SffUCbWIY6d3bdvBQ+U5ZmKtLHKuYn6GLvPR71t3Y7kk1hkpateLX6JJuNSqVqA8
+hyEROM9gIMRBBmv6nxvGpuNRI2kJM0DrfZShOQoA9b6EgLKHW3aTplBZ2qikotj/
+I2JmbqoPPvLBm3IAap4W4PD/vbCkCywqQ32HFHzfeNgKTioXTCU3yUNsCf+V64zz
+SL+1GtxB8PJWajOazReIym/iMlstAI6SzGFHlYlYAmbJC7f58MOV8M+EGeL2O/8G
+U2eRigMzLo+NlbhbGnBdrSFyxUtbqg/NhXS9X8FIk4ErN1bw4wlUCnov12lji0Nq
+Zdw2bKfDwVDOitDzVwllTg4oNvHWBbRzWfXHXWzZO0LBIXrQaji6GdfitfIHJ3MG
+j63mKoESehxAsz1Tnd5P4gmqXIeKNWRai0gmbQLsezg168lhoBudaTSvetcz+GI6
+62nZgTvBdcL/T+jXNHNz/7i33fvU3SDGg4nCdiCb1NetxxknusM5atGyge+P6sGM
+DGon/ns5AuMT5eaqbzlHvy6QQltIdtG7TD23EG4NGBJxIRgwKNlI8eqoEKDxn5a1
+iMrQWQLETxIjvhPmMEXOYUs3UT/vi3N+XtyptpugfCfwxFfvDfWsS+cDv4OTDnft
+s2O6s3zWubkyi+rW3hgpZNtAMR4UEi+K0QBlCB6+iqYG6LReVoETFavQVCLjhc+s
+au66qNC7VqHwJ4HYP/UPceQsJQavlI3jxC7IPlsaqamMjmJVQyhwqCXj4UX7VJdZ
+js/vo/9FoTTNLv0Gw/Oyr5JVnFbr8IlKgal+r4ZEhpG8qTBkZ4VySApZQYIxnUwz
+EHVX+jS+AdaXyOpBH86xKldnYuR9crMdEOiuhcEI2IGCpaMCkPGR28UmPh+FldU2
+sjQ9ZKaC85XlB8vLY+Rvg2vQsi0A65fUA+kw1Lq8G3S8jycl1o6miwyfDYUkwmF3
+1FVPB8iTAs1O0peOKYMvfPSbZX+EhVxiCDptylK1hE+v6mrmEjzSbOgmRcvk0/w3
+r6/qbj9ARmh0sFs9exakEKqrsHvzxWJpqkjtcdmMmf4k3RbGYJI3cvaqqR/THvjU
+hSSITRDXOBeCsLbLgUw7wNFZJray8wWnXOFv4tTrDEgOpWNZlN6sBzE3dP8gQ+we
+5+pJ48AULm8j54kKR81ChsUx/5zoLukLbDm6w/BMGj0paqq0sOBNge0DsgsrvO2m
+nf0MoAvM+a4+xm6E2NMiQKQHPKWKedVLyQw2gGegvLe6HovwZ7K8rC22dTJHl8Dr
+mCBjxWZBa3/C2q9NcovcBWPbZP4IKuyATKG8pCXQQCMhcRsr4q9u6Bv7/Bpg+XBS
+QgRMEFOZxyF1gyQk84JGGMSbqV48G9EKAfJ3ZMKwySZXLIZ2OBCvpKpVGAmh1RbT
+S6Yis6UK2HKdS8fKvdFuTIbtAkg5sDGmgTMgbA+4etaVYsARjsg0T6sn2Igyn2z+
+IeITc+E2YB9E9UwE0nsAc1oDBP4jz7VcLuiD/b2pr93ejZNYZAYu+8i18SkQBVum
+jmj8uFg6gSb709MWn4aghLuGRANcYO3tf5YOD5XFr8p1ikcBais26cN6ZqQaiefL
+aoI/INWNg5WodvyXSBxyMLh5OytrqdOFBotG4E/ZLkul+oLxqmFDNffWJUkfZGOm
+OYeVMXzyzvMP4PgS27+iYCMk0kHJoan3CZePlCFBcI43nWWkCNaOmlqtDae4XPgb
+1wC2rQBBve6gqD4381JwgymJUswoZgDXieJ7c8EWL8If3JHh3VW7m+/ycxMugluc
+qCEz9MV0nbx0GnTqlzI0X2rSgRX6XUxFh9Pc01OPvBRf/bYBUo1YghuM4G12DMq6
+L3iM1Ta2vN2cs5KJvgZg9K6stzaasIyxcM21Y7zYcXfjbwadbJ+JvqwEBUAs/yde
+ybv6bUttjV6unl2552hhXWjyddV7hPml5nVQKO1ELWvDtmlEch7CkpYUgch25St/
+mcEPayLWCpb8IbC376lYiLmXEhs6DQsevZzBamllmAv34ezaYrtW4QowU+Djh1/1
+gSwvc6CaumBgc8G+fVaPcPWrV7AVPYWkUHAT3MeAzvReUDxR2oVw/wBHWxRwSYQM
+vp04v3CcCzuQJ31E6x1s8l3Bkcvrup+2CkjwAm/78Qwfe/+Cgp9xRGEalLzJCTNR
+15sgGtKjqb+P+Ew5oqbwr3yhvhqBA3WW5q/yBPQg4GCyUGm+aVWAVTSRNK9Q6LJP
++U34xuTBHaUMUcBU+i2zIedOkgoSxfqaJAL1xNMnvJ6f+QXsTi5DfKT6hd+aCD/2
+gfUI+73BPbot84rz8hg/rVKAD811M4ZzjpgiJ1DD2vdekMZrPnkR+qf20052quB+
+9RsZflxj0GIdQipAHThmZGWx+YtAqOKL2VnBiczR7tYWJE3OdmNUF9BdOk4XoAwe
+HMaNwPgTZFu0yVviAk0roN6SWwASz3qNxe92BiS4y5e9nwUl8sA5UkU99U1E9dMG
+Ic2buaUGBx4gMDFFUV5zd32BhZKiq7zvBw4WHCoyQIKSwsXS7v4AGCZMTVNXWWJw
+cn6MoKGmrt/w/f4DHzs8Plxsd5mpuMzb5ufwAAAAAAAAAAAAABMhNkY=
+-----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-----
+MIILNTCCARKgAwIBAgIHAQAAAAAAATAKBggrBgEFBQcGQzAUMRIwEAYIKwYBBQUH
+GQMNBIH9WQEwHhcNMjAwMTAxMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjAAMFkwEwYH
+KoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jA
+f53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0VqNjMGEwDgYDVR0P
+AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMCkGA1UdEQEB/wQfMB2C
+CWEuZXhhbXBsZYIQKi5ibGFoLmEuZXhhbXBsZTAMBgNVHRMBAf8EAjAAMAoGCCsG
+AQUFBwZDA4IKDwAAAAAAAAAAAAAAAAAACgCA8OQiJnd/cNQN2+dFRtzJxJTJfxHx
+rj8nnLqvbo+DvBYYjr1/LKaZFWG9GTCoZqYuj4kNx8zyRFCtQuoCyoW5im4Sl7R6
+8VhBhzO05jsaGDPuXW4MHSIq+BUDZZT0uj75GI69fyymmRVhvRkwqGamLo+JDcfM
+8kRQrULqAsqFuYoACXsEgf1ZAQl0pp913G7i0bmRQjPEx6HBK1DqLf8Kq/1TMIMB
+fWRHYmR+7e2cZH8NxJ4iYrh9Z1Uof/li/zzut/7EIzQHGPg1uvJGGzc5g+Gmx6Lp
+HxERgTdslysITggf1NmdYMLm5iaUQ5y6F5F+VL0g0TUgqcwwkWVPV8nIQG9GvssC
+891jxZK4x45QhBwkAYXQhZ3T47KcjG0IJVnLamJHvKXnlO5SH5iqJ5xqLyhy+7mf
+wPgUdxbfj2UCZKNz/HEID0AVIc2T0eTxTu+V+w040Z9fTXcO3CmcFvc4mj2qCDaL
+bS4aotJBCwljaXdzOa1rsOiqhS4grvDGUqC/iV7jl607f/+VmpQwlVjlKf1gIBx/
+sl3ZNcu4/e0kNazoGrRYOw/uWNWET2Asnh4uyfU16gaxQnRCbpffONyZKPrHqePQ
+dsYLnuWVaA/ay16vWyrckQZka/Y0sd+EXjjT4EQTT/DoJXv8J62ooI3BXd+vYXhm
+CC6kSwjw2OZkYjbxlv2YkFf+i88NnxY5IdJwyOFI8xbQVaoUGMfFwxjcHCKutofY
+IvK8B6q6jABQRRPxsE2E74xCa8O+tahG2WggiyxOBNVPiKUKzJomrRoSF7ClXjaK
+iJ5Jrr5Le4pe/2v/TBceMvTWjfQgT3mr4KE08kodp2BlVGS91dp4QG/zfH6KiU2I
+WV5ZzS4dZrfxbeJOEpF8joTaXVuRL0+FeWGV4SiV9Owf4i+CZANjKP0AAsWytKZL
+0xUUKA/J08n1xcKOwWq5CrC7eOzQsTwVtnF4ysoOs5R28qMcePj3Gc0LxlGQ/Sad
+QkLzxZuXg+V8JP2GK7VDgKbPJnDhUEA2sJLGTxoeLc7bsf7CGoWiE0RkT5pDNwXf
+85DvGVA9ucEENu2wQwTuEINQG+4MKMRJDGIthMD7xvmkg7OB8eGATp7DQ1nGpkpl
+WFw3NASQzelh109FWQFeu5sMZfrLDDGQME5kJ+lyYuv+pAKL2uPa+hG/j4cUWGjl
+8ucOZZqvGn6QGxRLK2gPRkBWmRuFDw/ej3yjbwOXuVSFiH4d/FHgePr4IIG9Izf9
+yWRyOdiJk51BC4iFvuLb0DAbYCHy336nOdW2l6iTl3jW7JTHs9IuR5Qp39oAe2XJ
+TuQuoxDuDcsrGndWaZYsSZ+SEqG7/VqFzp2/hX6dTfMqKOrawBnim8n7YI2FiEC6
+804otIx//HIyXHSN0xg/HLLdnkai1/eZpGpGhk5VOKmMGPV8PCOvOiv+IjbI5Fd9
+ejM2WMCvcpiVhoQk24VAQAroYNSw3BXmj84RoHF32efxyweMTxZXFjhfLeAxEgvx
+M9loTmOvUoxVb8NqOHDIrHx+RHSuO/4t8nbDRsZ+396GL36lGFyJ+zjgNWNuqH+L
+guhluNQM4sivjx8waPaFeqPHGp5O5cDwh0qwjuHjECoHM2IANUnK6iFGSMhFthW9
+imJhnFR2U5Pt+oLZH8CXOKzYWNhhPztbmJuRFJbV7fOa9SYTg0M/88p0HPB1Prpm
+UDxi/s6LQIJUGf1crIcxNOhGo1FgcR1KAFbxMhDCr6Upl186VUGlkPuIUu0/P2NN
+BeVQ7vjw5/Nn1SOypUgMk8REjAc6eW9odGoWSjy5ZABR6aNrRV2TtK5/RVtWSClm
+4OdxCpc1oUw12yjzodchaS1H1juHgxBo62FBVeyc2ol0kvupc7bdjUzsQs/54HC9
+jL49Dc7EGLRyDgJ1nO7PjKCJPkbfBF2DQVi5fEEGK74OFDSmxEnWg4XiUjbww5FQ
+3JLI++bSt0YwpCCDO/Q1HCE9CfxJOJQ/4fnsRhLYT9Je15Lh7C5Bc5mcpMa86J92
+vaWsBDMCewQFA5TpHQVNUTXh9uD966Hn7zrwXW53CccKHP5xFX9ACBeiezGvtEBh
+sN179qgNv0N1ukkyDj/NWCfAyEfsVmGOvWS7Q0vwipyM7UzlkZ4IpHp8o3E/GTpa
+SOEW8aYZGJjMAJ56zCtFZQalhYJLfqnLJUpNkkO+dzXM+jX9x4dasRiwl3iCPUJb
+IDLKXpQOH7mjZ9dtBloBRr55QgffqbFqbll2J/lO+SxC8FAr8CoSDG8maEm/ZFqv
+IXLNHJCLmzzFKmCYUt7Vu/EQDtccguRwln+r2oPZUPJAXefN4gp7AUBNs8UoO24+
+lP4CBMcht6oJICYh5uIb7yH49klEeVu7HkjcAmVidrnYtjPHWg/QBOJZPKh/CJWv
+a8II36BEeU9hSkDpAIYw89deL2GQqs1t2sffTv8X+cBf/wCSMHNKGOr2x7B8aavs
+BUUEhPSHsz+3fnVaqFRS7dPhvcdURsUUMqAW4i7VSGMZ19WaPYFQzkRqlNeIM3hl
+mxtofMVFCS89vXOMAdy2qDJR2Nq0Y0tZ83SfHNfaBRxl/bYVx6gxV3jYvBuqXMJG
+4E+OJFulK6hhVEnpQNGsKkX/Dvcyce3amBS9KxxjwEQ7CHP3+flj3kqpbLgfJVNo
+FUSxKN3qEy5b5quYiMvAP1e+qgG+iGZ0z0Uz0Zh+KfOS3wLwgLU9KH2KIejAnNBW
+A0qSa5wJcRe+oG3TFDiDLyjXUlttGn0MPqwI2uRCvFaubjw7XGybZ7Kxj4tiWMvw
+l/GeHSyZ5AvDW+rPl56BVhxqxv6IZvxmYHWAq0kom7gofXWtJnvKGlF15M5LbZsf
+h7JWHqAVzx7Wo5ft3Y1Ow3r495nkoriy+vy4Cdw1bcqgFs5lPjRUI+9hszFC6eZs
+mY8tctYmAjqGpMLI0PxTisDlNJ4zHThbliBJW53bGDuBtjzUbtKDplI5w5/luAv7
+4NsYEZdMFx4D+EJvbUSc0Ton0fiyBv4Yc60ed//I5XhejW2E6nsrkEd3/PfPJ87r
+Qoyv6yXwKI3GkrhLrSn0rCMm5lZKzhtr5/2TE4uyEEnguf6fp3NLQdIN335UlWFW
+9cqp+Oa/ByxGBzCuuT3yMXl1Q6kTQxrtAcpAIN21fkRiek0DWoFz9e38XTGNcLEv
+iXYx5oX232UxxQP59VFgwRhonn/kIvLCMzTRXbX6Y3GcKqek1uNJITZNQ965PGYw
+3bjw1SXjT1Vv90xWKh7ZQY8IQyvrL29CjhmJ+dR8/9S8YzTY0HvUt28FvP+EExr6
+Mbj7cfQGFSMmKCw4UV54mJqjt7jJ2vb8/gEKESUxQEZWfIirvM7d5AUVNEJGXmFm
+aXaDhpSZtNTs+BkoLjEzU1txj5KivsDByusAAAAAAAAAAAAAABQjNUU=
+-----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;