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

Fix APIs involved in the MTROperationalCredentialsDelegate. #23893

Merged
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
59 changes: 59 additions & 0 deletions src/darwin/Framework/CHIP/MTRAttestationInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,71 @@

#import <Foundation/Foundation.h>

#import <Matter/MTRCertificates.h>
#import <Matter/MTRDefines.h>

NS_ASSUME_NONNULL_BEGIN

/**
* Represents information relating to product attestation.
*
*/
MTR_NEWLY_AVAILABLE
@interface MTRAttestationInfo : NSObject

/**
* The attestation challenge from the secure session.
*/
@property (nonatomic, copy, readonly) NSData * challenge;
/**
* The attestation nonce from the AttestationRequest command.
*/
@property (nonatomic, copy, readonly) NSData * nonce;
/**
* The TLV-encoded attestation_elements_message that was used to find the
* certificationDeclaration and firmwareInfo.
*/
@property (nonatomic, copy, readonly) MTRTLVBytes elementsTLV;
/**
* A signature, using the device attestation private key of the device that sent
* the attestation information, over the concatenation of elementsTLV and the
* attestation challenge from the secure session.
*/
@property (nonatomic, copy, readonly) NSData * elementsSignature;
/**
* The device attestation certificate for the device. This can be used to
* verify signatures created with the device attestation private key.
*/
@property (nonatomic, copy, readonly) MTRCertificateDERBytes deviceAttestationCertificate;
/**
* The product attestation intermediate certificate that can be used to verify
* the authenticity of the device attestation certificate.
*/
@property (nonatomic, copy, readonly) MTRCertificateDERBytes productAttestationIntermediateCertificate;
/**
* The certification declaration of the device. This is a DER-encoded string
* representing a CMS-formatted certification declaration.
*/
@property (nonatomic, copy, readonly) NSData * certificationDeclaration;
/*
* Firmware information, if any, provided in the elementsTLV. The encoding of
* this is not currently specified, but if present this must match the
* Distributed Compliance Ledger entry for the device.
*/
@property (nonatomic, copy, readonly, nullable) NSData * firmwareInfo;

- (instancetype)initWithChallenge:(NSData *)challenge
nonce:(NSData *)nonce
elementsTLV:(MTRTLVBytes)elementsTLV
elementsSignature:(NSData *)elementsSignature
deviceAttestationCertificate:(MTRCertificateDERBytes)deviceAttestationCertificate
productAttestationIntermediateCertificate:(MTRCertificateDERBytes)processAttestationIntermediateCertificate
certificationDeclaration:(NSData *)certificationDeclaration
firmwareInfo:(NSData *)firmwareInfo;

@end

MTR_NEWLY_DEPRECATED("Please use MTRAttestationInfo")
@interface AttestationInfo : NSObject

@property (nonatomic, copy) NSData * challenge;
Expand Down
26 changes: 26 additions & 0 deletions src/darwin/Framework/CHIP/MTRAttestationInfo.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@

NS_ASSUME_NONNULL_BEGIN

@implementation MTRAttestationInfo : NSObject

- (instancetype)initWithChallenge:(NSData *)challenge
nonce:(NSData *)nonce
elementsTLV:(MTRTLVBytes)elementsTLV
elementsSignature:(NSData *)elementsSignature
deviceAttestationCertificate:(MTRCertificateDERBytes)deviceAttestationCertificate
productAttestationIntermediateCertificate:(MTRCertificateDERBytes)productAttestationIntermediateCertificate
certificationDeclaration:(NSData *)certificationDeclaration
firmwareInfo:(NSData *)firmwareInfo
{
if (self = [super init]) {
_challenge = challenge;
_nonce = nonce;
_elementsTLV = elementsTLV;
_elementsSignature = elementsSignature;
_deviceAttestationCertificate = deviceAttestationCertificate;
_productAttestationIntermediateCertificate = productAttestationIntermediateCertificate;
_certificationDeclaration = certificationDeclaration;
_firmwareInfo = firmwareInfo;
}
return self;
}

@end

@implementation AttestationInfo : NSObject

- (instancetype)initWithChallenge:(NSData *)challenge
Expand Down
40 changes: 39 additions & 1 deletion src/darwin/Framework/CHIP/MTRCSRInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,50 @@

#import <Foundation/Foundation.h>

#import <Matter/MTRDefines.h>

typedef NSData * MTRCSRDERBytes;

NS_ASSUME_NONNULL_BEGIN

/**
* Represents information relating to NOC CSR.
* Represents information relating to a certificate signing request for a Matter
* operational certificate.
*/
MTR_NEWLY_AVAILABLE
@interface MTROperationalCSRInfo : NSObject

/**
* DER-encoded certificate signing request.
*/
@property (nonatomic, copy, readonly) MTRCSRDERBytes csr;
/**
* The nonce provided in the original CSRRequest command hat led to this CSR
* being created.
*/
@property (nonatomic, copy, readonly) NSData * csrNonce;
/**
* TLV-encoded nocsr-elements structure. This includes the "csr" and "csrNonce"
* fields, and can include additional vendor-specific information.
*/
@property (nonatomic, copy, readonly) MTRTLVBytes csrElementsTLV;
/**
* A signature, using the device attestation private key of the device that
* created the CSR, over the concatenation of csrElementsTLV and the attestation
* challenge from the secure session.
*
* The attestation challenge is available in MTRAttestionInfo.
*/
@property (nonatomic, copy, readonly) NSData * attestationSignature;

