Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow per-controller control of PAAs and CD signing keys. #28998

Merged
merged 2 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/darwin/Framework/CHIP/MTRDeviceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#import "MTRDeviceController_Internal.h"

#import "MTRAttestationTrustStoreBridge.h"
#import "MTRBaseDevice_Internal.h"
#import "MTRCommissionableBrowser.h"
#import "MTRCommissionableBrowserResult_Internal.h"
Expand Down Expand Up @@ -86,6 +87,7 @@
static NSString * const kErrorGetAttestationChallenge = @"Failure getting attestation challenge";
static NSString * const kErrorSpake2pVerifierGenerationFailed = @"PASE verifier generation failed";
static NSString * const kErrorSpake2pVerifierSerializationFailed = @"PASE verifier serialization failed";
static NSString * const kErrorCDCertStoreInit = @"Init failure while initializing Certificate Declaration Signing Keys store";

typedef void (^SyncWorkQueueBlock)(void);
typedef id (^SyncWorkQueueBlockWithReturnValue)(void);
Expand All @@ -101,6 +103,7 @@ @interface MTRDeviceController () {

@property (readonly) chip::Controller::DeviceCommissioner * cppCommissioner;
@property (readonly) chip::Credentials::PartialDACVerifier * partialDACVerifier;
@property (readonly) chip::Credentials::DefaultDACVerifier * defaultDACVerifier;
@property (readonly) MTRDeviceControllerDelegateBridge * deviceControllerDelegateBridge;
@property (readonly) MTROperationalCredentialsDelegate * operationalCredentialsDelegate;
@property (readonly) MTRP256KeypairBridge signingKeypairBridge;
Expand All @@ -110,6 +113,8 @@ @interface MTRDeviceController () {
@property (readonly) NSMutableDictionary * nodeIDToDeviceMap;
@property (readonly) os_unfair_lock deviceMapLock; // protects nodeIDToDeviceMap
@property (readonly) MTRCommissionableBrowser * commissionableBrowser;
@property (readonly) MTRAttestationTrustStoreBridge * attestationTrustStoreBridge;

@end

@implementation MTRDeviceController
Expand Down Expand Up @@ -234,6 +239,16 @@ - (void)cleanup
{
VerifyOrDie(_cppCommissioner == nullptr);

if (_defaultDACVerifier) {
delete _defaultDACVerifier;
_defaultDACVerifier = nullptr;
}

if (_attestationTrustStoreBridge) {
delete _attestationTrustStoreBridge;
_attestationTrustStoreBridge = nullptr;
}

[self clearDeviceAttestationDelegateBridge];

if (_operationalCredentialsDelegate) {
Expand Down Expand Up @@ -388,9 +403,41 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams
// fabric information for the relevant fabric indices on controller
// bring-up.
commissionerParams.removeFromFabricTableOnShutdown = false;
commissionerParams.deviceAttestationVerifier = _factory.deviceAttestationVerifier;
commissionerParams.permitMultiControllerFabrics = startupParams.allowMultipleControllersPerFabric;

// Set up our attestation verifier. Assume we want to use the default
// one, until something tells us otherwise.
const chip::Credentials::AttestationTrustStore * trustStore;
if (startupParams.productAttestationAuthorityCertificates) {
_attestationTrustStoreBridge
= new MTRAttestationTrustStoreBridge(startupParams.productAttestationAuthorityCertificates);
trustStore = _attestationTrustStoreBridge;
} else {
// TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
trustStore = chip::Credentials::GetTestAttestationTrustStore();
}

_defaultDACVerifier = new chip::Credentials::DefaultDACVerifier(trustStore);

if (startupParams.certificationDeclarationCertificates) {
auto cdTrustStore = _defaultDACVerifier->GetCertificationDeclarationTrustStore();
if (cdTrustStore == nullptr) {
errorCode = CHIP_ERROR_INCORRECT_STATE;
}
if ([self checkForStartError:errorCode logMsg:kErrorCDCertStoreInit]) {
return;
}

for (NSData * cdSigningCert in startupParams.certificationDeclarationCertificates) {
errorCode = cdTrustStore->AddTrustedKey(AsByteSpan(cdSigningCert));
if ([self checkForStartError:errorCode logMsg:kErrorCDCertStoreInit]) {
return;
}
}
}

commissionerParams.deviceAttestationVerifier = _defaultDACVerifier;

auto & factory = chip::Controller::DeviceControllerFactory::GetInstance();

errorCode = factory.SetupCommissioner(commissionerParams, *_cppCommissioner);
Expand Down Expand Up @@ -725,7 +772,7 @@ - (BOOL)setOperationalCertificateIssuer:(nullable id<MTROperationalCertificateIs
} else {
// TODO: Once we are not supporting setNocChainIssuer this
// branch can just go away.
self->_cppCommissioner->SetDeviceAttestationVerifier(self->_factory.deviceAttestationVerifier);
self->_cppCommissioner->SetDeviceAttestationVerifier(self->_defaultDACVerifier);
}
return YES;
};
Expand Down
81 changes: 24 additions & 57 deletions src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#import "MTRDeviceControllerFactory.h"
#import "MTRDeviceControllerFactory_Internal.h"

#import "MTRAttestationTrustStoreBridge.h"
#import "MTRCertificates.h"
#import "MTRControllerAccessControl.h"
#import "MTRDemuxingStorage.h"
Expand All @@ -43,8 +42,6 @@
#include <credentials/FabricTable.h>
#include <credentials/GroupDataProviderImpl.h>
#include <credentials/PersistentStorageOpCertStore.h>
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
#include <crypto/PersistentStorageOperationalKeystore.h>
#include <crypto/RawKeySessionKeystore.h>
#include <lib/support/Pool.h>
Expand All @@ -58,15 +55,12 @@

static NSString * const kErrorPersistentStorageInit = @"Init failure while creating a persistent storage delegate";
static NSString * const kErrorSessionResumptionStorageInit = @"Init failure while creating a session resumption storage delegate";
static NSString * const kErrorAttestationTrustStoreInit = @"Init failure while creating the attestation trust store";
static NSString * const kErrorDACVerifierInit = @"Init failure while creating the device attestation verifier";
static NSString * const kErrorGroupProviderInit = @"Init failure while initializing group data provider";
static NSString * const kErrorControllersInit = @"Init controllers array failure";
static NSString * const kErrorCertificateValidityPolicyInit = @"Init certificate validity policy failure";
static NSString * const kErrorControllerFactoryInit = @"Init failure while initializing controller factory";
static NSString * const kErrorKeystoreInit = @"Init failure while initializing persistent storage keystore";
static NSString * const kErrorCertStoreInit = @"Init failure while initializing persistent storage operational certificate store";
static NSString * const kErrorCDCertStoreInit = @"Init failure while initializing Certificate Declaration Signing Keys store";
static NSString * const kErrorOtaProviderInit = @"Init failure while creating an OTA provider delegate";
static NSString * const kErrorSessionKeystoreInit = @"Init failure while initializing session keystore";

Expand All @@ -78,7 +72,6 @@ @interface MTRDeviceControllerFactory ()
@property (atomic, readonly) dispatch_queue_t chipWorkQueue;
@property (readonly) DeviceControllerFactory * controllerFactory;
@property (readonly) PersistentStorageDelegate * persistentStorageDelegate;
@property (readonly) MTRAttestationTrustStoreBridge * attestationTrustStoreBridge;
@property (readonly) MTROTAProviderDelegateBridge * otaProviderDelegateBridge;
@property (readonly) Crypto::RawKeySessionKeystore * sessionKeystore;
// We use TestPersistentStorageDelegate just to get an in-memory store to back
Expand All @@ -90,7 +83,12 @@ @interface MTRDeviceControllerFactory ()
@property (readonly) PersistentStorageOperationalKeystore * keystore;
@property (readonly) Credentials::PersistentStorageOpCertStore * opCertStore;
@property (readonly) MTROperationalBrowser * operationalBrowser;
@property () chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier;

// productAttestationAuthorityCertificates and certificationDeclarationCertificates are just copied
// from MTRDeviceControllerFactoryParams.
@property (readonly, nullable) NSArray<MTRCertificateDERBytes> * productAttestationAuthorityCertificates;
@property (readonly, nullable) NSArray<MTRCertificateDERBytes> * certificationDeclarationCertificates;

@property (readonly) BOOL advertiseOperational;
@property (nonatomic, readonly) Credentials::IgnoreCertificateValidityPeriodPolicy * certificateValidityPolicy;
@property (readonly) MTRSessionResumptionStorageBridge * sessionResumptionStorage;
Expand Down Expand Up @@ -291,16 +289,6 @@ - (void)cleanupInitObjects

- (void)cleanupStartupObjects
{
if (_deviceAttestationVerifier) {
delete _deviceAttestationVerifier;
_deviceAttestationVerifier = nullptr;
}

if (_attestationTrustStoreBridge) {
delete _attestationTrustStoreBridge;
_attestationTrustStoreBridge = nullptr;
}

if (_otaProviderDelegateBridge) {
delete _otaProviderDelegateBridge;
_otaProviderDelegateBridge = nullptr;
Expand Down Expand Up @@ -504,44 +492,8 @@ - (BOOL)startControllerFactory:(MTRDeviceControllerFactoryParams *)startupParams
return;
}

// Initialize device attestation verifier
const Credentials::AttestationTrustStore * trustStore;
if (startupParams.productAttestationAuthorityCertificates) {
_attestationTrustStoreBridge
= new MTRAttestationTrustStoreBridge(startupParams.productAttestationAuthorityCertificates);
if (_attestationTrustStoreBridge == nullptr) {
MTR_LOG_ERROR("Error: %@", kErrorAttestationTrustStoreInit);
errorCode = CHIP_ERROR_NO_MEMORY;
return;
}
trustStore = _attestationTrustStoreBridge;
} else {
// TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
trustStore = Credentials::GetTestAttestationTrustStore();
}
_deviceAttestationVerifier = new Credentials::DefaultDACVerifier(trustStore);
if (_deviceAttestationVerifier == nullptr) {
MTR_LOG_ERROR("Error: %@", kErrorDACVerifierInit);
errorCode = CHIP_ERROR_NO_MEMORY;
return;
}

if (startupParams.certificationDeclarationCertificates) {
auto cdTrustStore = _deviceAttestationVerifier->GetCertificationDeclarationTrustStore();
if (cdTrustStore == nullptr) {
MTR_LOG_ERROR("Error: %@", kErrorCDCertStoreInit);
errorCode = CHIP_ERROR_INCORRECT_STATE;
return;
}

for (NSData * cdSigningCert in startupParams.certificationDeclarationCertificates) {
errorCode = cdTrustStore->AddTrustedKey(AsByteSpan(cdSigningCert));
if (errorCode != CHIP_NO_ERROR) {
MTR_LOG_ERROR("Error: %@", kErrorCDCertStoreInit);
return;
}
}
}
_productAttestationAuthorityCertificates = [startupParams.productAttestationAuthorityCertificates copy];
_certificationDeclarationCertificates = [startupParams.certificationDeclarationCertificates copy];

chip::Controller::FactoryInitParams params;
if (startupParams.port != nil) {
Expand Down Expand Up @@ -827,6 +779,9 @@ - (MTRDeviceController * _Nullable)createControllerOnExistingFabric:(MTRDeviceCo
params:startupParams];
if (params == nil) {
fabricError = CHIP_ERROR_NO_MEMORY;
} else {
params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
}

return params;
Expand Down Expand Up @@ -879,6 +834,9 @@ - (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControl
params:startupParams];
if (params == nil) {
fabricError = CHIP_ERROR_NO_MEMORY;
} else {
params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
}
return params;
}
Expand All @@ -893,13 +851,22 @@ - (MTRDeviceController * _Nullable)createController:(MTRDeviceControllerStartupP
return [self _startDeviceController:startupParameters
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
return
auto * params =
[[MTRDeviceControllerStartupParamsInternal alloc] initForNewController:controller
fabricTable:fabricTable
keystore:self->_keystore
advertiseOperational:self.advertiseOperational
params:startupParameters
error:fabricError];
if (params != nil) {
if (params.productAttestationAuthorityCertificates == nil) {
params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
}
if (params.certificationDeclarationCertificates == nil) {
params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
}
}
return params;
}
error:error];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
namespace chip {
namespace Credentials {
class GroupDataProvider;
class DeviceAttestationVerifier;
} // namespace Credentials
} // namespace chip

Expand Down Expand Up @@ -70,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN

@property (readonly) chip::PersistentStorageDelegate * storageDelegate;
@property (readonly) chip::Credentials::GroupDataProvider * groupData;
@property (readonly) chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ MTR_NEWLY_AVAILABLE
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

/**
* The Product Attestation Authority certificates that are trusted to sign
* device attestation information (and in particular to sign Product Attestation
* Intermediate certificates, which then sign Device Attestation Certificates).
*
* Defaults to nil.
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
*/
@property (nonatomic, copy, nullable) NSArray<MTRCertificateDERBytes> * productAttestationAuthorityCertificates;

/**
* The Certification Declaration certificates whose public keys correspond to
* private keys that are trusted to sign certification declarations. Defaults
* to nil.
*
* These certificates are used in addition to, not replacing, the default set of
* well-known certification declaration signing keys.
*/
@property (nonatomic, copy, nullable) NSArray<MTRCertificateDERBytes> * certificationDeclarationCertificates;

/**
* Set an MTROperationalCertificateIssuer to call (on the provided queue) when
* operational certificates need to be provided during commissioning.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ - (instancetype)initWithStorageDelegate:(id<MTRDeviceControllerStorageDelegate>)
return nil;
}

_productAttestationAuthorityCertificates = nil;
_certificationDeclarationCertificates = nil;

_ipk = ipk;
_vendorID = vendorID;
_rootCertificate = rootCertificate;
Expand Down Expand Up @@ -601,6 +604,8 @@ - (instancetype)initForNewController:(MTRDeviceController *)controller
_allowMultipleControllersPerFabric = YES;
_storageDelegate = params.storageDelegate;
_storageDelegateQueue = params.storageDelegateQueue;
_productAttestationAuthorityCertificates = params.productAttestationAuthorityCertificates;
_certificationDeclarationCertificates = params.certificationDeclarationCertificates;

return self;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ MTR_HIDDEN

@property (nonatomic, assign, readonly) BOOL allowMultipleControllersPerFabric;

@property (nonatomic, nullable) NSArray<MTRCertificateDERBytes> * productAttestationAuthorityCertificates;
@property (nonatomic, nullable) NSArray<MTRCertificateDERBytes> * certificationDeclarationCertificates;

/**
* A storage delegate that can be provided when initializing the startup params.
* This must be provided if and only if the controller factory was initialized
Expand Down
Loading