Skip to content

Commit

Permalink
Added parameter to Objective-C CHIPDeviceController to accept PAA cer… (
Browse files Browse the repository at this point in the history
#17035)

* 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 <bzbarsky@apple.com>

* Update src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm

Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>

* 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 <commits@restyled.io>
Co-authored-by: Justin Wood <woody@apple.com>
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
  • Loading branch information
4 people authored and pull[bot] committed Jul 24, 2023
1 parent 96e8c0d commit 1177095
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 8 additions & 0 deletions src/darwin/Framework/CHIP.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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, ); }; };
Expand Down Expand Up @@ -110,6 +112,8 @@
1ED276DF26C57CF000547A89 /* CHIPCallbackBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CHIPCallbackBridge.mm; path = "zap-generated/CHIPCallbackBridge.mm"; sourceTree = "<group>"; };
1ED276E126C5812A00547A89 /* CHIPCluster.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPCluster.mm; sourceTree = "<group>"; };
1ED276E326C5832500547A89 /* CHIPCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPCluster.h; sourceTree = "<group>"; };
27A53C1527FBC6920053F131 /* CHIPAttestationTrustStoreBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPAttestationTrustStoreBridge.h; sourceTree = "<group>"; };
27A53C1627FBC6920053F131 /* CHIPAttestationTrustStoreBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPAttestationTrustStoreBridge.mm; sourceTree = "<group>"; };
2C1B02782641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHIPOperationalCredentialsDelegate.mm; sourceTree = "<group>"; };
2C1B02792641DB4E00780EF1 /* CHIPOperationalCredentialsDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPOperationalCredentialsDelegate.h; sourceTree = "<group>"; };
2C222ACE255C620600E446B9 /* CHIPDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHIPDevice.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
1 change: 1 addition & 0 deletions src/darwin/Framework/CHIP/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ config("darwin_config") {
static_library("framework") {
sources = [
"CHIP.h",
"CHIPAttestationTrustStoreBridge.mm",
"CHIPCluster.mm",
"CHIPCommissioningParameters.m",
"CHIPControllerAccessControl.h",
Expand Down
36 changes: 36 additions & 0 deletions src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.h
Original file line number Diff line number Diff line change
@@ -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 <credentials/attestation_verifier/DeviceAttestationVerifier.h>

NS_ASSUME_NONNULL_BEGIN

class CHIPAttestationTrustStoreBridge : public chip::Credentials::AttestationTrustStore {
public:
~CHIPAttestationTrustStoreBridge() {};

void Init(NSArray<NSData *> * paaCerts);

CHIP_ERROR GetProductAttestationAuthorityCert(
const chip::ByteSpan & skid, chip::MutableByteSpan & outPaaDerBuffer) const override;

private:
NSArray<NSData *> * mPaaCerts;
};

NS_ASSUME_NONNULL_END
45 changes: 45 additions & 0 deletions src/darwin/Framework/CHIP/CHIPAttestationTrustStoreBridge.mm
Original file line number Diff line number Diff line change
@@ -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<const uint8_t *>(value.bytes), value.length); }

void CHIPAttestationTrustStoreBridge::Init(NSArray<NSData *> * 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;
}
4 changes: 3 additions & 1 deletion src/darwin/Framework/CHIP/CHIPDeviceController.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CHIPPersistentStorageDelegate>)storageDelegate
vendorId:(uint16_t)vendorId
nocSigner:(id<CHIPKeypair>)nocSigner
ipk:(NSData * _Nullable)ipk;
ipk:(NSData * _Nullable)ipk
paaCerts:(NSArray<NSData *> * _Nullable)paaCerts;
/**
* Shutdown the CHIP Stack. Repeated calls to shutdown without calls to startup in between are NO-OPs.
*/
Expand Down
27 changes: 23 additions & 4 deletions src/darwin/Framework/CHIP/CHIPDeviceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
#import "CHIPDeviceController.h"

#import "CHIPAttestationTrustStoreBridge.h"
#import "CHIPCommissioningParameters.h"
#import "CHIPControllerAccessControl.h"
#import "CHIPDevicePairingDelegateBridge.h"
Expand Down Expand Up @@ -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";
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -183,12 +191,13 @@ - (BOOL)startup:(_Nullable id<CHIPPersistentStorageDelegate>)storageDelegate
vendorId:(uint16_t)vendorId
nocSigner:(id<CHIPKeypair>)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<CHIPPersistentStorageDelegate>)storageDelegate
vendorId:(uint16_t)vendorId
nocSigner:(id<CHIPKeypair>)nocSigner
ipk:(NSData * _Nullable)ipk
paaCerts:(NSArray<NSData *> * _Nullable)paaCerts
{
if (vendorId == chip::VendorId::Common) {
// Shouldn't be using the "standard" vendor ID for actual devices.
Expand Down Expand Up @@ -243,9 +252,14 @@ - (BOOL)startup:(_Nullable id<CHIPPersistentStorageDelegate>)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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1177095

Please sign in to comment.