diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 8b34769b09ecea..a0da54001a3a94 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -35,6 +35,7 @@ #import "MTRPersistentStorageDelegateBridge.h" #import "MTRSetupPayload.h" #import "NSDataSpanConversion.h" +#import "NSSetCATConversion.h" #import "NSStringSpanConversion.h" #import #import @@ -312,27 +313,11 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams chip::CATValues cats = chip::kUndefinedCATs; if (startupParams.caseAuthenticatedTags != nil) { - unsigned long long tagCount = startupParams.caseAuthenticatedTags.count; - if (tagCount > chip::kMaxSubjectCATAttributeCount) { - MTR_LOG_ERROR("%llu CASE Authenticated Tags cannot be represented in a certificate.", tagCount); + errorCode = ToCATValues(startupParams.caseAuthenticatedTags, cats); + if (errorCode != CHIP_NO_ERROR) { + // ToCATValues already handles logging. return; } - - size_t tagIndex = 0; - for (NSNumber * boxedTag in startupParams.caseAuthenticatedTags) { - if (!chip::CanCastTo(boxedTag.unsignedLongLongValue)) { - MTR_LOG_ERROR("0x%llx is not a valid CASE Authenticated Tag value.", boxedTag.unsignedLongLongValue); - return; - } - - auto tag = static_cast(boxedTag.unsignedLongLongValue); - if (!chip::IsValidCASEAuthTag(tag)) { - MTR_LOG_ERROR("0x%" PRIx32 " is not a valid CASE Authenticated Tag value.", tag); - return; - } - - cats.values[tagIndex++] = tag; - } } if (commissionerParams.operationalKeypair != nullptr) { diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm index 771995bf01bc66..7c8885d92e7ae0 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm @@ -20,6 +20,7 @@ #import "MTRLogging_Internal.h" #import "MTRP256KeypairBridge.h" #import "NSDataSpanConversion.h" +#import "NSSetCATConversion.h" #include #include @@ -302,13 +303,7 @@ - (instancetype)initForExistingFabric:(FabricTable *)fabricTable auto tagCount = cats.GetNumTagsPresent(); if (tagCount > 0) { - auto * catSet = [[NSMutableSet alloc] initWithCapacity:tagCount]; - for (auto & value : cats.values) { - if (value != kUndefinedCAT) { - [catSet addObject:@(value)]; - } - } - self.caseAuthenticatedTags = [NSSet setWithSet:catSet]; + self.caseAuthenticatedTags = FromCATValues(cats); } else { self.caseAuthenticatedTags = nil; } diff --git a/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm b/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm index 7e5282eca51a52..a9edca0b6cdf26 100644 --- a/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm +++ b/src/darwin/Framework/CHIP/MTROperationalCredentialsDelegate.mm @@ -25,6 +25,7 @@ #import "MTRDeviceController_Internal.h" #import "MTRLogging_Internal.h" #import "NSDataSpanConversion.h" +#import "NSSetCATConversion.h" #include #include @@ -469,10 +470,7 @@ uint64_t GetIssuerId(NSNumber * _Nullable providedIssuerId) CATValues cats; if (caseAuthenticatedTags != nil) { - size_t idx = 0; - for (NSNumber * cat in [caseAuthenticatedTags.allObjects sortedArrayUsingSelector:@selector(compare:)]) { - cats.values[idx++] = [cat unsignedIntValue]; - } + ReturnErrorOnFailure(ToCATValues(caseAuthenticatedTags, cats)); } uint8_t nocBuffer[Controller::kMaxCHIPDERCertLength]; diff --git a/src/darwin/Framework/CHIP/NSSetCATConversion.h b/src/darwin/Framework/CHIP/NSSetCATConversion.h new file mode 100644 index 00000000000000..d6fc8a4b03e8b0 --- /dev/null +++ b/src/darwin/Framework/CHIP/NSSetCATConversion.h @@ -0,0 +1,74 @@ +/** + * 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. + */ + +#pragma once + +#import + +#import "MTRLogging_Internal.h" + +#include +#include +#include + +NS_ASSUME_NONNULL_BEGIN + +/** + * Utilities for converting between NSSet and chip::CATValues. + */ + +inline CHIP_ERROR ToCATValues(NSSet * catSet, chip::CATValues & values) +{ + values = chip::kUndefinedCATs; + + unsigned long long tagCount = catSet.count; + if (tagCount > chip::kMaxSubjectCATAttributeCount) { + MTR_LOG_ERROR("%llu CASE Authenticated Tags cannot be represented in a certificate.", tagCount); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + size_t tagIndex = 0; + for (NSNumber * boxedTag in [catSet.allObjects sortedArrayUsingSelector:@selector(compare:)]) { + auto unboxedTag = boxedTag.unsignedLongLongValue; + if (!chip::CanCastTo(unboxedTag)) { + MTR_LOG_ERROR("0x%llx is not a valid CASE Authenticated Tag value.", unboxedTag); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + auto tag = static_cast(unboxedTag); + if (!chip::IsValidCASEAuthTag(tag)) { + MTR_LOG_ERROR("0x%" PRIx32 " is not a valid CASE Authenticated Tag value.", tag); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + values.values[tagIndex++] = tag; + } + + return CHIP_NO_ERROR; +} + +inline NSSet * FromCATValues(const chip::CATValues & values) +{ + auto * catSet = [[NSMutableSet alloc] initWithCapacity:values.GetNumTagsPresent()]; + for (auto & value : values.values) { + if (value != chip::kUndefinedCAT) { + [catSet addObject:@(value)]; + } + } + return [NSSet setWithSet:catSet]; +} + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index fea8bd9966ac2a..96dfaa203fddfc 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -154,6 +154,7 @@ 51431AF927D2973E008A7943 /* MTRIMDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51431AF827D2973E008A7943 /* MTRIMDispatch.mm */; }; 51431AFB27D29CA4008A7943 /* ota-provider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51431AFA27D29CA4008A7943 /* ota-provider.cpp */; }; 5143851E2A65885500EDC8E6 /* MTRSwiftPairingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5143851D2A65885500EDC8E6 /* MTRSwiftPairingTests.swift */; }; + 51565CAC2A796B8200469F18 /* NSSetCATConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CAB2A796B8200469F18 /* NSSetCATConversion.h */; }; 515C1C6F284F9FFB00A48F0C /* MTRFramework.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */; }; 515C1C70284F9FFB00A48F0C /* MTRFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */; }; 51669AF02913204400F4AA36 /* MTRBackwardsCompatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 51669AEF2913204400F4AA36 /* MTRBackwardsCompatTests.m */; }; @@ -458,6 +459,7 @@ 51431AFA27D29CA4008A7943 /* ota-provider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ota-provider.cpp"; path = "clusters/ota-provider/ota-provider.cpp"; sourceTree = ""; }; 5143851C2A65885400EDC8E6 /* MatterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MatterTests-Bridging-Header.h"; sourceTree = ""; }; 5143851D2A65885500EDC8E6 /* MTRSwiftPairingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MTRSwiftPairingTests.swift; sourceTree = ""; }; + 51565CAB2A796B8200469F18 /* NSSetCATConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSSetCATConversion.h; sourceTree = ""; }; 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRFramework.mm; sourceTree = ""; }; 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRFramework.h; sourceTree = ""; }; 51669AEF2913204400F4AA36 /* MTRBackwardsCompatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRBackwardsCompatTests.m; sourceTree = ""; }; @@ -1098,6 +1100,7 @@ 997DED152695343400975E97 /* MTRThreadOperationalDataset.mm */, 3D843710294977000070D20A /* NSDataSpanConversion.h */, 3D84370E294977000070D20A /* NSStringSpanConversion.h */, + 51565CAB2A796B8200469F18 /* NSSetCATConversion.h */, 5117DD3729A931AE00FFA1AA /* MTROperationalBrowser.h */, 5117DD3629A931AD00FFA1AA /* MTROperationalBrowser.mm */, 5173A47229C0E2ED00F67F48 /* MTRFabricInfo_Internal.h */, @@ -1213,6 +1216,7 @@ 5ACDDD7A27CD129700EFD68A /* MTRClusterStateCacheContainer.h in Headers */, 5A6FEC9227B5669C00F25F42 /* MTRDeviceControllerOverXPC.h in Headers */, 5117DD3929A931AE00FFA1AA /* MTROperationalBrowser.h in Headers */, + 51565CAC2A796B8200469F18 /* NSSetCATConversion.h in Headers */, 2C1B027B2641DB4E00780EF1 /* MTROperationalCredentialsDelegate.h in Headers */, 5173A47529C0E2ED00F67F48 /* MTRFabricInfo_Internal.h in Headers */, 3D843717294979230070D20A /* MTRClusters_Internal.h in Headers */,