- (instancetype)initWithCSR:(MTRCSRDERBytes)csr
csrNonce:(NSData *)csrNonce
csrElementsTLV:(MTRTLVBytes)csrElementsTLV
attestationSignature:(NSData *)attestationSignature;

@end

MTR_NEWLY_DEPRECATED("Please use MTROperationalCSRInfo")
@interface CSRInfo : NSObject

@property (nonatomic, copy) NSData * nonce;
Expand Down
17 changes: 17 additions & 0 deletions src/darwin/Framework/CHIP/MTRCSRInfo.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@

NS_ASSUME_NONNULL_BEGIN

@implementation MTROperationalCSRInfo : NSObject

- (instancetype)initWithCSR:(MTRCSRDERBytes)csr
csrNonce:(NSData *)csrNonce
csrElementsTLV:(MTRTLVBytes)csrElementsTLV
attestationSignature:(NSData *)attestationSignature;
{
if (self = [super init]) {
_csr = csr;
_csrNonce = csrNonce;
_csrElementsTLV = csrElementsTLV;
_attestationSignature = attestationSignature;
}
return self;
}
@end

@implementation CSRInfo : NSObject

- (instancetype)initWithNonce:(NSData *)nonce
Expand Down
2 changes: 2 additions & 0 deletions src/darwin/Framework/CHIP/MTRDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@
#else
#define MTR_EXTERN extern MTR_EXPORT
#endif

typedef NSData * MTRTLVBytes;
19 changes: 4 additions & 15 deletions src/darwin/Framework/CHIP/MTRDeviceController.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#import <Foundation/Foundation.h>

#import <Matter/MTRNOCChainIssuer.h>
#import <Matter/MTROperationalCertificateIssuer.h>

@class MTRBaseDevice;

Expand Down Expand Up @@ -117,20 +117,6 @@ typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NS
*/
- (void)setDeviceControllerDelegate:(id<MTRDeviceControllerDelegate>)delegate queue:(dispatch_queue_t)queue MTR_NEWLY_AVAILABLE;

/**
* Sets this MTRDeviceController to use the given issuer for issuing operational certs. By default, the MTRDeviceController uses an
* internal issuer.
*
* When a nocChainIssuer is set, the device commissioner will delegate verification to the chip::Credentials::PartialDACVerifier so
* that DAC chain and CD validation can be performed by custom code triggered by MTRNOCChainIssuer.onNOCChainGenerationNeeded().
* Otherwise, the device commissioner uses the chip::Credentials::DefaultDACVerifier
*
* @param[in] nocChainIssuer the NOC Chain issuer to use for issuer operational certs
*
* @param[in] queue The queue on which the callbacks will be delivered
*/
- (void)setNocChainIssuer:(id<MTRNOCChainIssuer>)nocChainIssuer queue:(dispatch_queue_t)queue;

