diff --git a/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm b/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm index 22fa5258219d21..fc1072b3cc789e 100644 --- a/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm +++ b/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm @@ -55,10 +55,9 @@ constexpr const char * identities[] = { kIdentityAlpha, kIdentityBeta, kIdentityGamma }; for (size_t i = 0; i < ArraySize(identities); ++i) { - auto controllerParams = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:nocSigner]; + auto controllerParams = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:nocSigner ipk:ipk]; controllerParams.vendorId = chip::VendorId::TestVendor1; controllerParams.fabricId = i + 1; - controllerParams.ipk = ipk; // We're not sure whether we're creating a new fabric or using an // existing one, so just try both. diff --git a/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj b/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj index 8efc153410d354..6c115bb8e5cd7f 100644 --- a/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj +++ b/src/darwin/CHIPTool/CHIPTool.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 2C21071525D1A8F200DDA4AD /* MultiAdminViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C21071325D1A8F200DDA4AD /* MultiAdminViewController.m */; }; 2C460C2425D7594B000512D6 /* DeviceSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C460C2325D7594B000512D6 /* DeviceSelector.m */; }; 2C460C3225D97CB3000512D6 /* UnpairDevicesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C460C3025D97CB3000512D6 /* UnpairDevicesViewController.m */; }; + 51C8E3FB28261DCF00D47D00 /* FabricKeys.m in Sources */ = {isa = PBXBuildFile; fileRef = 51C8E3FA28261DCF00D47D00 /* FabricKeys.m */; }; 991DC091247747F500C13860 /* EnumerateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 991DC090247747F500C13860 /* EnumerateViewController.m */; }; 997A639C253F93F7005C64E6 /* CHIP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 997A639B253F93F7005C64E6 /* CHIP.framework */; }; 997A639D253F93F7005C64E6 /* CHIP.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 997A639B253F93F7005C64E6 /* CHIP.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -62,6 +63,8 @@ 2C460C2325D7594B000512D6 /* DeviceSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceSelector.m; sourceTree = ""; }; 2C460C3025D97CB3000512D6 /* UnpairDevicesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UnpairDevicesViewController.m; sourceTree = ""; }; 2C460C3125D97CB3000512D6 /* UnpairDevicesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnpairDevicesViewController.h; sourceTree = ""; }; + 51C8E3F928261DCF00D47D00 /* FabricKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FabricKeys.h; sourceTree = ""; }; + 51C8E3FA28261DCF00D47D00 /* FabricKeys.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FabricKeys.m; sourceTree = ""; }; 991DC08F247747F500C13860 /* EnumerateViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EnumerateViewController.h; sourceTree = ""; }; 991DC090247747F500C13860 /* EnumerateViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EnumerateViewController.m; sourceTree = ""; }; 997A639B253F93F7005C64E6 /* CHIP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CHIP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -245,6 +248,8 @@ B232D8C0251A0EE200792CB4 /* Framework Helpers */ = { isa = PBXGroup; children = ( + 51C8E3F928261DCF00D47D00 /* FabricKeys.h */, + 51C8E3FA28261DCF00D47D00 /* FabricKeys.m */, B2946A9924C9A7BF005C87D0 /* DefaultsUtils.h */, B2946A9A24C9A7BF005C87D0 /* DefaultsUtils.m */, ); @@ -401,6 +406,7 @@ B243A6692513A73600E56FEA /* RootViewController.m in Sources */, B204A632244E1D0700C7C0E1 /* main.m in Sources */, B204A624244E1D0600C7C0E1 /* SceneDelegate.m in Sources */, + 51C8E3FB28261DCF00D47D00 /* FabricKeys.m in Sources */, B2946A4224C99D53005C87D0 /* WiFiViewController.m in Sources */, 0CA0E0CF248599BB009087B9 /* OnOffViewController.m in Sources */, ); diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m index ac6bc504611561..6538a0f89a5251 100644 --- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m @@ -16,6 +16,7 @@ */ #import "DefaultsUtils.h" +#import "FabricKeys.h" NSString * const kCHIPToolDefaultsDomain = @"com.apple.chiptool"; NSString * const kNetworkSSIDDefaultsKey = @"networkSSID"; @@ -81,7 +82,12 @@ void CHIPSetNextAvailableDeviceID(uint64_t id) return; } - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:nil]; + __auto_type * keys = [[FabricKeys alloc] init]; + if (keys == nil) { + return; + } + + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:keys ipk:keys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; @@ -98,11 +104,17 @@ void CHIPSetNextAvailableDeviceID(uint64_t id) CHIPDeviceController * CHIPRestartController(CHIPDeviceController * controller) { + __auto_type * keys = [[FabricKeys alloc] init]; + if (keys == nil) { + NSLog(@"No keys, can't restart controller"); + return controller; + } + NSLog(@"Shutting down the stack"); [controller shutdown]; NSLog(@"Starting up the stack"); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:nil]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:keys ipk:keys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.h b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.h new file mode 100644 index 00000000000000..2d60189ad76241 --- /dev/null +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.h @@ -0,0 +1,35 @@ +/** + * 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. + */ + +#pragma once + +#import +#import + +/** + * Management of the CA key and IPK for our fabric. + */ + +NS_ASSUME_NONNULL_BEGIN + +@interface FabricKeys : NSObject + +@property (readonly, nonatomic, strong) NSData * ipk; + +- (instancetype)init; +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.m b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.m new file mode 100644 index 00000000000000..6b0eadd9f503a3 --- /dev/null +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.m @@ -0,0 +1,237 @@ +/** + * 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 "FabricKeys.h" + +#import + +@interface FabricKeys () +@property (readonly) SecKeyRef privateKey; +@property (readonly) SecKeyRef publicKey; +@end + +static const NSString * kCHIPIPKKeyChainLabel = @"matter-tool.nodeopcerts.IPK:0"; +static const NSString * kCHIPCAKeyChainLabel = @"matter-tool.nodeopcerts.CA:0"; + +@implementation FabricKeys + ++ (NSDictionary *)ipkParams +{ + return @{ + (__bridge NSString *) kSecClass : (__bridge NSString *) kSecClassKey, + (__bridge NSString *) kSecAttrApplicationLabel : kCHIPIPKKeyChainLabel, + (__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassSymmetric, + }; +} + ++ (NSData *)loadIPK +{ + NSMutableDictionary * query = [[NSMutableDictionary alloc] initWithDictionary:[FabricKeys ipkParams]]; + query[(__bridge NSString *) kSecReturnData] = @(YES); + + // The CFDataRef we get from SecItemCopyMatching allocates its buffer in a + // way that zeroes it when deallocated. + CFDataRef keyDataRef; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, (CFTypeRef *) &keyDataRef); + if (status != errSecSuccess || keyDataRef == nil) { + NSLog(@"Did not find IPK in the keychain"); + return nil; + } + + NSLog(@"Found an existing IPK in the keychain"); + NSData * keyData = CFBridgingRelease(keyDataRef); + + return [[NSData alloc] initWithBase64EncodedData:keyData options:0]; +} + ++ (NSData *)generateIPK +{ + NSMutableDictionary * query = [[NSMutableDictionary alloc] initWithDictionary:[FabricKeys ipkParams]]; + + // First, delete any existing item, since otherwise trying to add the new item + // later will fail. Ignore delete failure, since we might not have had the + // item at all. + SecItemDelete((__bridge CFDictionaryRef) query); + + // Generate an IPK. For now, hardcoded to 16 bytes until the + // framework exposes this constant. + const size_t ipk_size = 16; + NSMutableData * ipkData = [NSMutableData dataWithLength:ipk_size]; + if (ipkData == nil) { + return nil; + } + + int status = SecRandomCopyBytes(kSecRandomDefault, ipk_size, [ipkData mutableBytes]); + if (status != errSecSuccess) { + NSLog(@"Failed to generate IPK : %d", status); + return nil; + } + + query[(__bridge NSString *) kSecValueData] = [ipkData base64EncodedDataWithOptions:0]; + + OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef) query, NULL); + if (addStatus != errSecSuccess) { + NSLog(@"Failed to store IPK : %d", addStatus); + return nil; + } + + return ipkData; +} + ++ (NSDictionary *)privateKeyParams +{ + return @{ + (__bridge NSString *) kSecClass : (__bridge NSString *) kSecClassKey, + (__bridge NSString *) kSecAttrApplicationLabel : kCHIPCAKeyChainLabel, + // We're storing a base-64 encoding of some opaque thing that represents + // our keypair. It's not really a public or private key; claim it's a + // symmetric key. + (__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassSymmetric, + }; +} + ++ (NSDictionary *)privateKeyCreationParams +{ + // For now harcoded to 256 bits until the framework exposes this constant. + const size_t keySizeInBits = 256; + + return @{ + (__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassPrivate, + (__bridge NSString *) kSecAttrKeyType : (__bridge NSNumber *) kSecAttrKeyTypeECSECPrimeRandom, + (__bridge NSString *) kSecAttrKeySizeInBits : @(keySizeInBits), + (__bridge NSString *) kSecAttrIsPermanent : @(NO) + }; +} + ++ (SecKeyRef)loadCAPrivateKey +{ + NSMutableDictionary * query = [[NSMutableDictionary alloc] initWithDictionary:[FabricKeys privateKeyParams]]; + query[(__bridge NSString *) kSecReturnData] = @(YES); + + // The CFDataRef we get from SecItemCopyMatching allocates its buffer in a + // way that zeroes it when deallocated. + CFDataRef keyDataRef; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, (CFTypeRef *) &keyDataRef); + if (status != errSecSuccess || keyDataRef == nil) { + NSLog(@"Did not find CA key in the keychain"); + return NULL; + } + + NSLog(@"Found an existing CA key in the keychain"); + NSData * encodedKey = CFBridgingRelease(keyDataRef); + + NSData * keyData = [[NSData alloc] initWithBase64EncodedData:encodedKey options:0]; + if (keyData == nil) { + NSLog(@"Could not base64-decode CA key"); + return NULL; + } + + CFErrorRef error = NULL; + SecKeyRef key = SecKeyCreateWithData( + (__bridge CFDataRef) keyData, (__bridge CFDictionaryRef)[FabricKeys privateKeyCreationParams], &error); + if (error) { + NSLog(@"Could not reconstruct private key %@", (__bridge NSError *) error); + return NULL; + } + + return key; +} + ++ (SecKeyRef)generateCAPrivateKey +{ + NSMutableDictionary * query = [[NSMutableDictionary alloc] initWithDictionary:[FabricKeys privateKeyParams]]; + + // First, delete any existing item, since otherwise trying to add the new item + // later will fail. Ignore delete failure, since we might not have had the + // item at all. + SecItemDelete((__bridge CFDictionaryRef) query); + + CFErrorRef error = NULL; + SecKeyRef key = SecKeyCreateRandomKey((__bridge CFDictionaryRef)[FabricKeys privateKeyCreationParams], &error); + if (error) { + NSLog(@"Could not generate private key: %@", (__bridge NSError *) error); + return NULL; + } + + NSData * keyData = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(key, &error); + if (error) { + NSLog(@"Could not get key external representation: %@", (__bridge NSError *) error); + CFRelease(key); + return NULL; + } + + query[(__bridge NSString *) kSecValueData] = [keyData base64EncodedDataWithOptions:0]; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef) query, NULL); + if (status != errSecSuccess) { + NSLog(@"Failed to store private key : %d", status); + CFRelease(key); + return NULL; + } + + return key; +} + +- (instancetype)init +{ + if (!(self = [super init])) { + return nil; + } + + if (!(_ipk = [FabricKeys loadIPK])) { + if (!(_ipk = [FabricKeys generateIPK])) { + return nil; + } + } + + if (!(_privateKey = [FabricKeys loadCAPrivateKey])) { + if (!(_privateKey = [FabricKeys generateCAPrivateKey])) { + return nil; + } + } + + _publicKey = SecKeyCopyPublicKey(_privateKey); + return self; +} + +- (NSData *)ECDSA_sign_hash:(NSData *)hash +{ + CFErrorRef error = NULL; + CFDataRef outData + = SecKeyCreateSignature(_privateKey, kSecKeyAlgorithmECDSASignatureRFC4754, (__bridge CFDataRef) hash, &error); + + if (error != noErr) { + NSLog(@"Failed to sign cert: %@", (__bridge NSError *) error); + } + return (__bridge_transfer NSData *) outData; +} + +- (SecKeyRef)pubkey +{ + return self.publicKey; +} + +- (void)dealloc +{ + if (_publicKey) { + CFRelease(_publicKey); + } + + if (_privateKey) { + CFRelease(_privateKey); + } +} +@end diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index c59b4def0b3753..b3dc9ca8345abd 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -168,11 +168,9 @@ - (BOOL)startup:(CHIPDeviceControllerStartupParams *)startupParams CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; // create a CHIPP256KeypairBridge here and pass it to the operationalCredentialsDelegate - std::unique_ptr nativeBridge; - if (startupParams.rootCAKeypair != nil) { - _keypairBridge.Init(startupParams.rootCAKeypair); - nativeBridge.reset(new chip::Crypto::CHIPP256KeypairNativeBridge(_keypairBridge)); - } + _keypairBridge.Init(startupParams.rootCAKeypair); + auto nativeBridge = std::make_unique(_keypairBridge); + errorCode = _operationalCredentialsDelegate->init(_factory.storageDelegateBridge, std::move(nativeBridge), startupParams.ipk); if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorOperationalCredentialsInit]) { @@ -723,18 +721,18 @@ - (CHIP_ERROR)isRunningOnFabric:(chip::FabricInfo *)fabric isRunning:(BOOL *)isR @implementation CHIPDeviceControllerStartupParams -- (instancetype)initWithKeypair:(_Nullable id)rootCAKeypair +- (instancetype)initWithKeypair:(id)rootCAKeypair ipk:(NSData *)ipk { if (!(self = [super init])) { return nil; } _rootCAKeypair = rootCAKeypair; + _ipk = ipk; // Set various invalid values. _vendorId = chip::VendorId::Common; _fabricId = chip::kUndefinedFabricId; - _ipk = nil; return self; } diff --git a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h index a5156b28d5cad5..05664812e4c086 100644 --- a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h +++ b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h @@ -37,14 +37,7 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC ~CHIPOperationalCredentialsDelegate() {} - /** - * If nocSigner is not provided (is null), a keypair will be loaded from the - * keychain, or generated if nothing is present in the keychain. - * - * If ipk is not provided (is nil), an IPK will be loaded from the keychain, - * or generated if nothing is present in the keychain. - */ - CHIP_ERROR init(CHIPPersistentStorageDelegateBridge * storage, ChipP256KeypairPtr nocSigner, NSData * _Nullable ipk); + CHIP_ERROR init(CHIPPersistentStorageDelegateBridge * storage, ChipP256KeypairPtr nocSigner, NSData * ipk); CHIP_ERROR GenerateNOCChain(const chip::ByteSpan & csrElements, const chip::ByteSpan & csrNonce, const chip::ByteSpan & attestationSignature, const chip::ByteSpan & attestationChallenge, const chip::ByteSpan & DAC, @@ -68,16 +61,6 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC const chip::Crypto::AesCcm128KeySpan GetIPK() { return mIPK.Span(); } private: - CHIP_ERROR GenerateRootCertKeys(); - CHIP_ERROR LoadRootCertKeysFromKeyChain(); - CHIP_ERROR DeleteRootCertKeysFromKeychain(); - - CHIP_ERROR GenerateIPK(); - CHIP_ERROR LoadIPKFromKeyChain(); - CHIP_ERROR DeleteIPKFromKeyChain(); - - CHIP_ERROR SetIssuerID(CHIPPersistentStorageDelegateBridge * storage); - bool ToChipEpochTime(uint32_t offset, uint32_t & epoch); ChipP256KeypairPtr mIssuerKey; @@ -86,8 +69,6 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC chip::Crypto::AesCcm128Key mIPK; const uint32_t kCertificateValiditySecs = 365 * 24 * 60 * 60; - const NSString * kCHIPCAKeyChainLabel = @"matter.nodeopcerts.CA:0"; - const NSString * kCHIPIPKKeyChainLabel = @"matter.nodeopcerts.IPK:0"; CHIPPersistentStorageDelegateBridge * mStorage; @@ -96,7 +77,6 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC chip::NodeId mNextRequestedNodeId = 1; chip::FabricId mNextFabricId = 1; bool mNodeIdRequested = false; - bool mForceRootCertRegeneration = false; }; NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm index 9b1f3ab8f3b5d7..7b9090081d1f69 100644 --- a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm +++ b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm @@ -40,282 +40,22 @@ using namespace Credentials; using namespace Crypto; -static BOOL isRunningTests(void) -{ - NSDictionary * environment = [[NSProcessInfo processInfo] environment]; - return (environment[@"XCTestConfigurationFilePath"] != nil); -} - -static void ClearSecretData(NSMutableData * data) -{ - Crypto::ClearSecretData(static_cast([data mutableBytes]), [data length]); -} - CHIP_ERROR CHIPOperationalCredentialsDelegate::init( - CHIPPersistentStorageDelegateBridge * storage, ChipP256KeypairPtr nocSigner, NSData * _Nullable ipk) + CHIPPersistentStorageDelegateBridge * storage, ChipP256KeypairPtr nocSigner, NSData * ipk) { - if (storage == nil) { + if (storage == nil || nocSigner == nullptr || ipk == nil) { return CHIP_ERROR_INVALID_ARGUMENT; } mStorage = storage; - if (!nocSigner) { - CHIP_LOG_ERROR("CHIPOperationalCredentialsDelegate: No NOC Signer provided, using self managed keys"); - - mIssuerKey.reset(new chip::Crypto::P256Keypair()); - CHIP_ERROR err = LoadRootCertKeysFromKeyChain(); - - if (err != CHIP_NO_ERROR) { - // Generate keys if keys could not be loaded. Delete keys first, in - // case we have already-stored data that could not be loaded as - // keys; otherwise key generation will fail due to not being able to - // store in the keychain. - DeleteRootCertKeysFromKeychain(); - - err = GenerateRootCertKeys(); - } - - if (err != CHIP_NO_ERROR) { - CHIP_LOG_ERROR("CHIPOperationalCredentialsDelegate::init failed to set up CA keypair: %s", err.AsString()); - return err; - } - } else { - mIssuerKey = std::move(nocSigner); - } - - if (ipk) { - if ([ipk length] != mIPK.Length()) { - CHIP_LOG_ERROR("CHIPOperationalCredentialsDelegate::init provided IPK is wrong size"); - return CHIP_ERROR_INVALID_ARGUMENT; - } - memcpy(mIPK.Bytes(), [ipk bytes], [ipk length]); - } else { - CHIP_ERROR err = LoadIPKFromKeyChain(); - - if (err != CHIP_NO_ERROR) { - // Generate an IPK if an IPK could not be loaded. Delete the existing - // IPK first, in case we have already-stored data that could not be - // loaded as an IPK; otherwise IPK generation will fail due to not being - // able to store in the keychain. - DeleteIPKFromKeyChain(); - - err = GenerateIPK(); - } + mIssuerKey = std::move(nocSigner); - if (err != CHIP_NO_ERROR) { - CHIP_LOG_ERROR("CHIPOperationalCredentialsDelegate::init failed to set up IPK: %s", err.AsString()); - return err; - } - } - - // If keys were loaded, or generated, let's get the certificate issuer ID - - // TODO - enable generating a random issuer ID and saving it in persistent storage - // err = SetIssuerID(storage); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::SetIssuerID(CHIPPersistentStorageDelegateBridge * storage) -{ - static const char * const CHIP_COMMISSIONER_CA_ISSUER_ID = "com.zigbee.chip.commissioner.ca.issuer.id"; - if (storage == nil) { + if ([ipk length] != mIPK.Length()) { + CHIP_LOG_ERROR("CHIPOperationalCredentialsDelegate::init provided IPK is wrong size"); return CHIP_ERROR_INVALID_ARGUMENT; } - - uint16_t issuerIdLen = sizeof(mIssuerId); - if (CHIP_NO_ERROR != storage->SyncGetKeyValue(CHIP_COMMISSIONER_CA_ISSUER_ID, &mIssuerId, issuerIdLen)) { - mIssuerId = arc4random(); - mIssuerId = mIssuerId << 32 | arc4random(); - CHIP_LOG_ERROR("Assigned %llx certificate issuer ID to the commissioner", mIssuerId); - storage->SyncSetKeyValue(CHIP_COMMISSIONER_CA_ISSUER_ID, &mIssuerId, sizeof(mIssuerId)); - } else { - CHIP_LOG_ERROR("Found %llx certificate issuer ID for the commissioner", mIssuerId); - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::LoadRootCertKeysFromKeyChain() -{ - const NSDictionary * query = @{ - (id) kSecClass : (id) kSecClassGenericPassword, - (id) kSecAttrService : kCHIPCAKeyChainLabel, - (id) kSecAttrSynchronizable : @YES, - (id) kSecReturnData : @YES, - }; - - // The CFDataRef we get from SecItemCopyMatching allocates its - // buffer in a way that zeroes it when deallocated. - CFDataRef keyDataRef; - OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, (CFTypeRef *) &keyDataRef); - if (status == errSecItemNotFound || keyDataRef == nil) { - CHIP_LOG_ERROR("Did not find self managed keys in the keychain"); - return CHIP_ERROR_KEY_NOT_FOUND; - } - - CHIP_LOG_ERROR("Found an existing self managed keypair in the keychain"); - NSData * keyData = CFBridgingRelease(keyDataRef); - - NSMutableData * keypairData = [[NSMutableData alloc] initWithBase64EncodedData:keyData options:0]; - - chip::Crypto::P256SerializedKeypair serialized; - if ([keypairData length] != serialized.Capacity()) { - NSLog(@"Keypair length %u does not match expected length %u", static_cast([keypairData length]), - static_cast(serialized.Capacity())); - ClearSecretData(keypairData); - return CHIP_ERROR_INTERNAL; - } - - std::memmove((uint8_t *) serialized, [keypairData bytes], [keypairData length]); - serialized.SetLength([keypairData length]); - - ClearSecretData(keypairData); - - CHIP_LOG_ERROR("Deserializing the key"); - return mIssuerKey->Deserialize(serialized); -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::LoadIPKFromKeyChain() -{ - const NSDictionary * query = @{ - (id) kSecClass : (id) kSecClassGenericPassword, - (id) kSecAttrService : kCHIPIPKKeyChainLabel, - (id) kSecAttrSynchronizable : @YES, - (id) kSecReturnData : @YES, - }; - - // The CFDataRef we get from SecItemCopyMatching allocates its - // buffer in a way that zeroes it when deallocated. - CFDataRef keyDataRef; - OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, (CFTypeRef *) &keyDataRef); - if (status == errSecItemNotFound || keyDataRef == nil) { - CHIP_LOG_ERROR("Did not find IPK in the keychain"); - return CHIP_ERROR_KEY_NOT_FOUND; - } - - CHIP_LOG_ERROR("Found an existing IPK in the keychain"); - NSData * keyData = CFBridgingRelease(keyDataRef); - - NSMutableData * ipkData = [[NSMutableData alloc] initWithBase64EncodedData:keyData options:0]; - if ([ipkData length] != mIPK.Length()) { - NSLog(@"IPK length %u does not match expected length %u", static_cast([ipkData length]), - static_cast(mIPK.Length())); - ClearSecretData(ipkData); - return CHIP_ERROR_INTERNAL; - } - - memcpy(mIPK.Bytes(), [ipkData bytes], [ipkData length]); - ClearSecretData(ipkData); - return CHIP_NO_ERROR; -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::GenerateRootCertKeys() -{ - CHIP_LOG_ERROR("Generating self managed keys for the CA"); - CHIP_ERROR errorCode = mIssuerKey->Initialize(); - if (errorCode != CHIP_NO_ERROR) { - return errorCode; - } - - chip::Crypto::P256SerializedKeypair serializedKey; - errorCode = mIssuerKey->Serialize(serializedKey); - if (errorCode != CHIP_NO_ERROR) { - return errorCode; - } - - NSMutableData * keypairData = [NSMutableData dataWithBytes:serializedKey.Bytes() length:serializedKey.Length()]; - - const NSDictionary * addParams = @{ - (id) kSecClass : (id) kSecClassGenericPassword, - (id) kSecAttrService : kCHIPCAKeyChainLabel, - (id) kSecAttrSynchronizable : @YES, - // TODO: Figure out how to ClearSecretData on the base-64 encoded data? - (id) kSecValueData : [keypairData base64EncodedDataWithOptions:0], - }; - - ClearSecretData(keypairData); - - OSStatus status = SecItemAdd((__bridge CFDictionaryRef) addParams, nullptr); - // TODO: Enable SecItemAdd for Darwin unit tests - if (status != errSecSuccess && !isRunningTests()) { - NSLog(@"Failed in storing key : %d", status); - return CHIP_ERROR_INTERNAL; - } - - NSLog(@"Stored the keys"); - mForceRootCertRegeneration = true; - return CHIP_NO_ERROR; -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::GenerateIPK() -{ - CHIP_ERROR errorCode = DRBG_get_bytes(mIPK.Bytes(), mIPK.Length()); - if (errorCode != CHIP_NO_ERROR) { - return errorCode; - } - - NSMutableData * ipkData = [NSMutableData dataWithBytes:mIPK.Bytes() length:mIPK.Length()]; - - const NSDictionary * addParams = @{ - (id) kSecClass : (id) kSecClassGenericPassword, - (id) kSecAttrService : kCHIPIPKKeyChainLabel, - (id) kSecAttrSynchronizable : @YES, - // TODO: Figure out how to ClearSecretData on the base-64 encoded data? - (id) kSecValueData : [ipkData base64EncodedDataWithOptions:0], - }; - - ClearSecretData(ipkData); - - OSStatus status = SecItemAdd((__bridge CFDictionaryRef) addParams, nullptr); - // TODO: Enable SecItemAdd for Darwin unit tests - if (status != errSecSuccess && !isRunningTests()) { - NSLog(@"Failed in storing IPK : %d", status); - return CHIP_ERROR_INTERNAL; - } - - NSLog(@"Stored IPK"); - return CHIP_NO_ERROR; -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::DeleteRootCertKeysFromKeychain() -{ - CHIP_LOG_ERROR("Deleting self managed CA keys"); - OSStatus status = noErr; - - const NSDictionary * deleteParams = @{ - (id) kSecClass : (id) kSecClassGenericPassword, - (id) kSecAttrService : kCHIPCAKeyChainLabel, - (id) kSecAttrSynchronizable : @YES, - }; - - status = SecItemDelete((__bridge CFDictionaryRef) deleteParams); - if (status != errSecSuccess) { - NSLog(@"Failed in deleting key : %d", status); - return CHIP_ERROR_INTERNAL; - } - - NSLog(@"Deleted the key"); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CHIPOperationalCredentialsDelegate::DeleteIPKFromKeyChain() -{ - const NSDictionary * deleteParams = @{ - (id) kSecClass : (id) kSecClassGenericPassword, - (id) kSecAttrService : kCHIPIPKKeyChainLabel, - (id) kSecAttrSynchronizable : @YES, - }; - - OSStatus status = SecItemDelete((__bridge CFDictionaryRef) deleteParams); - if (status != errSecSuccess) { - NSLog(@"Failed in deleting IPK : %d", status); - return CHIP_ERROR_INTERNAL; - } - - NSLog(@"Deleted the IPK"); + memcpy(mIPK.Bytes(), [ipk bytes], [ipk length]); return CHIP_NO_ERROR; } @@ -338,19 +78,16 @@ static void ClearSecretData(NSMutableData * data) } ChipDN rcac_dn; - if (!mForceRootCertRegeneration) { - uint16_t rcacBufLen = static_cast(std::min(rcac.size(), static_cast(UINT16_MAX))); - PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - haveRootCert = (mStorage->SyncGetKeyValue(key, rcac.data(), rcacBufLen) == CHIP_NO_ERROR)); - if (haveRootCert) { - uint64_t rcacId; - rcac.reduce_size(rcacBufLen); - ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn)); - ReturnErrorOnFailure(rcac_dn.GetCertChipId(rcacId)); - VerifyOrReturnError(rcacId == mIssuerId, CHIP_ERROR_INTERNAL); - } - } - if (!haveRootCert) { + uint16_t rcacBufLen = static_cast(std::min(rcac.size(), static_cast(UINT16_MAX))); + PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, + haveRootCert = (mStorage->SyncGetKeyValue(key, rcac.data(), rcacBufLen) == CHIP_NO_ERROR)); + if (haveRootCert) { + uint64_t rcacId; + rcac.reduce_size(rcacBufLen); + ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn)); + ReturnErrorOnFailure(rcac_dn.GetCertChipId(rcacId)); + VerifyOrReturnError(rcacId == mIssuerId, CHIP_ERROR_INTERNAL); + } else { ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(mIssuerId)); ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterFabricId(fabricId)); @@ -361,8 +98,6 @@ static void ClearSecretData(NSMutableData * data) VerifyOrReturnError(CanCastTo(rcac.size()), CHIP_ERROR_INTERNAL); PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, ReturnErrorOnFailure(mStorage->SyncSetKeyValue(key, rcac.data(), static_cast(rcac.size())))); - - mForceRootCertRegeneration = false; } icac.reduce_size(0); diff --git a/src/darwin/Framework/CHIP/MatterControllerFactory.h b/src/darwin/Framework/CHIP/MatterControllerFactory.h index 22337fea2303c5..a407b2f43d956d 100644 --- a/src/darwin/Framework/CHIP/MatterControllerFactory.h +++ b/src/darwin/Framework/CHIP/MatterControllerFactory.h @@ -68,24 +68,24 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic) uint16_t vendorId; /* - * Root CA keypair that identifies (via its public key) the fabric. Nullable - * for now, but that will change. + * Root CA keypair that scopes (via its public key) the fabric id. To use + * startControllerOnExistingFabric successfully, both the public key of + * rootCAKeypair and the fabricId must match an existing fabric. */ -@property (strong, nonatomic, nullable) id rootCAKeypair; +@property (strong, nonatomic) id rootCAKeypair; /* * Fabric id for the controller. Must be set to a nonzero value. */ @property (nonatomic) uint64_t fabricId; /* - * IPK to use for the controller's fabric. Allowed to be null when - * starting a controller on an existing fabric. + * IPK to use for the controller's fabric. Allowed to change from the last time + * a controller was started on this fabric if a new IPK has been distributed to + * all the devices the controller wants to interact with. */ -@property (strong, nonatomic, nullable) NSData * ipk; +@property (strong, nonatomic) NSData * ipk; - (instancetype)init NS_UNAVAILABLE; -// TODO The keypair should not be nullable, but we need to sort out -// CHIPClustersTests and CHIPTool use of these APIs first. -- (instancetype)initWithKeypair:(_Nullable id)rootCAKeypair; +- (instancetype)initWithKeypair:(id)rootCAKeypair ipk:(NSData *)ipk; @end diff --git a/src/darwin/Framework/CHIP/MatterControllerFactory.mm b/src/darwin/Framework/CHIP/MatterControllerFactory.mm index 780a1e3ba11596..1f8a51546f654e 100644 --- a/src/darwin/Framework/CHIP/MatterControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MatterControllerFactory.mm @@ -297,22 +297,6 @@ - (CHIPDeviceController * _Nullable)startControllerOnExistingFabric:(CHIPDeviceC okToStart = YES; }); - if (startupParams.rootCAKeypair == nil) { - // TODO: This block needs for nil keypair needs to go away. - // - // We don't have to a public key to identify this fabric, so - // okToStart got set to false, just assume that it's OK to start - // the controller. But only if we have no running controllers - // already, so we don't stomp on other controllers. - // - // Our controller is already in _controllers. - if ([_controllers count] == 1) { - okToStart = YES; - } else { - CHIP_LOG_ERROR("No root key, an a controller is already running. Blocking second controller"); - } - } - if (okToStart == NO) { [self controllerShuttingDown:controller]; return nil; @@ -334,14 +318,6 @@ - (CHIPDeviceController * _Nullable)startControllerOnNewFabric:(CHIPDeviceContro return nil; } - if (startupParams.rootCAKeypair == nil) { - // TODO: This block needs for nil keypair needs to go away. - // - // Disallow starting on a "new fabric" if there is no indication - // of what the new fabric should be. - return nil; - } - // Create the controller, so we start the event loop, since we plan to do our fabric table operations there. auto * controller = [self createController]; if (controller == nil) { diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index fc1e6420300802..f94c3422a567f1 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -125,10 +125,9 @@ - (void)testInitStack __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller); diff --git a/src/darwin/Framework/CHIPTests/CHIPControllerTests.m b/src/darwin/Framework/CHIPTests/CHIPControllerTests.m index 2489ee9a9f327e..8ebc650fdc7b14 100644 --- a/src/darwin/Framework/CHIPTests/CHIPControllerTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPControllerTests.m @@ -69,10 +69,9 @@ - (void)testControllerLifecycle __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller); @@ -106,10 +105,9 @@ - (void)testFactoryShutdownShutsDownController __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller); @@ -133,10 +131,9 @@ - (void)testControllerMultipleShutdown __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertTrue([controller isRunning]); @@ -162,10 +159,9 @@ - (void)testControllerInvalidAccess __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertTrue([controller isRunning]); @@ -182,45 +178,6 @@ - (void)testControllerInvalidAccess XCTAssertFalse([factory isRunning]); } -- (void)testControllerStartTwoControllersNoKeypair -{ - __auto_type * factory = [MatterControllerFactory sharedInstance]; - XCTAssertNotNil(factory); - - __auto_type * storage = [[CHIPTestStorage alloc] init]; - __auto_type * factoryParams = [[MatterControllerFactoryParams alloc] initWithStorage:storage]; - XCTAssertTrue([factory startup:factoryParams]); - XCTAssertTrue([factory isRunning]); - - __auto_type * testKeys = [[CHIPTestKeys alloc] init]; - XCTAssertNotNil(testKeys); - - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:nil]; - params.vendorId = kTestVendorId; - params.fabricId = 1; - - // TODO: Once we require a non-nil keypair, this test will stop - // making sense and need to go away. - CHIPDeviceController * controller1 = [factory startControllerOnExistingFabric:params]; - XCTAssertNotNil(controller1); - XCTAssertTrue([controller1 isRunning]); - - // now try to start a second controller. - params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:nil]; - params.vendorId = kTestVendorId; - params.fabricId = 2; - CHIPDeviceController * controller2 = [factory startControllerOnExistingFabric:params]; - // Should fail, because we don't allow starting a second - // controller without a provided keypair. - XCTAssertNil(controller2); - - [controller1 shutdown]; - XCTAssertFalse([controller1 isRunning]); - - [factory shutdown]; - XCTAssertFalse([factory isRunning]); -} - - (void)testControllerNewFabricMatchesOldFabric { __auto_type * factory = [MatterControllerFactory sharedInstance]; @@ -234,10 +191,9 @@ - (void)testControllerNewFabricMatchesOldFabric __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller); @@ -269,10 +225,9 @@ - (void)testControllerExistingFabricMatchesRunningController __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller); @@ -303,10 +258,9 @@ - (void)testControllerStartControllersOnTwoFabricIds __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller1 = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller1); diff --git a/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m b/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m index 8087e497b7555f..bf7fbc7ed8514c 100644 --- a/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPDeviceTests.m @@ -157,10 +157,9 @@ - (void)initStack __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller); diff --git a/src/darwin/Framework/CHIPTests/CHIPXPCListenerSampleTests.m b/src/darwin/Framework/CHIPTests/CHIPXPCListenerSampleTests.m index 33c9c5fce65a2e..ed33ec69d0c852 100644 --- a/src/darwin/Framework/CHIPTests/CHIPXPCListenerSampleTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPXPCListenerSampleTests.m @@ -524,10 +524,9 @@ - (void)initStack __auto_type * testKeys = [[CHIPTestKeys alloc] init]; XCTAssertNotNil(testKeys); - __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys]; + __auto_type * params = [[CHIPDeviceControllerStartupParams alloc] initWithKeypair:testKeys ipk:testKeys.ipk]; params.vendorId = kTestVendorId; params.fabricId = 1; - params.ipk = testKeys.ipk; CHIPDeviceController * controller = [factory startControllerOnNewFabric:params]; XCTAssertNotNil(controller);