Skip to content

Commit

Permalink
Reset the wrong code retry attempts if a valid credential is presented
Browse files Browse the repository at this point in the history
- Provide a ResetWrongCodeEntryAttempts for apps to use to reset the wrong entry attempts

- Update DL_LockUnlock.yaml to test resetting the wrong code retry attempts
  • Loading branch information
nivi-apple committed Mar 7, 2023
1 parent 4203370 commit 82dee1a
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 74 deletions.
18 changes: 16 additions & 2 deletions src/app/clusters/door-lock-server/door-lock-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLo
// Schedule auto-relocking
if (success && LockOperationTypeEnum::kUnlock == opType)
{
// Reset code wrong entry attempts (in case there were any incorrect wrong code retries prior) since unlock was a success.
ResetWrongCodeEntryAttempts(endpointId);

// appclusters.pdf 5.3.3.25:
// The number of seconds to wait after unlocking a lock before it automatically locks again. 0=disabled. If set, unlock
// operations from any source will be timed. For one time unlock with timeout use the specific command.
Expand Down Expand Up @@ -181,7 +184,13 @@ bool DoorLockServer::SetPrivacyModeButton(chip::EndpointId endpointId, bool isEn
return SetAttribute(endpointId, Attributes::EnablePrivacyModeButton::Id, Attributes::EnablePrivacyModeButton::Set, isEnabled);
}

bool DoorLockServer::TrackWrongCodeEntry(chip::EndpointId endpointId)
/**
* @brief Handles a wrong code entry attempt. If the number of wrong entry attempts exceeds the max limit, engage lockout.
* Otherwise increment the number of incorrect attempts by 1.
*
* @param endpointId
*/
bool DoorLockServer::HandleWrongCodeEntry(chip::EndpointId endpointId)
{
auto endpointContext = getContext(endpointId);
if (nullptr == endpointContext)
Expand Down Expand Up @@ -3352,7 +3361,12 @@ bool DoorLockServer::HandleRemoteLockOperation(chip::app::CommandHandler * comma
exit:
if (!success && reason == OperationErrorEnum::kInvalidCredential)
{
TrackWrongCodeEntry(endpoint);
HandleWrongCodeEntry(endpoint);
}

// Reset the wrong code retry attempts if a valid credential is presented
if (success && pinCode.HasValue()) {
ResetWrongCodeEntryAttempts(endpoint);
}

// Send command response
Expand Down
13 changes: 12 additions & 1 deletion src/app/clusters/door-lock-server/door-lock-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class DoorLockServer
bool SetOneTouchLocking(chip::EndpointId endpointId, bool isEnabled);
bool SetPrivacyModeButton(chip::EndpointId endpointId, bool isEnabled);

bool TrackWrongCodeEntry(chip::EndpointId endpointId);
bool HandleWrongCodeEntry(chip::EndpointId endpointId);

bool GetAutoRelockTime(chip::EndpointId endpointId, uint32_t & autoRelockTime);
bool GetNumberOfUserSupported(chip::EndpointId endpointId, uint16_t & numberOfUsersSupported);
Expand Down Expand Up @@ -180,6 +180,17 @@ class DoorLockServer
return GetFeatures(endpointId).Has(DoorLockFeature::kUser) && SupportsAnyCredential(endpointId);
}

inline void ResetWrongCodeEntryAttempts(chip::EndpointId endpointId)
{
auto endpointContext = getContext(endpointId);
if (nullptr == endpointContext)
{
ChipLogError(Zcl, "Failed to reset wrong code entry attempts. No context for endpoint %d", endpointId);
return;
}
endpointContext->wrongCodeEntryAttempts = 0;
}

bool OnFabricRemoved(chip::EndpointId endpointId, chip::FabricIndex fabricIndex);

static void DoorLockOnAutoRelockCallback(chip::System::Layer *, void * callbackContext);
Expand Down
72 changes: 63 additions & 9 deletions src/app/tests/suites/DL_LockUnlock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,10 @@ tests:
arguments:
value: 0

- label: "Read the lockout timeout"
command: "readAttribute"
attribute: "UserCodeTemporaryDisableTime"
response:
value: 10
# Test resetting wrong code entry retry attempts
# Set the retry limit to 3. Try to unlock with incorrect PIN 2 times followed by a third time
# with correct PIN code. The retry attempts should be reset to 0 and we can now retry
# 3 times again before lockout happens. Unlock the door after the lockout timeout.

- label: "Set the WrongCodeEntryLimit to small value so we can test lockout"
command: "writeAttribute"
Expand Down Expand Up @@ -270,7 +269,54 @@ tests:
response:
error: FAILURE

- label: "Try to unlock the door with invalid PIN for the third time"
- label: "Try to unlock the door with valid PIN for the third time"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
arguments:
values:
- name: "PINCode"
value: "123456"

- label: "Verify that lock state attribute value is set to Unlocked"
command: "readAttribute"
attribute: "LockState"
response:
value: 2

- label: "Lock the door back prior to next tests"
command: "LockDoor"
timedInteractionTimeoutMs: 10000
arguments:
values:
- name: "PINCode"
value: "123456"

- label: "Verify that lock state attribute value is set to Locked"
command: "readAttribute"
attribute: "LockState"
response:
value: 1

# Engage lockout by trying invalid PIN again 3 times after the reset.
# The retry count should have reset to 0 to allow us 3 retry attempts again

- label: "Read the lockout timeout"
command: "readAttribute"
attribute: "UserCodeTemporaryDisableTime"
response:
value: 10

- label: "Try to unlock the door with invalid PIN for the first time after reset"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
arguments:
values:
- name: "PINCode"
value: "000000"
response:
error: FAILURE

- label: "Try to unlock the door with invalid PIN for the second time after reset"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
arguments:
Expand All @@ -280,9 +326,17 @@ tests:
response:
error: FAILURE

- label:
"Try to unlock the door with valid PIN and make sure it fails due to
lockout"
- label: "Try to unlock the door with invalid PIN for the third time after reset"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
arguments:
values:
- name: "PINCode"
value: "000000"
response:
error: FAILURE

- label: "Try to unlock the door with valid PIN and make sure it fails since we are in lockout"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
arguments:
Expand Down
Loading

0 comments on commit 82dee1a

Please sign in to comment.