diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 403bc8a0906183..44d3b63712d426 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -18,6 +18,7 @@ #import "MTRDeviceController_Internal.h" +#import "MTRAttestationTrustStoreBridge.h" #import "MTRBaseDevice_Internal.h" #import "MTRCommissionableBrowser.h" #import "MTRCommissionableBrowserResult_Internal.h" @@ -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); @@ -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; @@ -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 @@ -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) { @@ -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); @@ -725,7 +772,7 @@ - (BOOL)setOperationalCertificateIssuer:(nullable id_cppCommissioner->SetDeviceAttestationVerifier(self->_factory.deviceAttestationVerifier); + self->_cppCommissioner->SetDeviceAttestationVerifier(self->_defaultDACVerifier); } return YES; }; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 95282450952ef2..97785a45a9db99 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -17,7 +17,6 @@ #import "MTRDeviceControllerFactory.h" #import "MTRDeviceControllerFactory_Internal.h" -#import "MTRAttestationTrustStoreBridge.h" #import "MTRCertificates.h" #import "MTRControllerAccessControl.h" #import "MTRDemuxingStorage.h" @@ -43,8 +42,6 @@ #include #include #include -#include -#include #include #include #include @@ -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"; @@ -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 @@ -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 * productAttestationAuthorityCertificates; +@property (readonly, nullable) NSArray * certificationDeclarationCertificates; + @property (readonly) BOOL advertiseOperational; @property (nonatomic, readonly) Credentials::IgnoreCertificateValidityPeriodPolicy * certificateValidityPolicy; @property (readonly) MTRSessionResumptionStorageBridge * sessionResumptionStorage; @@ -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; @@ -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) { @@ -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; @@ -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; } @@ -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]; } diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h index 4ffcb3af545506..9717f5062c93f5 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h @@ -30,7 +30,6 @@ namespace chip { namespace Credentials { class GroupDataProvider; - class DeviceAttestationVerifier; } // namespace Credentials } // namespace chip @@ -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 diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h index 7087bd87fbaf8e..b592849f066974 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h @@ -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. + */ +@property (nonatomic, copy, nullable) NSArray * 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 * certificationDeclarationCertificates; + /** * Set an MTROperationalCertificateIssuer to call (on the provided queue) when * operational certificates need to be provided during commissioning. diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm index 9fb71429a07720..c4ad49dda014cd 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm @@ -262,6 +262,9 @@ - (instancetype)initWithStorageDelegate:(id) return nil; } + _productAttestationAuthorityCertificates = nil; + _certificationDeclarationCertificates = nil; + _ipk = ipk; _vendorID = vendorID; _rootCertificate = rootCertificate; @@ -601,6 +604,8 @@ - (instancetype)initForNewController:(MTRDeviceController *)controller _allowMultipleControllersPerFabric = YES; _storageDelegate = params.storageDelegate; _storageDelegateQueue = params.storageDelegateQueue; + _productAttestationAuthorityCertificates = params.productAttestationAuthorityCertificates; + _certificationDeclarationCertificates = params.certificationDeclarationCertificates; return self; } diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h index 53cec273ebdc52..cb7540c2e16e65 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h @@ -96,6 +96,9 @@ MTR_HIDDEN @property (nonatomic, assign, readonly) BOOL allowMultipleControllersPerFabric; +@property (nonatomic, nullable) NSArray * productAttestationAuthorityCertificates; +@property (nonatomic, nullable) NSArray * 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