/**
* Return the attestation challenge for the secure session of the device being commissioned.
*
Expand Down Expand Up @@ -221,6 +207,9 @@ typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NS
- (void)setPairingDelegate:(id<MTRDevicePairingDelegate>)delegate
queue:(dispatch_queue_t)queue MTR_NEWLY_DEPRECATED("Please use setDeviceControllerDelegate:");

- (void)setNocChainIssuer:(id<MTRNOCChainIssuer>)nocChainIssuer
queue:(dispatch_queue_t)queue
MTR_NEWLY_DEPRECATED("Please set the operationalCertificateIssuer in the MTRDeviceControllerStartupParams instead.");
@end

NS_ASSUME_NONNULL_END
100 changes: 93 additions & 7 deletions src/darwin/Framework/CHIP/MTRDeviceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory queue:(dis
return nil;
}

_operationalCredentialsDelegate = new MTROperationalCredentialsDelegate();
_operationalCredentialsDelegate = new MTROperationalCredentialsDelegate(self);
if ([self checkForInitError:(_operationalCredentialsDelegate != nullptr) logMsg:kErrorOperationalCredentialsInit]) {
return nil;
}
Expand Down Expand Up @@ -341,9 +341,21 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams

if (commissionerInitialized == NO) {
[self cleanupAfterStartup];
return NO;
}

// TODO: Once setNocChainIssuer no longer needs to be supported,
// we can just move the internals of
// setOperationalCertificateIssuer into the sync-dispatched block
// above.
if (![self setOperationalCertificateIssuer:startupParams.operationalCertificateIssuer
queue:startupParams.operationalCertificateIssuerQueue]) {
MTR_LOG_ERROR("operationalCertificateIssuer and operationalCertificateIssuerQueue must both be nil or both be non-nil");
[self cleanupAfterStartup];
return NO;
}

return commissionerInitialized;
return YES;
}

- (NSNumber *)controllerNodeID
Expand Down Expand Up @@ -548,20 +560,31 @@ - (void)setDeviceControllerDelegate:(id<MTRDeviceControllerDelegate>)delegate qu
});
}

- (void)setNocChainIssuer:(id<MTRNOCChainIssuer>)nocChainIssuer queue:(dispatch_queue_t)queue
- (BOOL)setOperationalCertificateIssuer:(nullable id<MTROperationalCertificateIssuer>)operationalCertificateIssuer
queue:(nullable dispatch_queue_t)queue
{
VerifyOrReturn([self checkIsRunning]);
if ((operationalCertificateIssuer != nil && queue == nil) || (operationalCertificateIssuer == nil && queue != nil)) {
return NO;
}

VerifyOrReturnValue([self checkIsRunning], NO);

__block BOOL success = NO;
dispatch_sync(_chipWorkQueue, ^{
VerifyOrReturn([self checkIsRunning]);

if (nocChainIssuer != nil) {
self->_operationalCredentialsDelegate->SetNocChainIssuer(nocChainIssuer, queue);
if (operationalCertificateIssuer != nil) {
self->_operationalCredentialsDelegate->SetOperationalCertificateIssuer(operationalCertificateIssuer, queue);
self->_cppCommissioner->SetDeviceAttestationVerifier(_partialDACVerifier);
} else {
self->_cppCommissioner->SetDeviceAttestationVerifier(chip::Credentials::GetDeviceAttestationVerifier());
// TODO: Once we are not supporting setNocChainIssuer this
// branch can just go away.
self->_cppCommissioner->SetDeviceAttestationVerifier(_factory.deviceAttestationVerifier);
}
success = YES;
});

return success;
}

+ (nullable NSData *)computePASEVerifierForSetupPasscode:(NSNumber *)setupPasscode
Expand Down Expand Up @@ -882,6 +905,64 @@ - (void)onPairingDeleted:(NSError * _Nullable)error

@end

/**
* Shim to allow us to treat an MTRNOCChainIssuer as an
* MTROperationalCertificateIssuer.
*/
@interface MTROperationalCertificateChainIssuerShim : NSObject <MTROperationalCertificateIssuer>
@property (nonatomic, readonly) id<MTRNOCChainIssuer> nocChainIssuer;
- (instancetype)initWithIssuer:(id<MTRNOCChainIssuer>)nocChainIssuer;
@end

@implementation MTROperationalCertificateChainIssuerShim
- (instancetype)initWithIssuer:(id<MTRNOCChainIssuer>)nocChainIssuer
{
if (self = [super init]) {
_nocChainIssuer = nocChainIssuer;
}
return self;
}

- (void)issueOperationalCertificateForRequest:(MTROperationalCSRInfo *)csrInfo
attestationInfo:(MTRAttestationInfo *)attestationInfo
controller:(MTRDeviceController *)controller
completion:(MTROperationalCertificateIssuedHandler)completion
{
CSRInfo * oldCSRInfo = [[CSRInfo alloc] initWithNonce:csrInfo.csrNonce
elements:csrInfo.csrElementsTLV
elementsSignature:csrInfo.attestationSignature
csr:csrInfo.csr];
NSData * _Nullable firmwareInfo = attestationInfo.firmwareInfo;
if (firmwareInfo == nil) {
firmwareInfo = [NSData data];
}
AttestationInfo * oldAttestationInfo =
[[AttestationInfo alloc] initWithChallenge:attestationInfo.challenge
nonce:attestationInfo.nonce
elements:attestationInfo.elementsTLV
elementsSignature:attestationInfo.elementsSignature
dac:attestationInfo.deviceAttestationCertificate
pai:attestationInfo.productAttestationIntermediateCertificate
certificationDeclaration:attestationInfo.certificationDeclaration
firmwareInfo:firmwareInfo];
[self.nocChainIssuer
onNOCChainGenerationNeeded:oldCSRInfo
attestationInfo:oldAttestationInfo
onNOCChainGenerationComplete:^(NSData * operationalCertificate, NSData * intermediateCertificate, NSData * rootCertificate,
NSData * _Nullable ipk, NSNumber * _Nullable adminSubject, NSError * __autoreleasing * error) {
auto * info = [[MTROperationalCertificateInfo alloc] initWithOperationalCertificate:operationalCertificate
intermediateCertificate:intermediateCertificate
rootCertificate:rootCertificate
adminSubject:adminSubject];
completion(info, nil);
if (error != nil) {
*error = nil;
}
}];
}

@end

@implementation MTRDeviceController (Deprecated)

- (NSNumber *)controllerNodeId
Expand Down Expand Up @@ -1105,4 +1186,9 @@ - (void)setPairingDelegate:(id<MTRDevicePairingDelegate>)delegate queue:(dispatc
[self setDeviceControllerDelegate:delegateShim queue:queue];
}

- (void)setNocChainIssuer:(id<MTRNOCChainIssuer>)nocChainIssuer queue:(dispatch_queue_t)queue
{
[self setOperationalCertificateIssuer:[[MTROperationalCertificateChainIssuerShim alloc] initWithIssuer:nocChainIssuer]
queue:queue];
}
@end
Loading