Skip to content

Commit

Permalink
Merge branch 'doom/2991-e2e-runner' of https://github.com/flipperdevi…
Browse files Browse the repository at this point in the history
…ces/flipperzero-firmware into doom/2991-e2e-runner
  • Loading branch information
doomwastaken committed Oct 18, 2023
2 parents 76a7fc4 + 8f5acb1 commit dd5e407
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 130 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/smoke_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ name: 'Smoke tests'
on:
push:
branches:
- dev
- "release*"
tags:
- '*'
pull_request:

env:
TARGETS: f7
Expand Down
4 changes: 3 additions & 1 deletion scripts/flippigator/flippigator/extensions/command_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ def Result(self):
def __init__(self, input):
print("input: ", input)
s = str(input).split("\n")
# remove empty lines
s = list(filter(None, s))
self.__Command = s[0]
self.__Result = s[1].removeprefix("[+] ").removesuffix(" ")
self.__Result = s[1:]


class proxmark_command:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def execute(self, cmd) -> List[command_result]:

result = self.__get_result(data_out)
print("result: ", result[0])
return result
return result[0]

def shutdown(self):
pass
Expand All @@ -57,8 +57,8 @@ def __parse_data(self, output_data):
raw_result = str(output_data).split("[usb|script] pm3 --> ")

