blob: b445eb88cd130c6ec20976bd707593c57fbf286a [file] [log] [blame]
/**
* 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 <Matter/Matter.h>
// system dependencies
#import <XCTest/XCTest.h>
#import "MTRTestKeys.h"
@interface MatterCertificateTests : XCTestCase
@end
@implementation MatterCertificateTests
- (void)testGenerateRootCert
{
__auto_type * testKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(testKeys);
__auto_type * rootCert = [MTRCertificates createRootCertificate:testKeys issuerID:nil fabricID:nil error:nil];
XCTAssertNotNil(rootCert);
// Test round-trip through TLV format.
__auto_type * tlvCert = [MTRCertificates convertX509Certificate:rootCert];
XCTAssertNotNil(tlvCert);
__auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
XCTAssertNotNil(derCert);
XCTAssertEqualObjects(rootCert, derCert);
}
- (void)testGenerateIntermediateCert
{
__auto_type * rootKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(rootKeys);
__auto_type * rootCert = [MTRCertificates createRootCertificate:rootKeys issuerID:nil fabricID:nil error:nil];
XCTAssertNotNil(rootCert);
__auto_type * intermediateKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(intermediateKeys);
__auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys
rootCertificate:rootCert
intermediatePublicKey:intermediateKeys.publicKey
issuerID:nil
fabricID:nil
error:nil];
XCTAssertNotNil(intermediateCert);
// Test round-trip through TLV format.
__auto_type * tlvCert = [MTRCertificates convertX509Certificate:intermediateCert];
XCTAssertNotNil(tlvCert);
__auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
XCTAssertNotNil(derCert);
XCTAssertEqualObjects(intermediateCert, derCert);
}
- (void)testGenerateOperationalCertNoIntermediate
{
__auto_type * rootKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(rootKeys);
__auto_type * rootCert = [MTRCertificates createRootCertificate:rootKeys issuerID:nil fabricID:nil error:nil];
XCTAssertNotNil(rootCert);
__auto_type * operationalKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(operationalKeys);
__auto_type * cats = [[NSMutableArray alloc] initWithCapacity:3];
// High bits are identifier, low bits are version.
[cats addObject:@0x00010001];
[cats addObject:@0x00020001];
[cats addObject:@0x0003FFFF];
__auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:cats
error:nil];
XCTAssertNotNil(operationalCert);
// Test round-trip through TLV format.
__auto_type * tlvCert = [MTRCertificates convertX509Certificate:operationalCert];
XCTAssertNotNil(tlvCert);
__auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
XCTAssertNotNil(derCert);
XCTAssertEqualObjects(operationalCert, derCert);
}
- (void)testGenerateOperationalCertWithIntermediate
{
__auto_type * rootKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(rootKeys);
__auto_type * rootCert = [MTRCertificates createRootCertificate:rootKeys issuerID:nil fabricID:nil error:nil];
XCTAssertNotNil(rootCert);
__auto_type * intermediateKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(intermediateKeys);
__auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys
rootCertificate:rootCert
intermediatePublicKey:intermediateKeys.publicKey
issuerID:nil
fabricID:nil
error:nil];
XCTAssertNotNil(intermediateCert);
__auto_type * operationalKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(operationalKeys);
__auto_type * operationalCert = [MTRCertificates createOperationalCertificate:intermediateKeys
signingCertificate:intermediateCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:nil
error:nil];
XCTAssertNotNil(operationalCert);
// Test round-trip through TLV format.
__auto_type * tlvCert = [MTRCertificates convertX509Certificate:operationalCert];
XCTAssertNotNil(tlvCert);
__auto_type * derCert = [MTRCertificates convertMatterCertificate:tlvCert];
XCTAssertNotNil(derCert);
XCTAssertEqualObjects(operationalCert, derCert);
}
- (void)testGenerateOperationalCertErrorCases
{
__auto_type * rootKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(rootKeys);
__auto_type * rootCert = [MTRCertificates createRootCertificate:rootKeys issuerID:nil fabricID:nil error:nil];
XCTAssertNotNil(rootCert);
__auto_type * operationalKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(operationalKeys);
__auto_type * longCats = [[NSMutableArray alloc] initWithCapacity:4];
[longCats addObject:@0x00010001];
[longCats addObject:@0x00020001];
[longCats addObject:@0x00030001];
[longCats addObject:@0x00040001];
__auto_type * catsWithSameIdentifier = [[NSMutableArray alloc] initWithCapacity:3];
// High bits are identifier, low bits are version.
[catsWithSameIdentifier addObject:@0x00010001];
[catsWithSameIdentifier addObject:@0x00020001];
[catsWithSameIdentifier addObject:@0x00010002];
__auto_type * catsWithDuplicatedCAT = [[NSMutableArray alloc] initWithCapacity:3];
// High bits are identifier, low bits are version.
[catsWithDuplicatedCAT addObject:@0x00010001];
[catsWithDuplicatedCAT addObject:@0x00020001];
[catsWithDuplicatedCAT addObject:@0x00010001];
__auto_type * catsWithInvalidVersion = [[NSMutableArray alloc] initWithCapacity:2];
// High bits are identifier, low bits are version.
[catsWithInvalidVersion addObject:@0x00010001];
[catsWithInvalidVersion addObject:@0x00020000];
// Check basic case works
__auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:nil
error:nil];
XCTAssertNotNil(operationalCert);
// CATs too long
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:longCats
error:nil];
XCTAssertNil(operationalCert);
// Multiple CATs with the same identifier but different versions
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:catsWithSameIdentifier
error:nil];
XCTAssertNil(operationalCert);
// Multiple CATs with the same identifier and same version
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:catsWithDuplicatedCAT
error:nil];
XCTAssertNil(operationalCert);
// CAT with invalid version
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:catsWithInvalidVersion
error:nil];
XCTAssertNil(operationalCert);
// Signing key mismatch
operationalCert = [MTRCertificates createOperationalCertificate:operationalKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@1
caseAuthenticatedTags:nil
error:nil];
XCTAssertNil(operationalCert);
// Invalid fabric id
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@0
nodeID:@1
caseAuthenticatedTags:nil
error:nil];
XCTAssertNil(operationalCert);
// Undefined node id
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@0
caseAuthenticatedTags:nil
error:nil];
XCTAssertNil(operationalCert);
// Non-operational node id
operationalCert = [MTRCertificates createOperationalCertificate:rootKeys
signingCertificate:rootCert
operationalPublicKey:operationalKeys.publicKey
fabricID:@1
nodeID:@(0xFFFFFFFFFFFFFFFFLLU)
caseAuthenticatedTags:nil
error:nil];
XCTAssertNil(operationalCert);
}
- (void)testGenerateCSR
{
__auto_type * testKeys = [[MTRTestKeys alloc] init];
XCTAssertNotNil(testKeys);
__auto_type * csr = [MTRCertificates createCertificateSigningRequest:testKeys error:nil];
XCTAssertNotNil(csr);
__auto_type * publicKey = [MTRCertificates extractPublicKeyFromCertificateSigningRequest:csr error:nil];
XCTAssertNotNil(publicKey);
SecKeyRef originalKeyRef = [testKeys publicKey];
XCTAssertTrue(originalKeyRef != NULL);
NSData * originalPublicKey = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(originalKeyRef, nil);
XCTAssertNotNil(originalPublicKey);
XCTAssertEqualObjects(publicKey, originalPublicKey);
}
@end