diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload.h b/src/darwin/Framework/CHIP/MTRSetupPayload.h index d1cd5550bcf800..99a9bb844a7302 100644 --- a/src/darwin/Framework/CHIP/MTRSetupPayload.h +++ b/src/darwin/Framework/CHIP/MTRSetupPayload.h @@ -175,7 +175,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) /** * Generate a random Matter-valid setup PIN. */ -+ (NSUInteger)generateRandomPIN; ++ (NSUInteger)generateRandomPIN MTR_NEWLY_DEPRECATED("Please use generateRandomSetupPasscode"); /** * Generate a random Matter-valid setup passcode. @@ -214,6 +214,12 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) */ - (NSString * _Nullable)qrCodeString MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)); +/** + * Check whether the provided setup passcode (represented as an unsigned + * integer) is a valid setup passcode. + */ ++ (BOOL)isValidSetupPasscode:(NSNumber *)setupPasscode MTR_NEWLY_AVAILABLE; + @end MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)) diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload.mm b/src/darwin/Framework/CHIP/MTRSetupPayload.mm index c4694884ea829d..f85d785071176a 100644 --- a/src/darwin/Framework/CHIP/MTRSetupPayload.mm +++ b/src/darwin/Framework/CHIP/MTRSetupPayload.mm @@ -476,6 +476,17 @@ - (nullable NSString *)qrCodeString return [self qrCodeStringSkippingValidation:NO]; } ++ (BOOL)isValidSetupPasscode:(NSNumber *)setupPasscode +{ + using namespace chip; + + uint64_t passCode = setupPasscode.unsignedLongLongValue; + if (!CanCastTo(passCode)) { + return NO; + } + return SetupPayload::IsValidSetupPIN(static_cast(passCode)); +} + - (nullable NSString *)qrCodeStringSkippingValidation:(BOOL)allowInvalid { chip::QRCodeSetupPayloadGenerator generator(_payload); diff --git a/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m b/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m index 6f53305f943a69..df99c3b7cda8c1 100644 --- a/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m +++ b/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m @@ -439,4 +439,39 @@ - (void)testDescriptionShowsUnknownDiscoveryMethods XCTAssertNotEqualObjects(a.description, b.description); } +- (uint32)generateRepeatedDigitPasscode:(uint8_t)digit +{ + // "digit" is expected to be a single digit. Generates a number that has + // that digit repeated 8 times. + uint32_t passcode = 0; + for (int i = 0; i < 8; ++i) { + passcode = passcode * 10 + digit; + } + return passcode; +} + +- (void)testValidSetupPasscode +{ + // First, check the repeated-digit cases. + for (uint8_t digit = 0; digit <= 9; ++digit) { + XCTAssertFalse([MTRSetupPayload isValidSetupPasscode:@([self generateRepeatedDigitPasscode:digit])]); + } + + // Then the sequential special cases. + XCTAssertFalse([MTRSetupPayload isValidSetupPasscode:@(12345678)]); + XCTAssertFalse([MTRSetupPayload isValidSetupPasscode:@(87654321)]); + + // Then the "too big" cases: + XCTAssertFalse([MTRSetupPayload isValidSetupPasscode:@(100000000)]); + XCTAssertFalse([MTRSetupPayload isValidSetupPasscode:@(1lu << 27)]); + XCTAssertFalse([MTRSetupPayload isValidSetupPasscode:@((1llu << 32) + 1)]); + + // Now some tests for known-valid passcodes: + XCTAssertTrue([MTRSetupPayload isValidSetupPasscode:@(1)]); + XCTAssertTrue([MTRSetupPayload isValidSetupPasscode:@(78654321)]); + + // And we should only generate valid ones. + XCTAssertTrue([MTRSetupPayload isValidSetupPasscode:[MTRSetupPayload generateRandomSetupPasscode]]); +} + @end