print("raw_result: ", raw_result)
print("-------------------------------------")
result = []
for raw in raw_result[1:]:
print("raw: ", raw)
result.append(command_result(raw).Result)
return result
13 changes: 11 additions & 2 deletions scripts/flippigator/flippigator/flippigator.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ def __init__(
self.logger = logging.getLogger(window_name)
if self._debugFlag:
self.logger.setLevel(logging.DEBUG)
else:
self.logger.setLevel(logging.WARNING)

self.nfc = AppNfc(self)
self.rfid = AppRfid(self)
Expand Down Expand Up @@ -298,14 +300,21 @@ def get_first_item(self, browser: Optional[bool] = False):

return menus

def go_to(self, target, area=(0, 64, 0, 128)):
def go_to(self, target, area=(0, 64, 0, 128), direction: Optional[str] = "down"):
state = self.get_current_state(area=area)
self.logger.info("Going to " + target)

while not (target in state):
self.press_down()
if direction == "down":
self.press_down()
elif direction == "up":
self.press_up()
state = self.get_current_state(area=area)

def open(self, target, area=(0, 64, 0, 128), direction: Optional[str] = "down"):
self.go_to(target, area, direction)
self.press_ok()

def go_to_main_screen(self):
self.press_back()
self.press_back()
Expand Down
Binary file added scripts/flippigator/img/ref/Rename.bmp
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
186 changes: 186 additions & 0 deletions scripts/flippigator/nfc/test_emulate_mifare_classic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import pytest
from flippigator.extensions.proxmark_wrapper import proxmark_wrapper
from flippigator.flippigator import FlipperHEXKeyboard, FlipperTextKeyboard
import time


class TestEmulateClassic:
@pytest.fixture(scope="class", autouse=True)
def add_4k7_manually(self, nav):
# Code below will run before each "function" (test)

# Delete file if exists, needs to be added as picture sadly
# nav.delete_file("NFC", "T_mfc_4k7")
# Todo: return back to line above, after browser is fixed
nav.nfc.go_into()
nav.open("Saved")
menu_items = nav.get_menu_list()
if "browser_T_mfc_4k7" in menu_items:
nav.open("browser_T_mfc_4k7", direction="up")
nav.open("Delete", direction="up")
nav.press_right()

nav.nfc.go_into()
nav.open("Add Manually")
# direction for faster testing, since its last element
nav.open("Mifare Classic 4k 7byte UID", direction="up")
nav.press_right()
nav.press_ok()
key = FlipperTextKeyboard(nav)
# if you need, you can make another fixture and use any "existing" file name in /img/ref
key.send("T_mfc_4k7\n")
nav.go_to_main_screen()

# here will be a test call
yield

# This code will run after each "function" (test)
# nav.delete_file("NFC", "T_mfc_4k7")
# Todo: return back to line above, after browser is fixed
# Todo2: move to function
nav.nfc.go_into()
nav.open("Saved")
menu_items = nav.get_menu_list()
if "browser_T_mfc_4k7" in menu_items:
nav.open("browser_T_mfc_4k7", direction="up")
nav.open("Delete", direction="up")
nav.press_right()

@pytest.fixture(scope="function")
def emulate_classic(self, nav):
nav.go_to_main_screen()
if nav.open_file("NFC", "T_mfc_4k7") == -1:
assert 0, "File not found"

# Need for emulation to start, otherwise error on proxmark side
time.sleep(1)

def test_mfc_4k7_basic(self, px, emulate_classic):
"""
px: proxmark_wrapper fixture
command: command to be executed
expected_result: expected result of the command
error: if the command should return an error
"""

# read 1 block
read1 = px.execute("hf mf rdbl --blk 1 -k ffffffffffff")
expected = "[=] 1 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................ "
assert expected in read1, "Incorrect block read"

# write 1 block
write1 = px.execute(
"hf mf wrbl --blk 1 -k ffffffffffff -d 11223344556677889910111213141516"
)
expected = "[+] Write ( ok )"
assert expected in write1, "Incorrect block write"

# read 1 block
read1_wrong = px.execute("hf mf rdbl --blk 1 -k ffffffffffff")
expected = '[=] 1 | 11 22 33 44 55 66 77 88 99 10 11 12 13 14 15 16 | ."3DUfw......... '
assert expected in read1_wrong, "Incorrect block read"

# set value block
set_value = px.execute("hf mf value --blk 1 -k ffffffffffff --set 1000")
expected = "[=] set value to : 1000"
expected_status = "[+] Update ... : success"
assert expected in set_value, "Incorrect set value"
assert expected_status in set_value, "Update failed"

# increment value block
inc_value = px.execute("hf mf value --blk 1 -k ffffffffffff --inc 200")
expected = "[=] Value incremented by : 200"
expected_status = "[+] Update ... : success"

assert expected in inc_value, "Incorrect increment value"
assert expected_status in inc_value, "Update failed"

# decrement value block
dec_value = px.execute("hf mf value --blk 1 -k ffffffffffff --dec 10000")
expected = "[=] Value decremented by : 10000"
expected_status = "[+] Update ... : success"
assert expected in dec_value, "Incorrect decrement value"
assert expected_status in dec_value, "Update failed"

# change key A in 0 sector
change_key = px.execute(
"hf mf wrbl --blk 3 -k ffffffffffff -d a0a1a2a3a4a5ff078069ffffffffffff"
)
expected = "[=] data: A0 A1 A2 A3 A4 A5 FF 07 80 69 FF FF FF FF FF FF"
expected_status = "[+] Write ( ok )"
assert expected in change_key, "Incorrect change key"
assert expected_status in change_key, "Update failed"

# read 1 block with old key
read1 = px.execute("hf mf rdbl --blk 1 -k ffffffffffff")
expected_status = "[#] Auth error"
assert expected_status in read1, "Auth error not present"

# read 1 block with new key
read1 = px.execute("hf mf rdbl --blk 1 -k a0a1a2a3a4a5")
expected = "[=] 1 | E8 03 00 00 17 FC FF FF E8 03 00 00 01 FE 01 FE | ................ "
assert expected in read1, "Incorrect block read"

# all tests below are non-functional, need help verifying them
# change key B in 0 sector
# change_key = px.execute("hf mf wrbl --blk 3 -k ffffffffffff -d ffffffffffff078069b0b1b2b3b4b5ff")
# assert change_key[0] == "Block write OK", "Incorrect change key"

# read sector trailer with key A
# trailer_a_key = px.execute("hf mf rdbl --blk 3 -k a0a1a2a3a4a5")
# assert trailer_a_key[0] == "Key A not present, Access Bits present, Key B present in the output", "Incorrect trailer read"

# read sector trailer with key B
# trailer_b_key = px.execute("hf mf rdbl --blk 3 -b -k b0b1b2b3b4b5")
# assert trailer_b_key[0] == "Key A not present, Access Bits not present, Key B not present in the output", "Incorrect trailer read"

# FF0F00 http://calc.gmss.ru/Mifare1k/ hf mf wrbl --blk 3 -k ffffffffffff -d ffffffffffffff0f0069ffffffffffff
# hf mf rdbl --blk 3 -k ffffffffffff No keyA, ACs, KeyB
# hf mf rdbl --blk 3 -b -k ffffffffffff No KeyA, No ACs, No KeyB
# hf mf wrbl --blk 3 -k ffffffffffff -d a0a1a2a3a4a5ff0f0069b0b1b2b3b4b5 Keys changed
# hf mf wrbl --blk 3 -b -k ffffffffffff -d a1a2a3a4a5a6ff0f0069b1b2b3b4b5b6 Keys not changed
# hf mf wrbl --blk 3 (-b) -k ffffffffffff -d a1a2a3a4a5a6ff078069b1b2b3b4b5b6 ACs not changed

data = [
(
"FF0F00",
[
(
"hf mf wrbl --blk 3 -k ffffffffffff -d ffffffffffffff0f0069ffffffffffff",
"[+] Write ( ok )",
),
(
"hf mf rdbl --blk 3 -k ffffffffffff",
"[=] 3 | 00 00 00 00 00 00 FF 0F 00 69 FF FF FF FF FF FF | .........i......",
),
(
"hf mf rdbl --blk 3 -b -k ffffffffffff",
"[#] Read block error",
), # [#] Read block error
(
"hf mf wrbl --blk 3 -k ffffffffffff -d a0a1a2a3a4a5ff0f0069b0b1b2b3b4b5",
"[+] Write ( ok )",
),
(
"hf mf wrbl --blk 3 -b -k b0b1b2b3b4b5 -d a1a2a3a4a5a6ff0f0069b1b2b3b4b5b6",
"[-] ⛔ Write ( fail )",
),
(
"hf mf wrbl --blk 3 -k a0a1a2a3a4a5 -d a1a2a3a4a5a6ff078069b1b2b3b4b5b6",
"[+] Write ( ok )",
),
(
"hf mf wrbl --blk 3 -b -k b1b2b3b4b5b6 -d a1a2a3a4a5a6ff078069b1b2b3b4b5b6",
"[-] ⛔ Write ( fail )",
),
],
),
]

@pytest.mark.parametrize("condition, cmds", data)
def test_trailer_access_condition(self, px, emulate_classic, condition, cmds):
for i, cmd in enumerate(cmds):
command = cmd[0]
expected = cmd[1]
result = px.execute(command)
assert expected in result, f"{i}: {command} failed"
Loading

0 comments on commit dd5e407

Please sign in to comment.