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