Skip to content

Commit ae4ce84

Browse files
authored
Picopass cleanup (#201)
1 parent 471e8db commit ae4ce84

4 files changed

+65
-77
lines changed

scenes/picopass_scene_card_menu.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@ void picopass_scene_card_menu_on_enter(void* context) {
2121
Submenu* submenu = picopass->submenu;
2222
PicopassPacs* pacs = &picopass->dev->dev_data.pacs;
2323
PicopassBlock* card_data = picopass->dev->dev_data.card_data;
24+
PicopassDeviceAuthMethod auth = picopass->dev->dev_data.auth;
2425

25-
bool sio = 0x30 == card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
26+
bool SE = card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].valid &&
27+
0x30 == card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
28+
bool SR = card_data[10].valid && 0x30 == card_data[10].data[0];
29+
bool has_sio = SE || SR;
2630
bool secured = (card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] & PICOPASS_FUSE_CRYPT10) !=
2731
PICOPASS_FUSE_CRYPT0;
28-
bool zero_config = picopass_is_memset(
29-
card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data, 0x00, PICOPASS_BLOCK_LEN);
3032
bool no_credential = picopass_is_memset(pacs->credential, 0x00, sizeof(pacs->credential));
31-
bool no_key = !card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].valid;
3233

33-
if(secured && zero_config) {
34+
if(auth == PicopassDeviceAuthMethodFailed) {
3435
submenu_add_item(
3536
submenu,
3637
"Save Partial",
@@ -42,7 +43,7 @@ void picopass_scene_card_menu_on_enter(void* context) {
4243
submenu, "Save", SubmenuIndexSave, picopass_scene_card_menu_submenu_callback, picopass);
4344
}
4445

45-
if(secured && (sio || pacs->sio)) {
46+
if(secured && has_sio) {
4647
submenu_add_item(
4748
submenu,
4849
"Save in Seader fmt",
@@ -60,7 +61,7 @@ void picopass_scene_card_menu_on_enter(void* context) {
6061
picopass);
6162
}
6263

63-
if(!zero_config && !no_key) {
64+
if(auth == PicopassDeviceAuthMethodNone || auth == PicopassDeviceAuthMethodKey) {
6465
submenu_add_item(
6566
submenu,
6667
"Write",

scenes/picopass_scene_more_info.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ void picopass_scene_more_info_on_exit(void* context) {
5151
Picopass* picopass = context;
5252

5353
// Clear views
54-
widget_reset(picopass->widget);
54+
text_box_reset(picopass->text_box);
5555
}

scenes/picopass_scene_read_card_success.c

+52-69
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,18 @@ void picopass_scene_read_card_success_widget_callback(
1818

1919
void picopass_scene_read_card_success_on_enter(void* context) {
2020
Picopass* picopass = context;
21+
PicopassDeviceAuthMethod auth = picopass->dev->dev_data.auth;
2122

2223
FuriString* csn_str = furi_string_alloc_set("CSN:");
2324
FuriString* credential_str = furi_string_alloc();
24-
FuriString* wiegand_str = furi_string_alloc();
25+
FuriString* info_str = furi_string_alloc();
2526
FuriString* key_str = furi_string_alloc();
2627

2728
dolphin_deed(DolphinDeedNfcReadSuccess);
2829

2930
// Send notification
3031
notification_message(picopass->notifications, &sequence_success);
3132

32-
// For initial testing, print auth method
33-
switch(picopass->dev->dev_data.auth) {
34-
case PicopassDeviceAuthMethodUnset:
35-
FURI_LOG_D(TAG, "Auth: Unset");
36-
break;
37-
case PicopassDeviceAuthMethodNone:
38-
FURI_LOG_D(TAG, "Auth: None");
39-
break;
40-
case PicopassDeviceAuthMethodKey:
41-
FURI_LOG_D(TAG, "Auth: Key");
42-
break;
43-
case PicopassDeviceAuthMethodNrMac:
44-
FURI_LOG_D(TAG, "Auth: NR-MAC");
45-
break;
46-
case PicopassDeviceAuthMethodFailed:
47-
FURI_LOG_D(TAG, "Auth: Failed");
48-
break;
49-
default:
50-
FURI_LOG_D(TAG, "Auth: Unknown");
51-
break;
52-
};
53-
5433
// Setup view
5534
PicopassBlock* card_data = picopass->dev->dev_data.card_data;
5635
PicopassPacs* pacs = &picopass->dev->dev_data.pacs;
@@ -62,19 +41,16 @@ void picopass_scene_read_card_success_on_enter(void* context) {
6241
furi_string_cat_printf(csn_str, "%02X", csn[i]);
6342
}
6443

65-
// We can't test the pacs->key in case it is intentionally all 0's and we can't test the key block since it is populated with the diversified key before each key test, so we approximate with the PACS config block being blank.
66-
bool zero_config = picopass_is_memset(
67-
card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data, 0x00, PICOPASS_BLOCK_LEN);
6844
bool empty = picopass_is_memset(
6945
card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data, 0xFF, PICOPASS_BLOCK_LEN);
70-
bool SE = 0x30 == card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
46+
bool SE = pacs->se_enabled;
7147
bool configCard = (card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[7] >> 2 & 3) == 2;
7248
bool secured = (card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] & PICOPASS_FUSE_CRYPT10) !=
7349
PICOPASS_FUSE_CRYPT0;
7450
bool hid_csn = picopass_device_hid_csn(picopass->dev);
7551

7652
if(!secured) {
77-
furi_string_cat_printf(wiegand_str, "Non-Secured Chip");
53+
furi_string_cat_printf(info_str, "Non-Secured Chip");
7854

7955
if(!hid_csn) {
8056
furi_string_cat_printf(credential_str, "Non-HID CSN");
@@ -86,8 +62,8 @@ void picopass_scene_read_card_success_on_enter(void* context) {
8662
"More",
8763
picopass_scene_read_card_success_widget_callback,
8864
picopass);
89-
} else if(zero_config) {
90-
furi_string_cat_printf(wiegand_str, "Read Failed");
65+
} else if(auth == PicopassDeviceAuthMethodFailed) {
66+
furi_string_cat_printf(info_str, "Read Failed");
9167

9268
if(pacs->se_enabled) {
9369
furi_string_cat_printf(credential_str, "SE enabled");
@@ -109,17 +85,19 @@ void picopass_scene_read_card_success_on_enter(void* context) {
10985
picopass);
11086
} else if(pacs->se_enabled) {
11187
furi_string_cat_printf(credential_str, "SE enabled");
112-
furi_string_cat_printf(wiegand_str, "SIO");
88+
furi_string_cat_printf(info_str, "SIO");
89+
11390
widget_add_button_element(
11491
widget,
11592
GuiButtonTypeRight,
11693
"More",
11794
picopass_scene_read_card_success_widget_callback,
11895
picopass);
11996
} else if(configCard) {
120-
furi_string_cat_printf(wiegand_str, "Config Card");
97+
furi_string_cat_printf(credential_str, "Config Card");
12198
} else if(empty) {
122-
furi_string_cat_printf(wiegand_str, "Empty");
99+
furi_string_cat_printf(credential_str, "Empty");
100+
123101
widget_add_button_element(
124102
widget,
125103
GuiButtonTypeCenter,
@@ -129,10 +107,11 @@ void picopass_scene_read_card_success_on_enter(void* context) {
129107
} else if(pacs->bitLength == 0 || pacs->bitLength == 255) {
130108
// Neither of these are valid. Indicates the block was all 0x00 or all 0xff
131109
if(SE) {
132-
furi_string_cat_printf(wiegand_str, "SIO");
110+
furi_string_cat_printf(info_str, "SIO");
133111
} else {
134-
furi_string_cat_printf(wiegand_str, "Invalid PACS");
112+
furi_string_cat_printf(info_str, "Invalid PACS");
135113
}
114+
136115
widget_add_button_element(
137116
widget,
138117
GuiButtonTypeCenter,
@@ -148,40 +127,13 @@ void picopass_scene_read_card_success_on_enter(void* context) {
148127
} else {
149128
size_t bytesLength = 1 + pacs->bitLength / 8;
150129
furi_string_set(credential_str, "");
130+
furi_string_cat_printf(credential_str, "(%d) ", pacs->bitLength);
151131
for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) {
152132
furi_string_cat_printf(credential_str, "%02X", pacs->credential[i]);
153133
}
154-
furi_string_cat_printf(wiegand_str, "%d bits", pacs->bitLength);
155134

156135
if(pacs->sio) {
157-
furi_string_cat_printf(credential_str, " +SIO");
158-
}
159-
160-
bool no_key = !card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].valid;
161-
162-
if(no_key) {
163-
furi_string_cat_printf(key_str, "No Key: used NR-MAC");
164-
} else {
165-
furi_string_cat_printf(key_str, "Key: ");
166-
uint8_t key[PICOPASS_BLOCK_LEN];
167-
memcpy(key, &pacs->key, PICOPASS_BLOCK_LEN);
168-
169-
bool standard_key = true;
170-
// Handle DES key being 56bits with parity in LSB
171-
for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
172-
if((key[i] & 0xFE) != (picopass_iclass_key[i] & 0xFE)) {
173-
standard_key = false;
174-
break;
175-
}
176-
}
177-
178-
if(standard_key) {
179-
furi_string_cat_printf(key_str, "Standard");
180-
} else {
181-
for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
182-
furi_string_cat_printf(key_str, "%02X", key[i]);
183-
}
184-
}
136+
furi_string_cat_printf(info_str, " +SIO");
185137
}
186138

187139
widget_add_button_element(
@@ -192,6 +144,37 @@ void picopass_scene_read_card_success_on_enter(void* context) {
192144
picopass);
193145
}
194146

147+
if(auth == PicopassDeviceAuthMethodUnset) {
148+
furi_string_cat_printf(key_str, "Error: Auth Unset");
149+
} else if(auth == PicopassDeviceAuthMethodNone) {
150+
furi_string_cat_printf(key_str, "Unsecure card");
151+
} else if(auth == PicopassDeviceAuthMethodNrMac) {
152+
furi_string_cat_printf(key_str, "No Key: used NR-MAC");
153+
} else if(auth == PicopassDeviceAuthMethodFailed) {
154+
furi_string_cat_printf(key_str, "Auth Failed");
155+
} else if(auth == PicopassDeviceAuthMethodKey) {
156+
furi_string_cat_printf(key_str, "Key: ");
157+
uint8_t key[PICOPASS_BLOCK_LEN];
158+
memcpy(key, &pacs->key, PICOPASS_BLOCK_LEN);
159+
160+
bool standard_key = true;
161+
// Handle DES key being 56bits with parity in LSB
162+
for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
163+
if((key[i] & 0xFE) != (picopass_iclass_key[i] & 0xFE)) {
164+
standard_key = false;
165+
break;
166+
}
167+
}
168+
169+
if(standard_key) {
170+
furi_string_cat_printf(key_str, "Standard");
171+
} else {
172+
for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
173+
furi_string_cat_printf(key_str, "%02X", key[i]);
174+
}
175+
}
176+
}
177+
195178
widget_add_button_element(
196179
widget,
197180
GuiButtonTypeLeft,
@@ -201,22 +184,22 @@ void picopass_scene_read_card_success_on_enter(void* context) {
201184

202185
widget_add_string_element(
203186
widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(csn_str));
204-
widget_add_string_element(
205-
widget, 64, 20, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(wiegand_str));
206187
widget_add_string_element(
207188
widget,
208189
64,
209-
36,
190+
20,
210191
AlignCenter,
211192
AlignCenter,
212-
FontSecondary,
193+
FontPrimary,
213194
furi_string_get_cstr(credential_str));
195+
widget_add_string_element(
196+
widget, 64, 36, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(info_str));
214197
widget_add_string_element(
215198
widget, 64, 46, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(key_str));
216199

217200
furi_string_free(csn_str);
218201
furi_string_free(credential_str);
219-
furi_string_free(wiegand_str);
202+
furi_string_free(info_str);
220203
furi_string_free(key_str);
221204

222205
view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget);

scenes/picopass_scene_read_factory_success.c

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ bool picopass_scene_read_factory_success_on_event(void* context, SceneManagerEve
7070
scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey);
7171
consumed = true;
7272
}
73+
} else if(event.type == SceneManagerEventTypeBack) {
74+
scene_manager_search_and_switch_to_previous_scene(
75+
picopass->scene_manager, PicopassSceneStart);
76+
consumed = true;
7377
}
7478
return consumed;
7579
}

0 commit comments

Comments
 (0)