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 f41610c
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 73 deletions.
19 changes: 17 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,13 @@ 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
78 changes: 70 additions & 8 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,70 @@ 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:
values:
- name: "PINCode"
value: "000000"
response:
error: FAILURE

- label:
"Try to unlock the door with invalid PIN for the third time after
reset"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
arguments:
Expand All @@ -281,8 +343,8 @@ tests:
error: FAILURE

- label:
"Try to unlock the door with valid PIN and make sure it fails due to
lockout"
"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 f41610c

Please sign in to comment.