Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reset the wrong code retry attempts if a valid credential is presented #25536

Merged
28 changes: 26 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 @@ -122,6 +122,13 @@ bool DoorLockServer::SetLockState(chip::EndpointId endpointId, DlLockState newLo
SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kUnspecified, userIndex, Nullable<chip::FabricIndex>(),
Nullable<chip::NodeId>(), credentials, success);

// Reset wrong entry attempts (in case there were any incorrect credentials presented before) if lock/unlock was a success
// and a valid credential was presented.
if (success && !credentials.IsNull() && !(credentials.Value().empty()))
{
ResetWrongCodeEntryAttempts(endpointId);
nivi-apple marked this conversation as resolved.
Show resolved Hide resolved
}

// Schedule auto-relocking
if (success && LockOperationTypeEnum::kUnlock == opType)
{
Expand Down Expand Up @@ -181,7 +188,7 @@ bool DoorLockServer::SetPrivacyModeButton(chip::EndpointId endpointId, bool isEn
return SetAttribute(endpointId, Attributes::EnablePrivacyModeButton::Id, Attributes::EnablePrivacyModeButton::Set, isEnabled);
}

bool DoorLockServer::TrackWrongCodeEntry(chip::EndpointId endpointId)
bool DoorLockServer::HandleWrongCodeEntry(chip::EndpointId endpointId)
{
auto endpointContext = getContext(endpointId);
if (nullptr == endpointContext)
Expand Down Expand Up @@ -209,6 +216,17 @@ bool DoorLockServer::TrackWrongCodeEntry(chip::EndpointId endpointId)
return true;
}

void DoorLockServer::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 DoorLockServer::engageLockout(chip::EndpointId endpointId)
{
uint8_t lockoutTimeout;
Expand Down Expand Up @@ -3352,7 +3370,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 during lock/unlock
if (success && pinCode.HasValue())
{
ResetWrongCodeEntryAttempts(endpoint);
nivi-apple marked this conversation as resolved.
Show resolved Hide resolved
}

// Send command response
Expand Down
19 changes: 18 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,15 @@ class DoorLockServer
bool SetOneTouchLocking(chip::EndpointId endpointId, bool isEnabled);
bool SetPrivacyModeButton(chip::EndpointId endpointId, bool isEnabled);

bool TrackWrongCodeEntry(chip::EndpointId endpointId);
/**
* @brief Handles a wrong code entry attempt for the endpoint. If the number of wrong entry attempts exceeds the max limit,
* engage lockout. Otherwise increment the number of incorrect attempts by 1. This is handled automatically for
* remote operations - lock and unlock. Applications are responsible for calling it for non-remote incorrect credential
* presentation attempts.
*
* @param endpointId
*/
bool HandleWrongCodeEntry(chip::EndpointId endpointId);
nivi-apple marked this conversation as resolved.
Show resolved Hide resolved
nivi-apple marked this conversation as resolved.
Show resolved Hide resolved

bool GetAutoRelockTime(chip::EndpointId endpointId, uint32_t & autoRelockTime);
bool GetNumberOfUserSupported(chip::EndpointId endpointId, uint16_t & numberOfUsersSupported);
Expand Down Expand Up @@ -183,6 +191,15 @@ class DoorLockServer
bool OnFabricRemoved(chip::EndpointId endpointId, chip::FabricIndex fabricIndex);

static void DoorLockOnAutoRelockCallback(chip::System::Layer *, void * callbackContext);
/**
* @brief Resets the wrong code entry attempts to 0 for the endpoint. This is done automatically when a
* remote lock operation with credentials succeeds, or when SetLockState is called with a non-empty credentials list.
* Applications that call the two-argument version of SetLockState and handle sending the relevant operation events
* themselves or via SendLockOperationEvent are responsible for calling this API when a valid credential is presented.
*
* @param endpointId
*/
void ResetWrongCodeEntryAttempts(chip::EndpointId endpointId);

private:
chip::FabricIndex getFabricIndex(const chip::app::CommandHandler * commandObj);
Expand Down
112 changes: 107 additions & 5 deletions src/app/tests/suites/DL_LockUnlock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,11 @@ 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. Try to unock with incorrect
# PIN 2 times followed by a third time with correct PIN code. We should be able to unlock since
# the count has been reset and we are not in lockout.

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

- 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

- label: "Try to unlock the door with invalid PIN for the first time"
command: "UnlockDoor"
nivi-apple marked this conversation as resolved.
Show resolved Hide resolved
timedInteractionTimeoutMs: 10000
arguments:
values:
- name: "PINCode"
value: "000000"
response:
error: FAILURE

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

- 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"
nivi-apple marked this conversation as resolved.
Show resolved Hide resolved
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

- 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"
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"
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"
command: "UnlockDoor"
timedInteractionTimeoutMs: 10000
Expand Down
Loading