blob: 8efc8989abb68915702a9de312870a1a93c6218f [file] [log] [blame]
/*
* Copyright (c) 2023 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.
*/
// module headers
#import <Matter/Matter.h>
#import "MTRErrorTestUtils.h"
#import "MTRTestKeys.h"
#import "MTRTestStorage.h"
// system dependencies
#import <XCTest/XCTest.h>
static const uint16_t kPairingTimeoutInSeconds = 10;
static const uint64_t kDeviceId = 0x12344321;
static NSString * kOnboardingPayload = @"MT:-24J0AFN00KA0648G00";
static const uint16_t kLocalPort = 5541;
static const uint16_t kTestVendorId = 0xFFF1u;
// Singleton controller we use.
static MTRDeviceController * sController = nil;
// Keys we can use to restart the controller.
static MTRTestKeys * sTestKeys = nil;
@interface MTROperationalCertificateIssureTestDeviceControllerDelegate : NSObject <MTRDeviceControllerDelegate>
@property (nonatomic, strong) XCTestExpectation * expectation;
@end
@implementation MTROperationalCertificateIssureTestDeviceControllerDelegate
- (id)initWithExpectation:(XCTestExpectation *)expectation
{
self = [super init];
if (self) {
_expectation = expectation;
}
return self;
}
- (void)controller:(MTRDeviceController *)controller commissioningSessionEstablishmentDone:(NSError *)error
{
XCTAssertEqual(error.code, 0);
NSError * commissionError = nil;
[sController commissionNodeWithID:@(kDeviceId)
commissioningParams:[[MTRCommissioningParameters alloc] init]
error:&commissionError];
XCTAssertNil(commissionError);
// Keep waiting for controller:commissioningComplete:
}
- (void)controller:(MTRDeviceController *)controller commissioningComplete:(NSError *)error
{
XCTAssertNotNil(error);
XCTAssertEqual(error.domain, MTRErrorDomain);
XCTAssertEqual(error.code, MTRErrorCodeIntegrityCheckFailed);
[_expectation fulfill];
_expectation = nil;
}
@end
@interface OperationalCertificateIssuer : NSObject <MTROperationalCertificateIssuer>
@property (nonatomic, readonly) BOOL shouldSkipAttestationCertificateValidation;
@end
@implementation OperationalCertificateIssuer
- (instancetype)init
{
if (self = [super init]) {
_shouldSkipAttestationCertificateValidation = NO;
}
return self;
}
- (void)issueOperationalCertificateForRequest:(MTROperationalCSRInfo *)csrInfo
attestationInfo:(MTRDeviceAttestationInfo *)attestationInfo
controller:(MTRDeviceController *)controller
completion:(void (^)(MTROperationalCertificateChain * _Nullable info,
NSError * _Nullable error))completion
{
XCTAssertNotNil(csrInfo);
XCTAssertNotNil(attestationInfo);
XCTAssertEqual(controller, sController);
__auto_type * csrInfoCopy = [[MTROperationalCSRInfo alloc] initWithCSRElementsTLV:csrInfo.csrElementsTLV
attestationSignature:csrInfo.attestationSignature];
XCTAssertEqualObjects(csrInfoCopy.csr, csrInfo.csr);
XCTAssertEqualObjects(csrInfoCopy.csrNonce, csrInfo.csrNonce);
XCTAssertEqualObjects(csrInfoCopy.csrElementsTLV, csrInfo.csrElementsTLV);
XCTAssertEqualObjects(csrInfoCopy.attestationSignature, csrInfo.attestationSignature);
completion(nil, [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeIntegrityCheckFailed userInfo:nil]);
}
@end
@interface MTROperationalCertificateIssuerTests : XCTestCase
@end
@implementation MTROperationalCertificateIssuerTests
- (void)setUp
{
[super setUp];
[self setContinueAfterFailure:NO];
}
- (void)testFailedCertificateIssuance
{
XCTestExpectation * expectation = [self expectationWithDescription:@"Pairing Complete"];
__auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
XCTAssertNotNil(factory);
__auto_type * storage = [[MTRTestStorage alloc] init];
__auto_type * factoryParams = [[MTRDeviceControllerFactoryParams alloc] initWithStorage:storage];
factoryParams.port = @(kLocalPort);
BOOL ok = [factory startControllerFactory:factoryParams error:nil];
XCTAssertTrue(ok);
__auto_type * testKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(testKeys);
sTestKeys = testKeys;
__auto_type * certificateIssuer = [[OperationalCertificateIssuer alloc] init];
// Needs to match what startControllerOnExistingFabric calls elsewhere in
// this file do.
__auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:testKeys.ipk fabricID:@(1) nocSigner:testKeys];
params.vendorID = @(kTestVendorId);
params.operationalCertificateIssuer = certificateIssuer;
params.operationalCertificateIssuerQueue = dispatch_get_main_queue();
MTRDeviceController * controller = [factory createControllerOnNewFabric:params error:nil];
XCTAssertNotNil(controller);
sController = controller;
__auto_type * deviceControllerDelegate =
[[MTROperationalCertificateIssureTestDeviceControllerDelegate alloc] initWithExpectation:expectation];
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.device_controller_delegate", DISPATCH_QUEUE_SERIAL);
[controller setDeviceControllerDelegate:deviceControllerDelegate queue:callbackQueue];
NSError * error;
__auto_type * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:kOnboardingPayload error:&error];
XCTAssertNotNil(payload);
XCTAssertNil(error);
[controller setupCommissioningSessionWithPayload:payload newNodeID:@(kDeviceId) error:&error];
XCTAssertNil(error);
[self waitForExpectationsWithTimeout:kPairingTimeoutInSeconds handler:nil];
[controller shutdown];
XCTAssertFalse([controller isRunning]);
[factory stopControllerFactory];
}
@end