From 30bd0aa8b66d87c20b266499d2c892e39f1e35f8 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Thu, 26 Jan 2023 05:07:08 +1300 Subject: [PATCH] Add MTRCertificateInfo / MTRDistinguishedNameInfo (#24631) * Add MTRCertificateInfo / MTRDistinguishedNameInfo. These are wrappers around ChipCert and ChipDN. Fixes #23668 * Address review comments --- .../Framework/CHIP/MTRCertificateInfo.h | 86 ++++++++ .../Framework/CHIP/MTRCertificateInfo.mm | 185 ++++++++++++++++++ src/darwin/Framework/CHIP/MTRCertificates.h | 3 + src/darwin/Framework/CHIP/MTRConversion.h | 6 + .../Framework/CHIP/MTRDefines_Internal.h | 29 +++ src/darwin/Framework/CHIP/Matter.h | 1 + .../CHIPTests/MTRCertificateInfoTests.m | 144 ++++++++++++++ .../Matter.xcodeproj/project.pbxproj | 14 ++ 8 files changed, 468 insertions(+) create mode 100644 src/darwin/Framework/CHIP/MTRCertificateInfo.h create mode 100644 src/darwin/Framework/CHIP/MTRCertificateInfo.mm create mode 100644 src/darwin/Framework/CHIP/MTRDefines_Internal.h create mode 100644 src/darwin/Framework/CHIPTests/MTRCertificateInfoTests.m diff --git a/src/darwin/Framework/CHIP/MTRCertificateInfo.h b/src/darwin/Framework/CHIP/MTRCertificateInfo.h new file mode 100644 index 00000000000000..94ff81313d8f95 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCertificateInfo.h @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class MTRDistinguishedNameInfo; + +/** + * Exposes Matter-specific information from an operational X.509 certificate. + * + * Note: This class does not support parsing certificates related to Device Attestation. + */ +NS_SWIFT_SENDABLE +MTR_NEWLY_AVAILABLE +@interface MTRCertificateInfo : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes the receiver with an operational certificate in Matter TLV format. + */ +- (nullable instancetype)initWithTLVBytes:(MTRCertificateTLVBytes)bytes; + +@property (readonly) MTRDistinguishedNameInfo * issuer; +@property (readonly) MTRDistinguishedNameInfo * subject; + +@property (readonly) NSDate * notBefore; +@property (readonly) NSDate * notAfter; + +@end + +/** + * Represents the Matter-specific components of an X.509 Distinguished Name. + */ +NS_SWIFT_SENDABLE +MTR_NEWLY_AVAILABLE +@interface MTRDistinguishedNameInfo : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + * The Node ID contained in the DN, if any. + */ +@property (readonly, nullable) NSNumber * nodeID; + +/** + * The Fabric ID contained in the DN, if any. + */ +@property (readonly, nullable) NSNumber * fabricID; + +/** + * The `RCAC` ID contained in the DN, if any. + */ +@property (readonly, nullable) NSNumber * rootCACertificateID; + +/** + * The `ICAC` ID contained in the DN, if any. + */ +@property (readonly, nullable) NSNumber * intermediateCACertificateID; + +/** + * The set of CASE Authenticated Tags contained in the DN. + */ +@property (readonly) NSSet * tags; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRCertificateInfo.mm b/src/darwin/Framework/CHIP/MTRCertificateInfo.mm new file mode 100644 index 00000000000000..abd1f4b849c97d --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRCertificateInfo.mm @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTRCertificateInfo.h" + +#import "MTRConversion.h" +#import "MTRDefines_Internal.h" + +#include + +NS_ASSUME_NONNULL_BEGIN + +using namespace chip; +using namespace chip::Credentials; +using namespace chip::ASN1; + +@interface MTRCertificateInfo () +- (nullable instancetype)initWithTLVBytes:(MTRCertificateTLVBytes)bytes NS_DESIGNATED_INITIALIZER; +@end + +@interface MTRDistinguishedNameInfo () +- (instancetype)initWithDN:(const ChipDN &)dn; +@end + +MTR_DIRECT_MEMBERS +@implementation MTRCertificateInfo { + NSData * _bytes; // needs to be kept around, _data may contain pointers into the backing buffer + struct ChipCertificateData _data; +} + +- (nullable instancetype)initWithTLVBytes:(MTRCertificateTLVBytes)bytes +{ + if (self = [super init]) { + VerifyOrReturnValue(_bytes = [bytes copy], nil); + VerifyOrReturnValue(DecodeChipCert(AsByteSpan(_bytes), _data) == CHIP_NO_ERROR, nil); + } + return self; +} + +- (MTRDistinguishedNameInfo *)issuer +{ + return [[MTRDistinguishedNameInfo alloc] initWithDN:_data.mIssuerDN]; +} + +- (MTRDistinguishedNameInfo *)subject +{ + return [[MTRDistinguishedNameInfo alloc] initWithDN:_data.mSubjectDN]; +} + +- (NSDate *)notBefore +{ + return ChipEpochSecondsAsDate(_data.mNotBeforeTime); +} + +- (NSDate *)notAfter +{ + // "no expiry" is encoded as kNullCertTime (see ChipEpochToASN1Time) + return (_data.mNotAfterTime != kNullCertTime) ? ChipEpochSecondsAsDate(_data.mNotAfterTime) : NSDate.distantFuture; +} + +- (id)copyWithZone:(nullable NSZone *)zone +{ + return self; // immutable, no need to copy +} + +- (BOOL)isEqual:(id)object +{ + if (self == object) { + return YES; + } + if ([object class] != MTRCertificateInfo.class) { + return NO; + } + auto other = (MTRCertificateInfo *) object; + return [_bytes isEqual:other->_bytes]; +} + +- (NSUInteger)hash +{ + return _bytes.hash; +} + +@end + +MTR_DIRECT_MEMBERS +@implementation MTRDistinguishedNameInfo { + ChipDN _dn; +} + +- (instancetype)initWithDN:(const ChipDN &)dn +{ + if (self = [super init]) { + _dn = dn; + } + return self; +} + +- (nullable NSNumber *)nodeID +{ + return [self identifierWithUniqueOID:kOID_AttributeType_MatterNodeId]; +} + +- (nullable NSNumber *)fabricID +{ + return [self identifierWithUniqueOID:kOID_AttributeType_MatterFabricId]; +} + +- (nullable NSNumber *)rootCACertificateID +{ + return [self identifierWithUniqueOID:kOID_AttributeType_MatterRCACId]; +} + +- (nullable NSNumber *)intermediateCACertificateID +{ + return [self identifierWithUniqueOID:kOID_AttributeType_MatterICACId]; +} + +- (nullable NSNumber *)identifierWithUniqueOID:(OID)oid +{ + NSAssert(IsChipDNAttr(oid), @"Invalid OID"); + + ChipRDN const * match = nullptr; + for (auto const & rdn : _dn.rdn) { + if (rdn.IsEmpty()) { + break; + } else if (rdn.mAttrOID == oid) { + VerifyOrReturnValue(!match, nil); // invalid, there should be only one matching RDN + match = &rdn; + } + } + + return (match) ? @(match->mChipVal) : nil; +} + +- (NSSet *)tags +{ + NSMutableSet * result; + for (auto const & rdn : _dn.rdn) { + if (rdn.IsEmpty()) { + break; + } else if (rdn.mAttrOID == kOID_AttributeType_MatterCASEAuthTag) { + NSNumber * tag = @(rdn.mChipVal); + if (!result) { + result = [NSMutableSet setWithObject:tag]; + } else { + [result addObject:tag]; + } + } + } + return (result) ? [result copy] : [NSSet set]; +} + +- (id)copyWithZone:(nullable NSZone *)zone +{ + return self; // immutable, no need to copy +} + +- (BOOL)isEqual:(id)object +{ + if (self == object) { + return YES; + } + if ([object class] != MTRDistinguishedNameInfo.class) { + return NO; + } + auto other = (MTRDistinguishedNameInfo *) object; + return _dn.IsEqual(other->_dn); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRCertificates.h b/src/darwin/Framework/CHIP/MTRCertificates.h index c236f2ea3ed21a..1035eea3783b63 100644 --- a/src/darwin/Framework/CHIP/MTRCertificates.h +++ b/src/darwin/Framework/CHIP/MTRCertificates.h @@ -28,6 +28,9 @@ NS_ASSUME_NONNULL_BEGIN @interface MTRCertificates : NSObject +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + /** * Create a root (self-signed) X.509 DER encoded certificate that has the * right fields to be a valid Matter root certificate. diff --git a/src/darwin/Framework/CHIP/MTRConversion.h b/src/darwin/Framework/CHIP/MTRConversion.h index 83392d08c68264..53225a690e2070 100644 --- a/src/darwin/Framework/CHIP/MTRConversion.h +++ b/src/darwin/Framework/CHIP/MTRConversion.h @@ -20,6 +20,7 @@ #import #include +#include #include NS_ASSUME_NONNULL_BEGIN @@ -32,4 +33,9 @@ AsNumber(chip::Optional optional) return (optional.HasValue()) ? @(optional.Value()) : nil; } +inline NSDate * ChipEpochSecondsAsDate(uint32_t chipEpochSeconds) +{ + return [NSDate dateWithTimeIntervalSince1970:(chip::kChipEpochSecondsSinceUnixEpoch + (NSTimeInterval) chipEpochSeconds)]; +} + NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRDefines_Internal.h b/src/darwin/Framework/CHIP/MTRDefines_Internal.h new file mode 100644 index 00000000000000..f8a6a9329a5cc9 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRDefines_Internal.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if __has_attribute(objc_direct) +#define MTR_DIRECT __attribute__((objc_direct)) +#else +#define MTR_DIRECT +#endif + +#if __has_attribute(objc_direct_members) +#define MTR_DIRECT_MEMBERS __attribute__((objc_direct_members)) +#else +#define MTR_DIRECT_MEMBERS +#endif diff --git a/src/darwin/Framework/CHIP/Matter.h b/src/darwin/Framework/CHIP/Matter.h index b5c699e20c695f..85842fb564c637 100644 --- a/src/darwin/Framework/CHIP/Matter.h +++ b/src/darwin/Framework/CHIP/Matter.h @@ -30,6 +30,7 @@ #import #import #import +#import #import #import #import diff --git a/src/darwin/Framework/CHIPTests/MTRCertificateInfoTests.m b/src/darwin/Framework/CHIPTests/MTRCertificateInfoTests.m new file mode 100644 index 00000000000000..c56f931b88fba0 --- /dev/null +++ b/src/darwin/Framework/CHIPTests/MTRCertificateInfoTests.m @@ -0,0 +1,144 @@ +// +/** + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@interface MTRCertificateInfoTests : XCTestCase + +@end + +@implementation MTRCertificateInfoTests + +// CHIP Certificate: +// Signature Algo : ECDSAWithSHA256 +// Issuer : [[ MatterRCACId = 0000000000000001 ]] +// Not Before : 0x27812280 ( 2021/01/01 00:00:00 ) +// Not After : 0x3A4D2580 ( 2030/12/30 00:00:00 ) +// Subject : [[ MatterRCACId = 0000000000000001 ]] +// Public Key Algo : ECPublicKey +// Curve Id : prime256v1 +// Public Key : 04 61 E7 5C FE 03 EC 90 5E F4 53 77 E5 F4 B5 1D +// E4 3D 55 F4 D4 E7 EA 7B 22 76 5E 59 CA 0A 9B DB +// 59 8F 69 DB 12 8B FB 35 BF 03 1F E9 51 ED 53 37 +// 5D 35 B0 53 22 F4 DF 7E BA EC 02 AC 52 F3 1B 9A +// D7 +// Extensions: +// Is CA : true +// Key Usage : KeyCertSign CRLSign +// Subject Key Id : F4 78 BD A6 C4 1B 24 4C 8A 3B 79 48 2B 1A 1C 7B AE 2E A6 0F +// Authority Key Id : F4 78 BD A6 C4 1B 24 4C 8A 3B 79 48 2B 1A 1C 7B AE 2E A6 0F +// Signature : 21 B8 CF A1 6D 3B 4B 71 6B 51 91 1A 46 80 D1 92 +// 1E 6D 3F 65 F2 A5 A4 27 67 7E 04 0A 50 99 96 2B +// 20 A4 11 10 7D 18 88 51 DD 30 84 52 A2 AA 40 3D +// EB 72 53 80 B0 6C 97 95 FF 38 66 38 F7 A9 65 F1 + +- (MTRCertificateTLVBytes)exampleRCACertTLV +{ + return [[NSData alloc] + initWithBase64EncodedString: + @"FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEEYedc/gPskF70U3fl9" + "LUd5D1V9NTn6nsidl5Zygqb21mPadsSi/s1vwMf6VHtUzddNbBTIvTffrrsAqxS8xua1zcKNQEpARgkAmAwBBT0eL2mxBskTIo7eUgrGhx7ri6mDzAFFP" + "R4vabEGyRMijt5SCsaHHuuLqYPGDALQCG4z6FtO0txa1GRGkaA0ZIebT9l8qWkJ2d+BApQmZYrIKQREH0YiFHdMIRSoqpAPetyU4CwbJeV/zhmOPepZfE" + "Y" + options:0]; +} + +- (void)testParseRootCertificateTLV +{ + MTRCertificateInfo * info = [[MTRCertificateInfo alloc] initWithTLVBytes:self.exampleRCACertTLV]; + XCTAssertNotNil(info); + XCTAssertEqual([NSDate.now compare:info.notBefore], NSOrderedDescending); + XCTAssertEqual([NSDate.now compare:info.notAfter], NSOrderedAscending); + + MTRDistinguishedNameInfo * subject = info.subject; + XCTAssertNotNil(subject); + XCTAssertEqualObjects(subject.rootCACertificateID, @1); + XCTAssertNil(subject.fabricID); + XCTAssertNil(subject.nodeID); + XCTAssertEqualObjects(subject.tags, [NSSet set]); + + XCTAssertEqualObjects(info.issuer, subject); +} + +// CHIP Certificate: +// Signature Algo : ECDSAWithSHA256 +// Issuer : [[ MatterRCACId = 0000000000000001 ]] +// Not Before : 0x2B61DC00 ( 2023/01/24 00:00:00 ) +// Not After : 0x3E2DDEFF ( 2033/01/20 23:59:59 ) +// Subject : [[ MatterFabricId = 0000000000000001, +// MatterNodeId = 000000000001B669, +// MatterCASEAuthTag = 00010001, +// MatterCASEAuthTag = 00080001 ]] +// Public Key Algo : ECPublicKey +// Curve Id : prime256v1 +// Public Key : 04 FD 7F 7A 19 37 E0 6D A4 C2 C9 95 C5 5F 01 10 +// D2 B0 FC 93 50 4C 4A 2A D5 65 90 8B 42 7C AF 60 +// 4A 1C 24 F9 C1 75 61 4C 45 DC 87 34 0F B4 1C 24 +// D2 40 11 3F 82 6D 8B 2A 24 0E E4 A5 9B 30 C6 A9 +// 51 +// Extensions: +// Is CA : false +// Key Usage : DigitalSignature +// Key Purpose : ServerAuth ClientAuth +// Subject Key Id : 03 FC 90 70 10 72 B7 55 09 30 59 B1 B9 4F 1C AE 44 3F DD 1C +// Authority Key Id : 16 49 0D 1A 14 45 78 D1 B8 38 F2 8D 81 0E 3F 5E 66 83 2F DD +// Signature : 77 2B 56 33 8B 86 AC AC 39 45 C4 0D 70 05 09 CD +// 46 E2 B7 17 A2 62 94 04 88 50 92 1C 65 53 5A 34 +// 01 98 EB 07 07 5E DC BF A1 BE 15 08 95 2B 7A 07 +// 03 21 59 7C E4 DD 0E F7 05 14 A5 78 B1 98 91 73 + +- (MTRCertificateTLVBytes)exampleNOCertTLV +{ + return [[NSData alloc] + initWithBase64EncodedString: + @"FTABCAvuIv83A5WWJAIBNwMkFAEYJgQA3GErJgX/3i0+NwYkFQEmEWm2AQAmFgEAAQAmFgEAC" + "AAYJAcBJAgBMAlBBP1/ehk34G2kwsmVxV8BENKw/JNQTEoq1WWQi0J8r2BKHCT5wXVhTEXchzQPtBwk0kARP4JtiyokDuSlmzDGqVE3CjUBKAEYJAIBNg" + "MEAgQBGDAEFAP8kHAQcrdVCTBZsblPHK5EP90cMAUUFkkNGhRFeNG4OPKNgQ4/XmaDL90YMAtAdytWM4uGrKw5RcQNcAUJzUbitxeiYpQEiFCSHGVTWjQ" + "BmOsHB17cv6G+FQiVK3oHAyFZfOTdDvcFFKV4sZiRcxg=" + options:0]; +} + +- (void)testParseOperationalCertificateTLV +{ + MTRCertificateInfo * info = [[MTRCertificateInfo alloc] initWithTLVBytes:self.exampleNOCertTLV]; + XCTAssertNotNil(info); + XCTAssertEqual([NSDate.now compare:info.notBefore], NSOrderedDescending); + XCTAssertEqual([NSDate.now compare:info.notAfter], NSOrderedAscending); + + MTRDistinguishedNameInfo * subject = info.subject; + XCTAssertNotNil(subject); + XCTAssertEqualObjects(subject.fabricID, @0x0000000000000001); + XCTAssertEqualObjects(subject.nodeID, @0x000000000001B669); + XCTAssertEqualObjects(subject.tags, ([NSSet setWithObjects:@0x00010001, @0x00080001, nil])); + XCTAssertNil(subject.rootCACertificateID); + + XCTAssertNotEqualObjects(info.issuer, subject); +} + +- (void)testCertificateInfoEquality +{ + MTRCertificateInfo * infoA1 = [[MTRCertificateInfo alloc] initWithTLVBytes:self.exampleRCACertTLV]; + MTRCertificateInfo * infoA2 = [[MTRCertificateInfo alloc] initWithTLVBytes:self.exampleRCACertTLV]; + MTRCertificateInfo * infoB = [[MTRCertificateInfo alloc] initWithTLVBytes:self.exampleNOCertTLV]; + XCTAssertNotIdentical(infoA1, infoA2); + XCTAssertEqualObjects(infoA1, infoA2); + XCTAssertEqualObjects(infoA1, infoA1); + XCTAssertNotEqualObjects(infoA1, infoB); +} + +@end diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 2637440c2273a4..31e40593414da7 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -44,10 +44,13 @@ 3D843716294979230070D20A /* MTRCallbackBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D843714294979230070D20A /* MTRCallbackBridge.h */; }; 3D843717294979230070D20A /* MTRClusters_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D843715294979230070D20A /* MTRClusters_Internal.h */; }; 3D84374B29498BAE0070D20A /* privilege-storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D84374A29498BAE0070D20A /* privilege-storage.cpp */; }; + 3D843756294AD25A0070D20A /* MTRCertificateInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D843754294AD25A0070D20A /* MTRCertificateInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3D843757294AD25A0070D20A /* MTRCertificateInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D843755294AD25A0070D20A /* MTRCertificateInfo.mm */; }; 3DECCB6E29347D2D00585AEC /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DECCB6D29347D2C00585AEC /* Security.framework */; }; 3DECCB702934AECD00585AEC /* MTRLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DECCB6F2934AC1C00585AEC /* MTRLogging.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3DECCB722934AFE200585AEC /* MTRLogging.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3DECCB712934AFE200585AEC /* MTRLogging.mm */; }; 3DECCB742934C21B00585AEC /* MTRDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DECCB732934C21B00585AEC /* MTRDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3DFCB3292966684500332B35 /* MTRCertificateInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DFCB3282966684500332B35 /* MTRCertificateInfoTests.m */; }; 3DFCB32C29678C9500332B35 /* MTRConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DFCB32B29678C9500332B35 /* MTRConversion.h */; }; 51029DF6293AA6100087AFB0 /* MTROperationalCertificateIssuer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51029DF5293AA6100087AFB0 /* MTROperationalCertificateIssuer.mm */; }; 510CECA8297F72970064E0B3 /* MTROperationalCertificateIssuerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 510CECA6297F72470064E0B3 /* MTROperationalCertificateIssuerTests.m */; }; @@ -234,10 +237,14 @@ 3D84372E294984AF0070D20A /* MTRCallbackBridge.zapt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MTRCallbackBridge.zapt; sourceTree = ""; }; 3D84372F294984AF0070D20A /* command_completion_type.zapt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = command_completion_type.zapt; sourceTree = ""; }; 3D84374A29498BAE0070D20A /* privilege-storage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "privilege-storage.cpp"; path = "util/privilege-storage.cpp"; sourceTree = ""; }; + 3D843754294AD25A0070D20A /* MTRCertificateInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRCertificateInfo.h; sourceTree = ""; }; + 3D843755294AD25A0070D20A /* MTRCertificateInfo.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRCertificateInfo.mm; sourceTree = ""; }; 3DECCB6D29347D2C00585AEC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; 3DECCB6F2934AC1C00585AEC /* MTRLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRLogging.h; sourceTree = ""; }; 3DECCB712934AFE200585AEC /* MTRLogging.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRLogging.mm; sourceTree = ""; }; 3DECCB732934C21B00585AEC /* MTRDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDefines.h; sourceTree = ""; }; + 3DFCB3282966684500332B35 /* MTRCertificateInfoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRCertificateInfoTests.m; sourceTree = ""; }; + 3DFCB32A2966827F00332B35 /* MTRDefines_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDefines_Internal.h; sourceTree = ""; }; 3DFCB32B29678C9500332B35 /* MTRConversion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRConversion.h; sourceTree = ""; }; 51029DF5293AA6100087AFB0 /* MTROperationalCertificateIssuer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTROperationalCertificateIssuer.mm; sourceTree = ""; }; 510CECA6297F72470064E0B3 /* MTROperationalCertificateIssuerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTROperationalCertificateIssuerTests.m; sourceTree = ""; }; @@ -498,6 +505,8 @@ 511913FA28C100EF009235E9 /* MTRBaseSubscriptionCallback.h */, 511913F928C100EF009235E9 /* MTRBaseSubscriptionCallback.mm */, 3D84370F294977000070D20A /* MTRCallbackBridgeBase.h */, + 3D843754294AD25A0070D20A /* MTRCertificateInfo.h */, + 3D843755294AD25A0070D20A /* MTRCertificateInfo.mm */, 517BF3EE282B62B800A8B7DB /* MTRCertificates.h */, 517BF3EF282B62B800A8B7DB /* MTRCertificates.mm */, 1ED276E326C5832500547A89 /* MTRCluster.h */, @@ -515,6 +524,7 @@ 3CF134A6289D8AD90017A19E /* MTRCSRInfo.h */, 3CF134A8289D8D800017A19E /* MTRCSRInfo.mm */, 3DECCB732934C21B00585AEC /* MTRDefines.h */, + 3DFCB32A2966827F00332B35 /* MTRDefines_Internal.h */, 7596A84A287636C1004DAE0E /* MTRDevice_Internal.h */, 7596A84228762729004DAE0E /* MTRDevice.h */, 7596A84328762729004DAE0E /* MTRDevice.mm */, @@ -600,6 +610,7 @@ 51E24E72274E0DAC007CCF6E /* MTRErrorTestUtils.mm */, 51C8E3F72825CDB600D47D00 /* MTRTestKeys.m */, 51D10D2D2808E2CA00E8CA3D /* MTRTestStorage.m */, + 3DFCB3282966684500332B35 /* MTRCertificateInfoTests.m */, 99C65E0F267282F1003402F6 /* MTRControllerTests.m */, 5AE6D4E327A99041001F2493 /* MTRDeviceTests.m */, 5A6FEC9C27B5E48800F25F42 /* MTRXPCProtocolTests.m */, @@ -667,6 +678,7 @@ 7596A84428762729004DAE0E /* MTRDevice.h in Headers */, B2E0D7B8245B0B5C003C5B48 /* MTRSetupPayload.h in Headers */, 7596A84D287782EF004DAE0E /* MTRAsyncCallbackWorkQueue_Internal.h in Headers */, + 3D843756294AD25A0070D20A /* MTRCertificateInfo.h in Headers */, 7596A83E28751220004DAE0E /* MTRBaseClusters_Internal.h in Headers */, 997DED182695344800975E97 /* MTRThreadOperationalDataset.h in Headers */, 9956064426420367000C28DE /* MTRSetupPayload_Internal.h in Headers */, @@ -862,6 +874,7 @@ 5ACDDD7D27CD16D200EFD68A /* MTRClusterStateCacheContainer.mm in Sources */, 513DDB8A2761F6F900DAA01A /* MTRAttributeTLVValueDecoder.mm in Sources */, 2FD775552695557E00FF4B12 /* error-mapping.cpp in Sources */, + 3D843757294AD25A0070D20A /* MTRCertificateInfo.mm in Sources */, 5A7947E427C0129600434CF2 /* MTRDeviceController+XPC.mm in Sources */, 5A6FEC9027B563D900F25F42 /* MTRDeviceControllerOverXPC.mm in Sources */, B289D4222639C0D300D4E314 /* MTROnboardingPayloadParser.mm in Sources */, @@ -897,6 +910,7 @@ 510CECA8297F72970064E0B3 /* MTROperationalCertificateIssuerTests.m in Sources */, 5A7947DE27BEC3F500434CF2 /* MTRXPCListenerSampleTests.m in Sources */, B2F53AF2245B0DCF0010745E /* MTRSetupPayloadParserTests.m in Sources */, + 3DFCB3292966684500332B35 /* MTRCertificateInfoTests.m in Sources */, 517BF3F3282B62CB00A8B7DB /* MTRCertificateTests.m in Sources */, 51E24E73274E0DAC007CCF6E /* MTRErrorTestUtils.mm in Sources */, );