# -*- coding: utf-8 -*- # SPDX-FileCopyrightText: 2023 Ledger SAS # SPDX-License-Identifier: LicenseRef-LEDGER """ This module provides Ragger tests for Password feature """ from pathlib import Path import pytest from ragger.error import ExceptionRAPDU from ragger.backend import BackendInterface from ragger.firmware import Firmware from ragger.navigator import Navigator from application_client.command_sender import CommandSender from application_client.app_def import Errors, PassWord from utils import util_navigate # In this test we check the card Password verification @pytest.mark.parametrize( "pwd, value", [ (PassWord.PW1, "123456"), (PassWord.PW2, "123456"), (PassWord.PW3, "12345678"), ], ) def test_verify(backend: BackendInterface, pwd: PassWord, value: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Verify PW status - Not yet verified with pytest.raises(ExceptionRAPDU) as err: client.send_verify_pw(pwd) assert err.value.status & 0xFFF0 == 0x63c0 # Verify PW with its value rapdu = client.send_verify_pw(pwd, value) assert rapdu.status == Errors.SW_OK # Verify PW status rapdu = client.send_verify_pw(pwd) assert rapdu.status == Errors.SW_OK # Verify PW Reset Status rapdu = client.send_verify_pw(pwd, reset=True) assert rapdu.status == Errors.SW_OK # Verify PW status - Not yet verified with pytest.raises(ExceptionRAPDU) as err: client.send_verify_pw(pwd) assert err.value.status & 0xFFF0 == 0x63c0 def test_verify_wrong(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Verify PW status - Wrong Password with pytest.raises(ExceptionRAPDU) as err: client.send_verify_pw(PassWord.PW1, "999999") assert err.value.status == Errors.SW_SECURITY_STATUS_NOT_SATISFIED # In this test we check the card Password verification with Pinpad def test_verify_confirm_accepted(firmware: Firmware, backend: BackendInterface, navigator: Navigator, test_name: Path) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Send the APDU (Asynchronous) with client.send_verify_pw_with_confirmation(PassWord.PW1): util_navigate(firmware, navigator, test_name, "Confirm_Yes") # Check the status (Asynchronous) response = client.get_async_response() assert response and response.status == Errors.SW_OK # In this test we check the Rejected card Password verification with Pinpad def test_verify_confirm_refused(firmware: Firmware, backend: BackendInterface, navigator: Navigator, test_name: Path) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Send the APDU (Asynchronous) with pytest.raises(ExceptionRAPDU) as err: with client.send_verify_pw_with_confirmation(PassWord.PW1): util_navigate(firmware, navigator, test_name, "Confirm_No") # Assert we have received a refusal assert err.value.status == Errors.SW_CONDITIONS_NOT_SATISFIED assert len(err.value.data) == 0 # In this test we check the Password Update @pytest.mark.parametrize( "pwd, actual, new", [ (PassWord.PW1, "123456", "654321"), (PassWord.PW3, "12345678", "87654321"), ], ) def test_change(backend: BackendInterface, pwd: PassWord, actual: str, new: str) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Verify PW with its value rapdu = client.send_verify_pw(pwd, actual) assert rapdu.status == Errors.SW_OK # Change PW value rapdu = client.send_change_pw(pwd, actual, new) assert rapdu.status == Errors.SW_OK # Verify PW status rapdu = client.send_verify_pw(pwd, new) assert rapdu.status == Errors.SW_OK # In this test we check the Password Reset def test_reset(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Verify PW1 rapdu = client.send_verify_pw(PassWord.PW1, "123456") assert rapdu.status == Errors.SW_OK # Verify PW3 (Admin) rapdu = client.send_verify_pw(PassWord.PW3, "12345678") assert rapdu.status == Errors.SW_OK # Reset PW1 with a new value rapdu = client.send_reset_pw("654321") assert rapdu.status == Errors.SW_OK # Verify PW status rapdu = client.send_verify_pw(PassWord.PW1, "654321") assert rapdu.status == Errors.SW_OK # In this test we check the Get Challenge def test_challenge(backend: BackendInterface) -> None: # Use the app interface instead of raw interface client = CommandSender(backend) # Get Random number rapdu = client.get_challenge(32) assert rapdu.status == Errors.SW_OK print(f"Random: {rapdu.data.hex()}")