Add a Darwin utility to convert Matter TLV certificates to DER. (#23628)

We have one for going DER -> TLV, but nothing for TLV -> DER.
diff --git a/src/darwin/Framework/CHIP/MTRCertificates.h b/src/darwin/Framework/CHIP/MTRCertificates.h
index 57eac02..e18878f 100644
--- a/src/darwin/Framework/CHIP/MTRCertificates.h
+++ b/src/darwin/Framework/CHIP/MTRCertificates.h
@@ -141,6 +141,16 @@
  */
 + (MTRCertificateTLVBytes _Nullable)convertX509Certificate:(MTRCertificateDERBytes)x509Certificate;
 
+/**
+ * Convert the given Matter TLV encoded certificate to the X.509v3 DER encoded
+ * format.
+ *
+ * Returns nil if the conversion fails (e.g. if the input data cannot be parsed
+ * as a Matter TLV encoded certificate, or if the certificate cannot be
+ * represented in the X.509v3 DER format).
+ */
++ (MTRCertificateDERBytes _Nullable)convertMatterCertificate:(MTRCertificateTLVBytes)matterCertificate MTR_NEWLY_AVAILABLE;
+
 @end
 
 @interface MTRCertificates (Deprecated)
diff --git a/src/darwin/Framework/CHIP/MTRCertificates.mm b/src/darwin/Framework/CHIP/MTRCertificates.mm
index 1996cbd..39735bd 100644
--- a/src/darwin/Framework/CHIP/MTRCertificates.mm
+++ b/src/darwin/Framework/CHIP/MTRCertificates.mm
@@ -214,6 +214,23 @@
     return AsData(chipCertBytes);
 }
 
++ (MTRCertificateDERBytes _Nullable)convertMatterCertificate:(MTRCertificateTLVBytes)matterCertificate
+{
+    chip::ByteSpan tlvCertBytes = AsByteSpan(matterCertificate);
+
+    uint8_t derCertBuffer[chip::Controller::kMaxCHIPDERCertLength];
+    chip::MutableByteSpan derCertBytes(derCertBuffer);
+
+    CHIP_ERROR errorCode = chip::Credentials::ConvertChipCertToX509Cert(tlvCertBytes, derCertBytes);
+
+    if (errorCode != CHIP_NO_ERROR) {
+        MTR_LOG_ERROR("ConvertChipCertToX509Cert: %{public}s", chip::ErrorStr(errorCode));
+        return nil;
+    }
+
+    return AsData(derCertBytes);
+}
+
 @end
 
 @implementation MTRCertificates (Deprecated)
diff --git a/src/darwin/Framework/CHIPTests/MTRCertificateTests.m b/src/darwin/Framework/CHIPTests/MTRCertificateTests.m
index e42ea14..abb6007 100644
--- a/src/darwin/Framework/CHIPTests/MTRCertificateTests.m
+++ b/src/darwin/Framework/CHIPTests/MTRCertificateTests.m
@@ -34,6 +34,15 @@
 
     __auto_type * rootCert = [MTRCertificates createRootCertificate:testKeys issuerID:nil fabricID:nil error:nil];
     XCTAssertNotNil(rootCert);
+
+    // Test round-trip through TLV format.
+    __auto_type * tlvCert = [MTRCertificates convertX509Certificate:rootCert];
+    XCTAssertNotNil(tlvCert);
+
+    __auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
+    XCTAssertNotNil(derCert);
+
+    XCTAssertEqualObjects(rootCert, derCert);
 }
 
 - (void)testGenerateIntermediateCert
@@ -54,6 +63,15 @@
                                                                            fabricID:nil
                                                                               error:nil];
     XCTAssertNotNil(intermediateCert);
+
+    // Test round-trip through TLV format.
+    __auto_type * tlvCert = [MTRCertificates convertX509Certificate:intermediateCert];
+    XCTAssertNotNil(tlvCert);
+
+    __auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
+    XCTAssertNotNil(derCert);
+
+    XCTAssertEqualObjects(intermediateCert, derCert);
 }
 
 - (void)testGenerateOperationalCertNoIntermediate
@@ -81,6 +99,15 @@
                                                             caseAuthenticatedTags:cats
                                                                             error:nil];
     XCTAssertNotNil(operationalCert);
+
+    // Test round-trip through TLV format.
+    __auto_type * tlvCert = [MTRCertificates convertX509Certificate:operationalCert];
+    XCTAssertNotNil(tlvCert);
+
+    __auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
+    XCTAssertNotNil(derCert);
+
+    XCTAssertEqualObjects(operationalCert, derCert);
 }
 
 - (void)testGenerateOperationalCertWithIntermediate
@@ -113,6 +140,15 @@
                                                             caseAuthenticatedTags:nil
                                                                             error:nil];
     XCTAssertNotNil(operationalCert);
+
+    // Test round-trip through TLV format.
+    __auto_type * tlvCert = [MTRCertificates convertX509Certificate:operationalCert];
+    XCTAssertNotNil(tlvCert);
+
+    __auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
+    XCTAssertNotNil(derCert);
+
+    XCTAssertEqualObjects(operationalCert, derCert);
 }
 
 - (void)testGenerateOperationalCertErrorCases