From 2afa53c1da2036aa034517698649650c243ba4b5 Mon Sep 17 00:00:00 2001 From: carricdsilva-apple <59451741+carricdsilva-apple@users.noreply.github.com> Date: Tue, 5 Apr 2022 18:37:03 -0700 Subject: [PATCH] =?UTF-8?q?Added=20parameter=20to=20Objective-C=20CHIPDevi?= =?UTF-8?q?ceController=20to=20accept=20PAA=20cer=E2=80=A6=20(#17035)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added parameter to Objective-C CHIPDeviceController to accept PAA certificates from Objective-C client Fixes #14126 Change overview Added a new parameter to CHIPDeviceController that is an array of NSData PAA certificates. Created an Objective-C bridge for the AttestationTrustStore class. The PAA certificates provided by the client are passed to the default device attestation verifier. If the client passes a nil value for the parameter then the testing root store is used. Testing Used an Objective-C client to pass valid certificates to ensure device attestation procedure succeeded with an m5stack device. Passed in nil to ensure the device attestation procedure used the test PAA certificates. * Restyled by whitespace * Restyled by clang-format * Update src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm Co-authored-by: Boris Zbarsky * Update src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm Co-authored-by: Boris Zbarsky * Updated files: examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m src/darwin/Framework/CHIP/BUILD.gn src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm src/darwin/Framework/CHIP/CHIPDeviceController.h src/darwin/Framework/CHIP/CHIPDeviceController.mm * Restyled by gn Co-authored-by: Restyled.io Co-authored-by: Justin Wood Co-authored-by: Boris Zbarsky --- .../commands/common/CHIPCommandBridge.mm | 2 +- .../Framework/CHIP.xcodeproj/project.pbxproj | 8 ++++ src/darwin/Framework/CHIP/BUILD.gn | 1 + .../CHIP/CHIPAttestationTrustStoreBridge.h | 36 +++++++++++++++ .../CHIP/CHIPAttestationTrustStoreBridge.mm | 45 +++++++++++++++++++ .../Framework/CHIP/CHIPDeviceController.h | 4 +- .../Framework/CHIP/CHIPDeviceController.mm | 27 +++++++++-- 7 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.h create mode 100644 src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm diff --git a/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm b/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm index 472b52b1422ffd..3cf75f6e7fa0c0 100644 --- a/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm +++ b/examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm @@ -47,7 +47,7 @@ ipk = [nocSigner getIPK]; - if (![mController startup:storage vendorId:chip::VendorId::TestVendor1 nocSigner:nocSigner ipk:ipk]) { + if (![mController startup:storage vendorId:chip::VendorId::TestVendor1 nocSigner:nocSigner ipk:ipk paaCerts:nil]) { ChipLogError(chipTool, "Controller startup failure."); return CHIP_ERROR_INTERNAL; } diff --git a/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj b/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj index c37d02c6a7283a..82b01f1596d9e2 100644 --- a/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/CHIP.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 1ED276E026C57CF000547A89 /* CHIPCallbackBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ED276DF26C57CF000547A89 /* CHIPCallbackBridge.mm */; }; 1ED276E226C5812A00547A89 /* CHIPCluster.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1ED276E126C5812A00547A89 /* CHIPCluster.mm */; }; 1ED276E426C5832500547A89 /* CHIPCluster.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ED276E326C5832500547A89 /* CHIPCluster.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 27A53C1727FBC6920053F131 /* CHIPAttestationTrustStoreBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 27A53C1527FBC6920053F131 /* CHIPAttestationTrustStoreBridge.h */; }; + 27A53C1827FBC6920053F131 /* CHIPAttestationTrustStoreBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27A53C1627FBC6920053F131 /* CHIPAttestationTrustStoreBridge.mm */; }; 2C1B027A2641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2C1B02782641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm */; }; 2C1B027B2641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C1B02792641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h */; }; 2C222AD0255C620600E446B9 /* CHIPDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C222ACE255C620600E446B9 /* CHIPDevice.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -110,6 +112,8 @@ 1ED276DF26C57CF000547A89 /* CHIPCallbackBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CHIPCallbackBridge.mm; path = "zap-generated/CHIPCallbackBridge.mm"; sourceTree = ""; }; 1ED276E126C5812A00547A89 /* CHIPCluster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPCluster.mm; sourceTree = ""; }; 1ED276E326C5832500547A89 /* CHIPCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPCluster.h; sourceTree = ""; }; + 27A53C1527FBC6920053F131 /* CHIPAttestationTrustStoreBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPAttestationTrustStoreBridge.h; sourceTree = ""; }; + 27A53C1627FBC6920053F131 /* CHIPAttestationTrustStoreBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPAttestationTrustStoreBridge.mm; sourceTree = ""; }; 2C1B02782641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPOperationalCredentialsDelegate.mm; sourceTree = ""; }; 2C1B02792641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPOperationalCredentialsDelegate.h; sourceTree = ""; }; 2C222ACE255C620600E446B9 /* CHIPDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPDevice.h; sourceTree = ""; }; @@ -259,6 +263,8 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + 27A53C1527FBC6920053F131 /* CHIPAttestationTrustStoreBridge.h */, + 27A53C1627FBC6920053F131 /* CHIPAttestationTrustStoreBridge.mm */, 513DDB852761F69300DAA01A /* CHIPAttributeTLVValueDecoder_Internal.h */, 1ED276E326C5832500547A89 /* CHIPCluster.h */, 1ED276E126C5812A00547A89 /* CHIPCluster.mm */, @@ -371,6 +377,7 @@ B2E0D7B8245B0B5C003C5B48 /* CHIPSetupPayload.h in Headers */, 997DED182695344800975E97 /* CHIPThreadOperationalDataset.h in Headers */, 9956064426420367000C28DE /* CHIPSetupPayload_Internal.h in Headers */, + 27A53C1727FBC6920053F131 /* CHIPAttestationTrustStoreBridge.h in Headers */, 5A830D6C27CFCF590053B85D /* CHIPDeviceControllerOverXPC_Internal.h in Headers */, 5A60370827EA1FF60020DB79 /* CHIPAttributeCacheContainer+XPC.h in Headers */, 5ACDDD7E27CD3F3A00EFD68A /* CHIPAttributeCacheContainer_Internal.h in Headers */, @@ -516,6 +523,7 @@ 99AECC802798A57F00B6355B /* CHIPCommissioningParameters.m in Sources */, 2CB7163C252E8A7C0026E2BB /* CHIPDevicePairingDelegateBridge.mm in Sources */, 997DED162695343400975E97 /* CHIPThreadOperationalDataset.mm in Sources */, + 27A53C1827FBC6920053F131 /* CHIPAttestationTrustStoreBridge.mm in Sources */, 998F287126D56940001846C6 /* CHIPP256KeypairBridge.mm in Sources */, 1E16A90226B98AB700683C53 /* CHIPTestClustersObjc.mm in Sources */, 51B22C2A2740CB47008D5055 /* CHIPCommandPayloadsObjc.mm in Sources */, diff --git a/src/darwin/Framework/CHIP/BUILD.gn b/src/darwin/Framework/CHIP/BUILD.gn index 31ef2e0d94ecaa..733d219fa2a2e2 100644 --- a/src/darwin/Framework/CHIP/BUILD.gn +++ b/src/darwin/Framework/CHIP/BUILD.gn @@ -29,6 +29,7 @@ config("darwin_config") { static_library("framework") { sources = [ "CHIP.h", + "CHIPAttestationTrustStoreBridge.mm", "CHIPCluster.mm", "CHIPCommissioningParameters.m", "CHIPControllerAccessControl.h", diff --git a/src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.h b/src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.h new file mode 100644 index 00000000000000..318bc6984bb685 --- /dev/null +++ b/src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.h @@ -0,0 +1,36 @@ +/** + * + * 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 "CHIPError_Internal.h" +#include + +NS_ASSUME_NONNULL_BEGIN + +class CHIPAttestationTrustStoreBridge : public chip::Credentials::AttestationTrustStore { +public: + ~CHIPAttestationTrustStoreBridge() {}; + + void Init(NSArray * paaCerts); + + CHIP_ERROR GetProductAttestationAuthorityCert( + const chip::ByteSpan & skid, chip::MutableByteSpan & outPaaDerBuffer) const override; + +private: + NSArray * mPaaCerts; +}; + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm b/src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm new file mode 100644 index 00000000000000..c224ed77e4bca5 --- /dev/null +++ b/src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm @@ -0,0 +1,45 @@ +/** + * + * 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 "CHIPAttestationTrustStoreBridge.h" + +static chip::ByteSpan asByteSpan(NSData * value) { return chip::ByteSpan(static_cast(value.bytes), value.length); } + +void CHIPAttestationTrustStoreBridge::Init(NSArray * paaCerts) { mPaaCerts = paaCerts; } + +CHIP_ERROR CHIPAttestationTrustStoreBridge::GetProductAttestationAuthorityCert( + const chip::ByteSpan & skid, chip::MutableByteSpan & outPaaDerBuffer) const +{ + VerifyOrReturnError(skid.size() == chip::Crypto::kSubjectKeyIdentifierLength, CHIP_ERROR_INVALID_ARGUMENT); + + size_t paaIdx; + chip::ByteSpan candidate; + + for (paaIdx = 0; paaIdx < mPaaCerts.count; ++paaIdx) { + uint8_t skidBuf[chip::Crypto::kSubjectKeyIdentifierLength] = { 0 }; + candidate = asByteSpan(mPaaCerts[paaIdx]); + chip::MutableByteSpan candidateSkidSpan { skidBuf }; + VerifyOrReturnError( + CHIP_NO_ERROR == chip::Crypto::ExtractSKIDFromX509Cert(candidate, candidateSkidSpan), CHIP_ERROR_INTERNAL); + + if (skid.data_equal(candidateSkidSpan)) { + // Found a match + return CopySpanToMutableSpan(candidate, outPaaDerBuffer); + } + } + return CHIP_ERROR_CA_CERT_NOT_FOUND; +} diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.h b/src/darwin/Framework/CHIP/CHIPDeviceController.h index abf57e6a05bafd..cbd9fb95a71f82 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.h +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.h @@ -120,11 +120,13 @@ typedef void (^CHIPDeviceConnectionCallback)(CHIPDevice * _Nullable device, NSEr * @param[in] vendorId The vendor ID of the commissioner application * @param[in] nocSigner The CHIPKeypair that is used to generate and sign Node Operational Credentials * @param[in] ipk The IPK to use for Operational Credentials. + * @param[in] paaCerts The PAA certificates used for device attestation */ - (BOOL)startup:(_Nullable id)storageDelegate vendorId:(uint16_t)vendorId nocSigner:(id)nocSigner - ipk:(NSData * _Nullable)ipk; + ipk:(NSData * _Nullable)ipk + paaCerts:(NSArray * _Nullable)paaCerts; /** * Shutdown the CHIP Stack. Repeated calls to shutdown without calls to startup in between are NO-OPs. */ diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index 740d1227b16753..536023c3e8c4e2 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -16,6 +16,7 @@ */ #import "CHIPDeviceController.h" +#import "CHIPAttestationTrustStoreBridge.h" #import "CHIPCommissioningParameters.h" #import "CHIPControllerAccessControl.h" #import "CHIPDevicePairingDelegateBridge.h" @@ -58,6 +59,7 @@ static NSString * const kErrorOperationalCredentialsInit = @"Init failure while creating operational credentials delegate"; static NSString * const kErrorPairingInit = @"Init failure while creating a pairing delegate"; static NSString * const kErrorPersistentStorageInit = @"Init failure while creating a persistent storage delegate"; +static NSString * const kErrorAttestationTrustStoreInit = @"Init failure while creating the attestation trust store"; static NSString * const kErrorPairDevice = @"Failure while pairing the device"; static NSString * const kErrorUnpairDevice = @"Failure while unpairing the device"; static NSString * const kErrorStopPairing = @"Failure while trying to stop the pairing process"; @@ -79,6 +81,7 @@ @interface CHIPDeviceController () @property (readonly) chip::Credentials::GroupDataProviderImpl * groupDataProvider; @property (readonly) CHIPDevicePairingDelegateBridge * pairingDelegateBridge; @property (readonly) CHIPPersistentStorageDelegateBridge * persistentStorageDelegateBridge; +@property (readonly) CHIPAttestationTrustStoreBridge * attestationTrustStoreBridge; @property (readonly) CHIPOperationalCredentialsDelegate * operationalCredentialsDelegate; @property (readonly) CHIPP256KeypairBridge keypairBridge; @property (readonly) chip::NodeId localDeviceId; @@ -123,6 +126,11 @@ - (instancetype)init return nil; } + _attestationTrustStoreBridge = new CHIPAttestationTrustStoreBridge(); + if ([self checkForInitError:(_attestationTrustStoreBridge != nullptr) logMsg:kErrorAttestationTrustStoreInit]) { + return nil; + } + _operationalCredentialsDelegate = new CHIPOperationalCredentialsDelegate(); if ([self checkForInitError:(_operationalCredentialsDelegate != nullptr) logMsg:kErrorOperationalCredentialsInit]) { return nil; @@ -183,12 +191,13 @@ - (BOOL)startup:(_Nullable id)storageDelegate vendorId:(uint16_t)vendorId nocSigner:(id)nocSigner { - return [self startup:storageDelegate vendorId:vendorId nocSigner:nocSigner ipk:nil]; + return [self startup:storageDelegate vendorId:vendorId nocSigner:nocSigner ipk:nil paaCerts:nil]; } - (BOOL)startup:(_Nullable id)storageDelegate vendorId:(uint16_t)vendorId nocSigner:(id)nocSigner ipk:(NSData * _Nullable)ipk + paaCerts:(NSArray * _Nullable)paaCerts { if (vendorId == chip::VendorId::Common) { // Shouldn't be using the "standard" vendor ID for actual devices. @@ -243,9 +252,14 @@ - (BOOL)startup:(_Nullable id)storageDelegate params.enableServerInteractions = true; // Initialize device attestation verifier - // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available - const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); - chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore)); + if (paaCerts) { + _attestationTrustStoreBridge->Init(paaCerts); + chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(_attestationTrustStoreBridge)); + } else { + // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available + const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); + chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore)); + } params.groupDataProvider = _groupDataProvider; params.fabricIndependentStorage = _persistentStorageDelegateBridge; @@ -675,6 +689,11 @@ - (BOOL)checkForInitError:(BOOL)condition logMsg:(NSString *)logMsg _persistentStorageDelegateBridge = NULL; } + if (_attestationTrustStoreBridge) { + delete _attestationTrustStoreBridge; + _attestationTrustStoreBridge = NULL; + } + if (_groupDataProvider) { _groupDataProvider->Finish(); delete _groupDataProvider;