From 2521842658eee9e9123cc05c9166f62401d6386e Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Fri, 11 Oct 2024 17:34:29 +0200 Subject: [PATCH] [darwin-framework-tool] Add an option to use per-controller storage instead of a global shared storage --- examples/darwin-framework-tool/BUILD.gn | 6 + .../commands/common/CHIPCommandBridge.h | 9 + .../commands/common/CHIPCommandBridge.mm | 168 +++++++++++++----- .../common/CHIPCommandStorageDelegate.h | 20 +++ .../common/CHIPCommandStorageDelegate.mm | 91 ++++------ .../commands/common/CertificateIssuer.h | 46 +++++ .../commands/common/CertificateIssuer.mm | 157 ++++++++++++++++ .../commands/common/ControllerStorage.h | 46 +++++ .../commands/common/ControllerStorage.mm | 132 ++++++++++++++ .../commands/common/PreferencesStorage.h | 32 ++++ .../commands/common/PreferencesStorage.mm | 110 ++++++++++++ .../commands/pairing/PairingCommandBridge.mm | 7 + .../commands/storage/Commands.h | 5 +- .../storage/StorageManagementCommand.h | 8 + .../storage/StorageManagementCommand.mm | 33 +++- .../Matter.xcodeproj/project.pbxproj | 24 +++ 16 files changed, 790 insertions(+), 104 deletions(-) create mode 100644 examples/darwin-framework-tool/commands/common/CertificateIssuer.h create mode 100644 examples/darwin-framework-tool/commands/common/CertificateIssuer.mm create mode 100644 examples/darwin-framework-tool/commands/common/ControllerStorage.h create mode 100644 examples/darwin-framework-tool/commands/common/ControllerStorage.mm create mode 100644 examples/darwin-framework-tool/commands/common/PreferencesStorage.h create mode 100644 examples/darwin-framework-tool/commands/common/PreferencesStorage.mm diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn index 5e7b7d641030b8..0d1e142f1074df 100644 --- a/examples/darwin-framework-tool/BUILD.gn +++ b/examples/darwin-framework-tool/BUILD.gn @@ -190,10 +190,16 @@ executable("darwin-framework-tool") { "commands/common/CHIPCommandBridge.mm", "commands/common/CHIPCommandStorageDelegate.mm", "commands/common/CHIPToolKeypair.mm", + "commands/common/CertificateIssuer.h", + "commands/common/CertificateIssuer.mm", + "commands/common/ControllerStorage.h", + "commands/common/ControllerStorage.mm", "commands/common/MTRDevice_Externs.h", "commands/common/MTRError.mm", "commands/common/MTRError_Utils.h", "commands/common/MTRLogging.h", + "commands/common/PreferencesStorage.h", + "commands/common/PreferencesStorage.mm", "commands/common/RemoteDataModelLogger.h", "commands/common/RemoteDataModelLogger.mm", "commands/configuration/Commands.h", diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h index 9458d304dbebb2..f58251bff48dd0 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h @@ -41,6 +41,8 @@ class CHIPCommandBridge : public Command { "Sets the commissioner node ID of the given " "commissioner-name. Interactive mode will only set a single commissioner on the inital command. " "The commissioner node ID will be persisted until a different one is specified."); + AddArgument("commissioner-shared-storage", 0, 1, &mCommissionerSharedStorage, + "Use a shared storage instance instead of individual storage for each commissioner. Default is true."); AddArgument("paa-trust-store-path", &mPaaTrustStorePath, "Path to directory holding PAA certificate information. Can be absolute or relative to the current working " "directory."); @@ -87,6 +89,7 @@ class CHIPCommandBridge : public Command { // This method returns the commissioner instance to be used for running the command. MTRDeviceController * CurrentCommissioner(); + NSNumber * CurrentCommissionerFabricId(); MTRDeviceController * GetCommissioner(const char * identity); @@ -130,6 +133,8 @@ class CHIPCommandBridge : public Command { void StopWaiting(); CHIP_ERROR MaybeSetUpStack(); + CHIP_ERROR SetUpStackWithSharedStorage(NSArray * productAttestationAuthorityCertificates); + CHIP_ERROR SetUpStackWithPerControllerStorage(NSArray * productAttestationAuthorityCertificates); void MaybeTearDownStack(); CHIP_ERROR GetPAACertsFromFolder(NSArray * __autoreleasing * paaCertsResult); @@ -140,6 +145,9 @@ class CHIPCommandBridge : public Command { // The current controller; the one the current command should be using. MTRDeviceController * mCurrentController; + static bool sUseSharedStorage; + chip::Optional mCommissionerSharedStorage; + std::condition_variable cvWaitingForResponse; std::mutex cvWaitingForResponseMutex; chip::Optional mCommissionerName; @@ -148,4 +156,5 @@ class CHIPCommandBridge : public Command { static dispatch_queue_t mOTAProviderCallbackQueue; chip::Optional mPaaTrustStorePath; chip::Optional mCommissionerVendorId; + std::string mCurrentIdentity; }; diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm index d52c29a5b04c8a..f51de87373f9b3 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm @@ -23,7 +23,10 @@ #include #include +#include // for chip::kTestControllerNodeId +#import "CertificateIssuer.h" +#import "ControllerStorage.h" #include "MTRError_Utils.h" #include @@ -34,10 +37,9 @@ std::map CHIPCommandBridge::mControllers; dispatch_queue_t CHIPCommandBridge::mOTAProviderCallbackQueue; OTAProviderDelegate * CHIPCommandBridge::mOTADelegate; +bool CHIPCommandBridge::sUseSharedStorage = true; constexpr char kTrustStorePathVariable[] = "PAA_TRUST_STORE_PATH"; -CHIPToolKeypair * gNocSigner = [[CHIPToolKeypair alloc] init]; - CHIP_ERROR CHIPCommandBridge::Run() { // In interactive mode, we want to avoid memory accumulating in the main autorelease pool, @@ -120,61 +122,111 @@ CHIP_ERROR CHIPCommandBridge::MaybeSetUpStack() { - if (IsInteractive()) { - return CHIP_NO_ERROR; - } - NSData * ipk; - gNocSigner = [[CHIPToolKeypair alloc] init]; - storage = [[CHIPToolPersistentStorageDelegate alloc] init]; + VerifyOrReturnError(!IsInteractive(), CHIP_NO_ERROR); mOTADelegate = [[OTAProviderDelegate alloc] init]; + storage = [[CHIPToolPersistentStorageDelegate alloc] init]; - auto factory = [MTRDeviceControllerFactory sharedInstance]; - if (factory == nil) { - ChipLogError(chipTool, "Controller factory is nil"); - return CHIP_ERROR_INTERNAL; + NSError * error; + __auto_type * certificateIssuer = [CertificateIssuer sharedInstance]; + [certificateIssuer startWithStorage:storage error:&error]; + VerifyOrReturnError(nil == error, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Can not start the certificate issuer: %@", error)); + + NSArray * productAttestationAuthorityCertificates = nil; + ReturnLogErrorOnFailure(GetPAACertsFromFolder(&productAttestationAuthorityCertificates)); + if ([productAttestationAuthorityCertificates count] == 0) { + productAttestationAuthorityCertificates = nil; } - auto params = [[MTRDeviceControllerFactoryParams alloc] initWithStorage:storage]; - params.shouldStartServer = YES; - params.otaProviderDelegate = mOTADelegate; - NSArray * paaCertResults; - ReturnLogErrorOnFailure(GetPAACertsFromFolder(&paaCertResults)); - if ([paaCertResults count] > 0) { - params.productAttestationAuthorityCertificates = paaCertResults; + sUseSharedStorage = mCommissionerSharedStorage.ValueOr(true); + if (sUseSharedStorage) { + return SetUpStackWithSharedStorage(productAttestationAuthorityCertificates); } - NSError * error; - if ([factory startControllerFactory:params error:&error] == NO) { - ChipLogError(chipTool, "Controller factory startup failed"); - return MTRErrorToCHIPErrorCode(error); + return SetUpStackWithPerControllerStorage(productAttestationAuthorityCertificates); +} + +CHIP_ERROR CHIPCommandBridge::SetUpStackWithPerControllerStorage(NSArray * productAttestationAuthorityCertificates) +{ + __auto_type * certificateIssuer = [CertificateIssuer sharedInstance]; + + constexpr const char * identities[] = { kIdentityAlpha, kIdentityBeta, kIdentityGamma }; + std::string commissionerName = mCommissionerName.HasValue() ? mCommissionerName.Value() : kIdentityAlpha; + for (size_t i = 0; i < ArraySize(identities); ++i) { + __auto_type * uuidString = [NSString stringWithFormat:@"%@%@", @"8DCADB14-AF1F-45D0-B084-00000000000", @(i)]; + __auto_type * controllerId = [[NSUUID alloc] initWithUUIDString:uuidString]; + __auto_type * vendorId = @(mCommissionerVendorId.ValueOr(chip::VendorId::TestVendor1)); + __auto_type * fabricId = @(i + 1); + __auto_type * nodeId = @(chip::kTestControllerNodeId); + + if (commissionerName.compare(identities[i]) == 0 && mCommissionerNodeId.HasValue()) { + nodeId = @(mCommissionerNodeId.Value()); + } + + NSError * error; + __auto_type * operational = [certificateIssuer issueOperationalCertificateForNodeID:nodeId fabricID:fabricId error:&error]; + + __auto_type * controllerStorage = [[ControllerStorage alloc] initWithControllerID:controllerId]; + __auto_type * controllerStorageQueue = dispatch_queue_create("com.chip.storage", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + __auto_type * params = [[MTRDeviceControllerExternalCertificateParameters alloc] initWithStorageDelegate:controllerStorage + storageDelegateQueue:controllerStorageQueue + uniqueIdentifier:controllerId + ipk:certificateIssuer.ipk + vendorID:vendorId + operationalKeypair:certificateIssuer.signingKey + operationalCertificate:operational + intermediateCertificate:nil + rootCertificate:certificateIssuer.rootCertificate]; + [params setOperationalCertificateIssuer:certificateIssuer queue:controllerStorageQueue]; + params.productAttestationAuthorityCertificates = productAttestationAuthorityCertificates; + + __auto_type * controller = [[MTRDeviceController alloc] initWithParameters:params error:&error]; + VerifyOrReturnError(nil != controller, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Controller startup failure: %@", error)); + mControllers[identities[i]] = controller; } - ReturnLogErrorOnFailure([gNocSigner createOrLoadKeys:storage]); + return CHIP_NO_ERROR; +} - ipk = [gNocSigner getIPK]; +CHIP_ERROR CHIPCommandBridge::SetUpStackWithSharedStorage(NSArray * productAttestationAuthorityCertificates) +{ + __auto_type * factory = [MTRDeviceControllerFactory sharedInstance]; + VerifyOrReturnError(nil != factory, CHIP_ERROR_INTERNAL, ChipLogError(chipTool, "Controller factory is nil")); + + auto factoryParams = [[MTRDeviceControllerFactoryParams alloc] initWithStorage:storage]; + factoryParams.shouldStartServer = YES; + factoryParams.otaProviderDelegate = mOTADelegate; + factoryParams.productAttestationAuthorityCertificates = productAttestationAuthorityCertificates; + + NSError * error; + auto started = [factory startControllerFactory:factoryParams error:&error]; + VerifyOrReturnError(started, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Controller factory startup failed")); + + __auto_type * certificateIssuer = [CertificateIssuer sharedInstance]; constexpr const char * identities[] = { kIdentityAlpha, kIdentityBeta, kIdentityGamma }; std::string commissionerName = mCommissionerName.HasValue() ? mCommissionerName.Value() : kIdentityAlpha; for (size_t i = 0; i < ArraySize(identities); ++i) { - auto controllerParams = [[MTRDeviceControllerStartupParams alloc] initWithIPK:ipk fabricID:@(i + 1) nocSigner:gNocSigner]; + __auto_type * fabricId = @(i + 1); + NSNumber * nodeId = nil; + __auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:certificateIssuer.ipk + fabricID:fabricId + nocSigner:certificateIssuer.signingKey]; if (commissionerName.compare(identities[i]) == 0 && mCommissionerNodeId.HasValue()) { - controllerParams.nodeId = @(mCommissionerNodeId.Value()); + params.nodeId = @(mCommissionerNodeId.Value()); } - // We're not sure whether we're creating a new fabric or using an - // existing one, so just try both. - auto controller = [factory createControllerOnExistingFabric:controllerParams error:&error]; + + params.nodeId = nodeId; + + // We're not sure whether we're creating a new fabric or using an existing one, so just try both. + auto controller = [factory createControllerOnExistingFabric:params error:&error]; if (controller == nil) { // Maybe we didn't have this fabric yet. - controllerParams.vendorID = @(mCommissionerVendorId.ValueOr(chip::VendorId::TestVendor1)); - controller = [factory createControllerOnNewFabric:controllerParams error:&error]; + params.vendorID = @(mCommissionerVendorId.ValueOr(chip::VendorId::TestVendor1)); + controller = [factory createControllerOnNewFabric:params error:&error]; } - if (controller == nil) { - ChipLogError(chipTool, "Controller startup failure."); - return MTRErrorToCHIPErrorCode(error); - } - + VerifyOrReturnError(nil != controller, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Controller startup failure: %@", error)); mControllers[identities[i]] = controller; } @@ -197,11 +249,29 @@ kIdentityBeta, kIdentityGamma); chipDie(); } + mCurrentIdentity = name; mCurrentController = mControllers[name]; } MTRDeviceController * CHIPCommandBridge::CurrentCommissioner() { return mCurrentController; } +NSNumber * CHIPCommandBridge::CurrentCommissionerFabricId() +{ + if (mCurrentIdentity.compare(kIdentityAlpha) == 0) { + return @(1); + } else if (mCurrentIdentity.compare(kIdentityBeta) == 0) { + return @(2); + } else if (mCurrentIdentity.compare(kIdentityGamma) == 0) { + return @(3); + } else { + ChipLogError(chipTool, "Unknown commissioner name: %s. Supported names are [%s, %s, %s]", mCurrentIdentity.c_str(), kIdentityAlpha, + kIdentityBeta, kIdentityGamma); + chipDie(); + } + + return @(0); // This should never happens. +} + MTRDeviceController * CHIPCommandBridge::GetCommissioner(const char * identity) { return mControllers[identity]; } MTRBaseDevice * CHIPCommandBridge::BaseDeviceWithNodeId(chip::NodeId nodeId) @@ -223,15 +293,25 @@ { StopCommissioners(); - auto factory = [MTRDeviceControllerFactory sharedInstance]; - NSData * ipk = [gNocSigner getIPK]; + if (sUseSharedStorage) { + auto factory = [MTRDeviceControllerFactory sharedInstance]; - constexpr const char * identities[] = { kIdentityAlpha, kIdentityBeta, kIdentityGamma }; - for (size_t i = 0; i < ArraySize(identities); ++i) { - auto controllerParams = [[MTRDeviceControllerStartupParams alloc] initWithIPK:ipk fabricID:@(i + 1) nocSigner:gNocSigner]; + constexpr const char * identities[] = { kIdentityAlpha, kIdentityBeta, kIdentityGamma }; + for (size_t i = 0; i < ArraySize(identities); ++i) { + __auto_type * certificateIssuer = [CertificateIssuer sharedInstance]; + auto controllerParams = [[MTRDeviceControllerStartupParams alloc] initWithIPK:certificateIssuer.ipk fabricID:@(i + 1) nocSigner:certificateIssuer.signingKey]; - auto controller = [factory createControllerOnExistingFabric:controllerParams error:nil]; - mControllers[identities[i]] = controller; + auto controller = [factory createControllerOnExistingFabric:controllerParams error:nil]; + mControllers[identities[i]] = controller; + } + } else { + NSArray * productAttestationAuthorityCertificates = nil; + ReturnOnFailure(GetPAACertsFromFolder(&productAttestationAuthorityCertificates)); + if ([productAttestationAuthorityCertificates count] == 0) { + productAttestationAuthorityCertificates = nil; + } + + ReturnOnFailure(SetUpStackWithPerControllerStorage(productAttestationAuthorityCertificates)); } } diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.h b/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.h index d5f743d57673c5..1da1b6b105f917 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.h +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.h @@ -1,8 +1,28 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 +extern NSString * const kDarwinFrameworkToolCertificatesDomain; + @interface CHIPToolPersistentStorageDelegate : NSObject - (nullable NSData *)storageDataForKey:(NSString *)key; - (BOOL)setStorageData:(NSData *)value forKey:(NSString *)key; diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.mm index 7cbdce85006375..3ec3dda55e1b05 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandStorageDelegate.mm @@ -1,89 +1,70 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + #include "CHIPCommandStorageDelegate.h" #import -#define LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE 0 - -NSString * const kCHIPToolDefaultsDomain = @"com.apple.chiptool"; +#import "PreferencesStorage.h" -id MTRGetDomainValueForKey(NSString * domain, NSString * key) -{ - id value = (id) CFBridgingRelease(CFPreferencesCopyAppValue((CFStringRef) key, (CFStringRef) domain)); - if (value) { - return value; - } - return nil; -} +NSString * const kDarwinFrameworkToolCertificatesDomain = @"com.apple.chiptool"; -BOOL MTRSetDomainValueForKey(NSString * domain, NSString * key, id value) -{ - CFPreferencesSetAppValue((CFStringRef) key, (__bridge CFPropertyListRef _Nullable)(value), (CFStringRef) domain); - return CFPreferencesAppSynchronize((CFStringRef) domain) == true; -} +@interface CHIPToolPersistentStorageDelegate () +@property (nonatomic, readonly) PreferencesStorage * storage; +@end -BOOL MTRRemoveDomainValueForKey(NSString * domain, NSString * key) -{ - CFPreferencesSetAppValue((CFStringRef) key, nullptr, (CFStringRef) domain); - return CFPreferencesAppSynchronize((CFStringRef) domain) == true; -} +@implementation CHIPToolPersistentStorageDelegate -id CHIPGetDomainKeyList(NSString * domain) +- (instancetype)init { - id value - = (id) CFBridgingRelease(CFPreferencesCopyKeyList((CFStringRef) domain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)); - if (value) { - return value; + if (!(self = [super init])) { + return nil; } - return nil; -} -BOOL CHIPClearAllDomain(NSString * domain) -{ - - NSArray * allKeys = CHIPGetDomainKeyList(domain); -#if LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE - NSLog(@"Removing keys: %@ %@", allKeys, domain); -#endif - for (id key in allKeys) { -#if LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE - NSLog(@"Removing key: %@", key); -#endif - if (!MTRRemoveDomainValueForKey(domain, (NSString *) key)) { - return NO; - } - } - return YES; + _storage = [[PreferencesStorage alloc] initWithDomain:kDarwinFrameworkToolCertificatesDomain]; + return self; } -@implementation CHIPToolPersistentStorageDelegate - - (BOOL)deleteAllStorage { - return CHIPClearAllDomain(kCHIPToolDefaultsDomain); + return [_storage reset]; } // MARK: CHIPPersistentStorageDelegate - (nullable NSData *)storageDataForKey:(NSString *)key { - NSData * value = MTRGetDomainValueForKey(kCHIPToolDefaultsDomain, key); -#if LOG_DEBUG_PERSISTENT_STORAGE_DELEGATE - NSLog(@"CHIPPersistentStorageDelegate Get Value for Key: %@, value %@", key, value); -#endif - return value; + return _storage[key]; } - (BOOL)setStorageData:(NSData *)value forKey:(NSString *)key { - return MTRSetDomainValueForKey(kCHIPToolDefaultsDomain, key, value); + _storage[key] = value; + return YES; } - (BOOL)removeStorageDataForKey:(NSString *)key { - if (MTRGetDomainValueForKey(kCHIPToolDefaultsDomain, key) == nil) { + if (_storage[key] == nil) { return NO; } - return MTRRemoveDomainValueForKey(kCHIPToolDefaultsDomain, key); + _storage[key] = nil; + return YES; } @end diff --git a/examples/darwin-framework-tool/commands/common/CertificateIssuer.h b/examples/darwin-framework-tool/commands/common/CertificateIssuer.h new file mode 100644 index 00000000000000..95257567c65839 --- /dev/null +++ b/examples/darwin-framework-tool/commands/common/CertificateIssuer.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 + +NS_ASSUME_NONNULL_BEGIN + +@interface CertificateIssuer : NSObject +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + ++ (CertificateIssuer *)sharedInstance; + +- (void)startWithStorage:(id)storage + error:(NSError * _Nullable * _Nullable)error; + +- (MTRCertificateDERBytes _Nullable)issueOperationalCertificateForNodeID:(NSNumber *)nodeID + fabricID:(NSNumber *)fabricID + error:(NSError * _Nullable * _Nullable)error; + +@property (nonatomic, readonly) MTRCertificateDERBytes rootCertificate; +@property (nonatomic, readonly) id signingKey; +@property (nonatomic, readonly) NSData * ipk; + +@property (nonatomic, nullable) NSNumber * fabricID; +@property (nonatomic, nullable) NSNumber * nextNodeID; +@property (nonatomic, readonly) BOOL shouldSkipAttestationCertificateValidation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/examples/darwin-framework-tool/commands/common/CertificateIssuer.mm b/examples/darwin-framework-tool/commands/common/CertificateIssuer.mm new file mode 100644 index 00000000000000..8c9f41ac03337c --- /dev/null +++ b/examples/darwin-framework-tool/commands/common/CertificateIssuer.mm @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 "CertificateIssuer.h" +#import "CHIPToolKeypair.h" + +#include + +@interface CertificateIssuer () +- (MTRCertificateDERBytes _Nullable)issueOperationalCertificateForNodeID:(NSNumber *)nodeID + fabricID:(NSNumber *)fabricID + publicKey:(SecKeyRef)publicKey + error:(NSError * _Nullable * _Nullable)error; +@end + +@implementation CertificateIssuer + ++ (CertificateIssuer *)sharedInstance +{ + static CertificateIssuer * certificateIssuer = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + certificateIssuer = [[CertificateIssuer alloc] init]; + }); + return certificateIssuer; +} + +- (instancetype)init +{ + if (!(self = [super init])) { + return nil; + } + + _rootCertificate = nil; + _ipk = nil; + _signingKey = nil; + _fabricID = nil; + _nextNodeID = nil; + _shouldSkipAttestationCertificateValidation = NO; + + return self; +} + +- (void)startWithStorage:(id)storage + error:(NSError * _Nullable * _Nullable)error +{ + __auto_type * signingKey = [[CHIPToolKeypair alloc] init]; + + auto err = [signingKey createOrLoadKeys:storage]; + if (CHIP_NO_ERROR != err) { + *error = [NSError errorWithDomain:@"Error" code:0 userInfo:@{ @"reason" : @"Error creating or loading keys" }]; + return; + } + + __auto_type * rootCertificate = [MTRCertificates createRootCertificate:signingKey issuerID:nil fabricID:nil error:error]; + if (nil == rootCertificate) { + *error = [NSError errorWithDomain:@"Error" code:0 userInfo:@{ @"reason" : @"Error creating root certificate" }]; + return; + } + + _rootCertificate = rootCertificate; + _signingKey = signingKey; + _ipk = [signingKey getIPK]; +} + +- (MTRCertificateDERBytes _Nullable)issueOperationalCertificateForNodeID:(NSNumber *)nodeID + fabricID:(NSNumber *)fabricID + error:(NSError * _Nullable * _Nullable)error +{ + __auto_type * publicKey = _signingKey.publicKey; + return [self issueOperationalCertificateForNodeID:nodeID fabricID:fabricID publicKey:publicKey error:error]; +} + +- (void)issueOperationalCertificateForRequest:(MTROperationalCSRInfo *)csrInfo + attestationInfo:(MTRDeviceAttestationInfo *)attestationInfo + controller:(MTRDeviceController *)controller + completion:(void (^)(MTROperationalCertificateChain * _Nullable info, + NSError * _Nullable error))completion +{ + NSError * error = nil; + + if (self.nextNodeID == nil) { + error = [NSError errorWithDomain:@"Error" code:0 userInfo:@{ @"reason" : @"nextNodeID is nil" }]; + completion(nil, error); + return; + } + + __auto_type * csr = csrInfo.csr; + __auto_type * rawPublicKey = [MTRCertificates publicKeyFromCSR:csr error:&error]; + if (error != nil) { + completion(nil, error); + return; + } + + NSDictionary * attributes = @{ + (__bridge NSString *) kSecAttrKeyType : (__bridge NSString *) kSecAttrKeyTypeECSECPrimeRandom, + (__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassPublic + }; + CFErrorRef keyCreationError = NULL; + SecKeyRef publicKey + = SecKeyCreateWithData((__bridge CFDataRef) rawPublicKey, (__bridge CFDictionaryRef) attributes, &keyCreationError); + + __auto_type * operationalCert = [self issueOperationalCertificateForNodeID:self.nextNodeID + fabricID:self.fabricID + publicKey:publicKey + error:&error]; + + // Release no-longer-needed key before we do anything else. + CFRelease(publicKey); + + if (error != nil) { + completion(nil, error); + return; + } + + __auto_type * certChain = [[MTROperationalCertificateChain alloc] initWithOperationalCertificate:operationalCert + intermediateCertificate:nil + rootCertificate:self.rootCertificate + adminSubject:nil]; + completion(certChain, nil); +} + +- (MTRCertificateDERBytes _Nullable)issueOperationalCertificateForNodeID:(NSNumber *)nodeID + fabricID:(NSNumber *)fabricID + publicKey:(SecKeyRef)publicKey + error:(NSError * _Nullable * _Nullable)error +{ + __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:self.signingKey + signingCertificate:self.rootCertificate + operationalPublicKey:publicKey + fabricID:fabricID + nodeID:nodeID + caseAuthenticatedTags:nil + error:error]; + if (error != nil) { + return nil; + } + + return operationalCert; +} + +@end diff --git a/examples/darwin-framework-tool/commands/common/ControllerStorage.h b/examples/darwin-framework-tool/commands/common/ControllerStorage.h new file mode 100644 index 00000000000000..72a67021b49f1e --- /dev/null +++ b/examples/darwin-framework-tool/commands/common/ControllerStorage.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kDarwinFrameworkToolControllerDomain; + +@interface ControllerStorage : NSObject +- (instancetype)initWithControllerID:(NSUUID *)controllerID; +@property (nonatomic, readonly) NSUUID * controllerID; + +- (nullable id)controller:(MTRDeviceController *)controller + valueForKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType; +- (BOOL)controller:(MTRDeviceController *)controller + storeValue:(id)value + forKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType; +- (BOOL)controller:(MTRDeviceController *)controller + removeValueForKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType; +- (NSDictionary> *)valuesForController:(MTRDeviceController *)controller securityLevel:(MTRStorageSecurityLevel)securityLevel sharingType:(MTRStorageSharingType)sharingType; +- (BOOL)controller:(MTRDeviceController *)controller storeValues:(NSDictionary> *)values securityLevel:(MTRStorageSecurityLevel)securityLevel sharingType:(MTRStorageSharingType)sharingType; +@end + +NS_ASSUME_NONNULL_END diff --git a/examples/darwin-framework-tool/commands/common/ControllerStorage.mm b/examples/darwin-framework-tool/commands/common/ControllerStorage.mm new file mode 100644 index 00000000000000..5f2d6b0a0e4c73 --- /dev/null +++ b/examples/darwin-framework-tool/commands/common/ControllerStorage.mm @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 "ControllerStorage.h" +#import "PreferencesStorage.h" + +#include + +NSString * const kDarwinFrameworkToolControllerDomain = @"com.apple.darwin-framework-tool.controller"; + +@interface ControllerStorage () +@property (nonatomic, readonly) PreferencesStorage * storage; +@end + +@implementation ControllerStorage +- (instancetype)initWithControllerID:(NSUUID *)controllerID +{ + if (!(self = [super init])) { + return nil; + } + + _storage = [[PreferencesStorage alloc] initWithDomain:kDarwinFrameworkToolControllerDomain]; + _controllerID = controllerID; + return self; +} + +- (nullable id)controller:(MTRDeviceController *)controller + valueForKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType +{ +#ifdef LOG_DEBUG_CONTROLLER_STORAGE + ChipLogError(chipTool, "Controller(%@) Storage - Get value for %@", controller, key); +#endif // LOG_DEBUG_CONTROLLER_STORAGE + + __auto_type * controllerKey = [NSString stringWithFormat:@"%@/%@", _controllerID, key]; + __auto_type * data = self.storage[controllerKey]; + if (data == nil) { + return data; + } + + NSError * error; + id value = [NSKeyedUnarchiver unarchivedObjectOfClasses:MTRDeviceControllerStorageClasses() fromData:data error:&error]; + return value; +} + +- (BOOL)controller:(MTRDeviceController *)controller + storeValue:(id)value + forKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType +{ +#ifdef LOG_DEBUG_CONTROLLER_STORAGE + ChipLogError(chipTool, "Controller(%@) Storage - Set value for %@", controller, key); +#endif // LOG_DEBUG_CONTROLLER_STORAGE + NSError * error; + NSData * data = [NSKeyedArchiver archivedDataWithRootObject:value requiringSecureCoding:YES error:&error]; + + __auto_type * controllerKey = [NSString stringWithFormat:@"%@/%@", _controllerID, key]; + self.storage[controllerKey] = data; + return YES; +} + +- (BOOL)controller:(MTRDeviceController *)controller + removeValueForKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType +{ +#ifdef LOG_DEBUG_CONTROLLER_STORAGE + ChipLogError(chipTool, "Controller(%@) Storage - Remove value for %@", controller, key); +#endif // LOG_DEBUG_CONTROLLER_STORAGE + + __auto_type * controllerKey = [NSString stringWithFormat:@"%@/%@", _controllerID, key]; + self.storage[controllerKey] = nil; + return YES; +} + +- (NSDictionary> *)valuesForController:(MTRDeviceController *)controller securityLevel:(MTRStorageSecurityLevel)securityLevel sharingType:(MTRStorageSharingType)sharingType +{ +#ifdef LOG_DEBUG_CONTROLLER_STORAGE + ChipLogError(chipTool, "Controller(%@) Storage - Get all values", controller); +#endif // LOG_DEBUG_CONTROLLER_STORAGE + + NSMutableDictionary * valuesToReturn = [NSMutableDictionary dictionary]; + for (NSString * controllerKey in self.storage) { + if (![controllerKey hasPrefix:[_controllerID UUIDString]]) { + continue; + } + __auto_type * key = [controllerKey stringByReplacingOccurrencesOfString:[_controllerID UUIDString] withString:@""]; + valuesToReturn[key] = [self controller:controller valueForKey:key securityLevel:securityLevel sharingType:sharingType]; + } + + if (!valuesToReturn.count) { + return nil; + } + + return valuesToReturn; +} + +- (BOOL)controller:(MTRDeviceController *)controller storeValues:(NSDictionary> *)values securityLevel:(MTRStorageSecurityLevel)securityLevel sharingType:(MTRStorageSharingType)sharingType +{ +#ifdef LOG_DEBUG_CONTROLLER_STORAGE + ChipLogError(chipTool, "Controller(%@) Storage - store values", controller); +#endif // LOG_DEBUG_CONTROLLER_STORAGE + + for (NSString * controllerKey in values) { + if (![controllerKey hasPrefix:[_controllerID UUIDString]]) { + continue; + } + __auto_type * key = [controllerKey stringByReplacingOccurrencesOfString:[_controllerID UUIDString] withString:@""]; + [self controller:controller storeValue:values[key] forKey:key securityLevel:securityLevel sharingType:sharingType]; + } + + return YES; +} + +@end diff --git a/examples/darwin-framework-tool/commands/common/PreferencesStorage.h b/examples/darwin-framework-tool/commands/common/PreferencesStorage.h new file mode 100644 index 00000000000000..85c12032766f42 --- /dev/null +++ b/examples/darwin-framework-tool/commands/common/PreferencesStorage.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 + +@interface PreferencesStorage : NSObject + +@property (nonatomic, strong) NSString * domain; + +- (instancetype)initWithDomain:(NSString *)domain; +- (NSData *)objectForKeyedSubscript:(NSString *)key; +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; +- (NSArray *)allKeys; +- (bool)reset; +- (void)print; + +@end diff --git a/examples/darwin-framework-tool/commands/common/PreferencesStorage.mm b/examples/darwin-framework-tool/commands/common/PreferencesStorage.mm new file mode 100644 index 00000000000000..e7ddba1313d450 --- /dev/null +++ b/examples/darwin-framework-tool/commands/common/PreferencesStorage.mm @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 "PreferencesStorage.h" + +@implementation PreferencesStorage +- (instancetype)initWithDomain:(NSString *)domain +{ + self = [super init]; + if (self) { + _domain = domain; + } + + return self; +} + +- (NSData *)objectForKeyedSubscript:(NSString *)key +{ + __auto_type domainRef = (__bridge CFStringRef) self.domain; + __auto_type keyRef = (__bridge CFStringRef) key; + __auto_type value = CFPreferencesCopyAppValue(keyRef, domainRef); + if (value) { + id obj = (__bridge_transfer id) value; + return obj; + } + return nil; +} + +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key +{ + __auto_type domainRef = (__bridge CFStringRef) self.domain; + __auto_type keyRef = (__bridge CFStringRef) key; + __auto_type value = (__bridge CFPropertyListRef) obj; + + CFPreferencesSetAppValue(keyRef, value, domainRef); + CFPreferencesAppSynchronize(domainRef); +} + +- (NSArray *)allKeys +{ + __auto_type domainRef = (__bridge CFStringRef) self.domain; + __auto_type keys = CFPreferencesCopyKeyList(domainRef, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + + if (!keys) { + return @[]; + } + + return (__bridge_transfer NSArray *) keys; +} + +- (bool)reset +{ + __auto_type * keys = [self allKeys]; + __auto_type domainRef = (__bridge CFStringRef) self.domain; + + for (NSString * key in keys) { + __auto_type keyRef = (__bridge CFStringRef) key; + CFPreferencesSetAppValue(keyRef, NULL, domainRef); + } + + return CFPreferencesAppSynchronize(domainRef); +} + +- (void)print +{ + NSLog(@"%@:", self.domain); + NSArray * keys = [self allKeys]; + for (NSString * key in keys) { + __auto_type * data = [self objectForKeyedSubscript:key]; + NSLog(@" * %@: %@", key, data); + } +} + +#pragma mark - NSFastEnumeration + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id _Nullable __unsafe_unretained[])buffer count:(NSUInteger)len +{ + __auto_type * keys = [self allKeys]; + if (state->state >= keys.count) { + return 0; + } + + state->itemsPtr = buffer; + state->mutationsPtr = &state->extra[0]; + + NSUInteger count = 0; + while (state->state < keys.count && count < len) { + buffer[count] = keys[state->state]; + state->state++; + count++; + } + return count; +} + +@end diff --git a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm index 1a060819b5700e..3ec4aee9e2e1e2 100644 --- a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm @@ -19,6 +19,7 @@ #import #include "../common/CHIPCommandBridge.h" +#include "../common/CertificateIssuer.h" #include "DeviceControllerDelegateBridge.h" #include "PairingCommandBridge.h" #include @@ -52,6 +53,12 @@ - (void)deviceAttestationCompletedForController:(MTRDeviceController *)controlle [deviceControllerDelegate setCommandBridge:this]; [deviceControllerDelegate setDeviceID:mNodeId]; + // With per-controller storage, the certificate issuer creates the operational certificate. + // When using shared storage, this step is a no-op. + auto * certificateIssuer = [CertificateIssuer sharedInstance]; + certificateIssuer.nextNodeID = @(mNodeId); + certificateIssuer.fabricID = CurrentCommissionerFabricId(); + if (mCommissioningType != CommissioningType::None) { MTRCommissioningParameters * params = [[MTRCommissioningParameters alloc] init]; switch (mCommissioningType) { diff --git a/examples/darwin-framework-tool/commands/storage/Commands.h b/examples/darwin-framework-tool/commands/storage/Commands.h index 65534272b81ca5..983fb22f4604b6 100644 --- a/examples/darwin-framework-tool/commands/storage/Commands.h +++ b/examples/darwin-framework-tool/commands/storage/Commands.h @@ -25,7 +25,10 @@ void registerCommandsStorage(Commands & commands) { const char * clusterName = "storage"; - commands_list clusterCommands = { make_unique() }; + commands_list clusterCommands = { + make_unique(), // + make_unique(), // + }; commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for managing persistent data stored by darwin-framework-tool."); diff --git a/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.h b/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.h index c2abddf18d0498..8c3ed69184d742 100644 --- a/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.h +++ b/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.h @@ -29,3 +29,11 @@ class StorageClearAll : public Command CHIP_ERROR Run() override; }; + +class StorageViewAll : public Command +{ +public: + StorageViewAll() : Command("view-all") {} + + CHIP_ERROR Run() override; +}; diff --git a/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.mm b/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.mm index e0c1b18ec890dc..007d2821bda5a3 100644 --- a/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.mm +++ b/examples/darwin-framework-tool/commands/storage/StorageManagementCommand.mm @@ -17,18 +17,43 @@ */ #include "../common/CHIPCommandStorageDelegate.h" +#include "../common/ControllerStorage.h" +#include "../common/PreferencesStorage.h" #include "StorageManagementCommand.h" #import -static CHIPToolPersistentStorageDelegate * storage = nil; +namespace { +NSArray * GetDomains() +{ + __auto_type * domains = @[ + kDarwinFrameworkToolCertificatesDomain, + kDarwinFrameworkToolControllerDomain + ]; + + return domains; +} +} CHIP_ERROR StorageClearAll::Run() { - storage = [[CHIPToolPersistentStorageDelegate alloc] init]; - if (![storage deleteAllStorage]) { - return CHIP_ERROR_INTERNAL; + __auto_type * domains = GetDomains(); + for (NSString * domain in domains) { + __auto_type * storage = [[PreferencesStorage alloc] initWithDomain:domain]; + VerifyOrReturnError([storage reset], CHIP_ERROR_INTERNAL); } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR StorageViewAll::Run() +{ + __auto_type * domains = GetDomains(); + for (NSString * domain in domains) { + __auto_type * storage = [[PreferencesStorage alloc] initWithDomain:domain]; + [storage print]; + } + return CHIP_NO_ERROR; } diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 488bd32967453e..5daf7f245d9976 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -334,6 +334,12 @@ B43B39EC2CB859A5006AA284 /* DumpMemoryGraphCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E52CB859A5006AA284 /* DumpMemoryGraphCommand.h */; }; B43B39ED2CB859A5006AA284 /* Commands.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E42CB859A5006AA284 /* Commands.h */; }; B43B39EE2CB859A5006AA284 /* LeaksTool.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E72CB859A5006AA284 /* LeaksTool.h */; }; + B43B39F52CB99090006AA284 /* ControllerStorage.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39F22CB99090006AA284 /* ControllerStorage.mm */; }; + B43B39F62CB99090006AA284 /* CertificateIssuer.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39F02CB99090006AA284 /* CertificateIssuer.mm */; }; + B43B39F72CB99090006AA284 /* PreferencesStorage.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39F42CB99090006AA284 /* PreferencesStorage.mm */; }; + B43B39F82CB99090006AA284 /* CertificateIssuer.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39EF2CB99090006AA284 /* CertificateIssuer.h */; }; + B43B39F92CB99090006AA284 /* PreferencesStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39F32CB99090006AA284 /* PreferencesStorage.h */; }; + B43B39FA2CB99090006AA284 /* ControllerStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39F12CB99090006AA284 /* ControllerStorage.h */; }; B45373AA2A9FE73400807602 /* WebSocketServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B45373A92A9FE73400807602 /* WebSocketServer.cpp */; }; B45373BD2A9FEA9100807602 /* service.c in Sources */ = {isa = PBXBuildFile; fileRef = B45373B22A9FEA9000807602 /* service.c */; settings = {COMPILER_FLAGS = "-Wno-error -Wno-unreachable-code -Wno-conversion -Wno-format-nonliteral"; }; }; B45373BE2A9FEA9100807602 /* network.c in Sources */ = {isa = PBXBuildFile; fileRef = B45373B32A9FEA9000807602 /* network.c */; settings = {COMPILER_FLAGS = "-Wno-error -Wno-unreachable-code -Wno-conversion -Wno-format-nonliteral"; }; }; @@ -785,6 +791,12 @@ B43B39E62CB859A5006AA284 /* DumpMemoryGraphCommand.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DumpMemoryGraphCommand.mm; sourceTree = ""; }; B43B39E72CB859A5006AA284 /* LeaksTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LeaksTool.h; sourceTree = ""; }; B43B39E82CB859A5006AA284 /* LeaksTool.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LeaksTool.mm; sourceTree = ""; }; + B43B39EF2CB99090006AA284 /* CertificateIssuer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CertificateIssuer.h; sourceTree = ""; }; + B43B39F02CB99090006AA284 /* CertificateIssuer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CertificateIssuer.mm; sourceTree = ""; }; + B43B39F12CB99090006AA284 /* ControllerStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ControllerStorage.h; sourceTree = ""; }; + B43B39F22CB99090006AA284 /* ControllerStorage.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ControllerStorage.mm; sourceTree = ""; }; + B43B39F32CB99090006AA284 /* PreferencesStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PreferencesStorage.h; sourceTree = ""; }; + B43B39F42CB99090006AA284 /* PreferencesStorage.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PreferencesStorage.mm; sourceTree = ""; }; B45373A92A9FE73400807602 /* WebSocketServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketServer.cpp; sourceTree = ""; }; B45373B22A9FEA9000807602 /* service.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = service.c; path = "repo/lib/core-net/service.c"; sourceTree = ""; }; B45373B32A9FEA9000807602 /* network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = network.c; path = "repo/lib/core-net/network.c"; sourceTree = ""; }; @@ -987,6 +999,12 @@ 037C3D9B2991BD4F00B7EEE2 /* common */ = { isa = PBXGroup; children = ( + B43B39EF2CB99090006AA284 /* CertificateIssuer.h */, + B43B39F02CB99090006AA284 /* CertificateIssuer.mm */, + B43B39F12CB99090006AA284 /* ControllerStorage.h */, + B43B39F22CB99090006AA284 /* ControllerStorage.mm */, + B43B39F32CB99090006AA284 /* PreferencesStorage.h */, + B43B39F42CB99090006AA284 /* PreferencesStorage.mm */, B4E262132AA0C7A300DBA5BC /* RemoteDataModelLogger.h */, B4E262122AA0C7A300DBA5BC /* RemoteDataModelLogger.mm */, 037C3D9C2991BD4F00B7EEE2 /* CHIPCommandBridge.mm */, @@ -1632,6 +1650,9 @@ B4FCD5712B603A6300832859 /* DownloadLogCommand.h in Headers */, 037C3DC32991BD5100B7EEE2 /* Commands.h in Headers */, B4F773CA2CB54B61008C6B23 /* LeakChecker.h in Headers */, + B43B39F82CB99090006AA284 /* CertificateIssuer.h in Headers */, + B43B39F92CB99090006AA284 /* PreferencesStorage.h in Headers */, + B43B39FA2CB99090006AA284 /* ControllerStorage.h in Headers */, 037C3DB82991BD5000B7EEE2 /* ClusterCommandBridge.h in Headers */, 037C3DC82991BD5100B7EEE2 /* CHIPToolKeypair.h in Headers */, 037C3DB52991BD5000B7EEE2 /* WriteAttributeCommandBridge.h in Headers */, @@ -1971,6 +1992,9 @@ B45373DF2A9FEB6F00807602 /* system.c in Sources */, B45373FC2A9FEC4F00807602 /* unix-caps.c in Sources */, B45373FE2A9FEC4F00807602 /* unix-fds.c in Sources */, + B43B39F52CB99090006AA284 /* ControllerStorage.mm in Sources */, + B43B39F62CB99090006AA284 /* CertificateIssuer.mm in Sources */, + B43B39F72CB99090006AA284 /* PreferencesStorage.mm in Sources */, B43B39EA2CB859A5006AA284 /* DumpMemoryGraphCommand.mm in Sources */, B43B39EB2CB859A5006AA284 /* LeaksTool.mm in Sources */, B45374002A9FEC4F00807602 /* unix-init.c in Sources */,