Skip to content

Commit

Permalink
Picopass: handle NR-MAC auth for legacy cards (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
bettse committed Jan 2, 2024
1 parent ef3333a commit d8303dc
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .catalog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ There are some situations when the offline loclass may not find a key, such as:

Due to the nature of how secure picopass works, it is possible to emulate some public fields from a card and capture the reader's response, which can be used to authenticate. Two of the pieces involved in this are the NR and MAC.

These instructions are intended to be performed all at the same time. If you use the card with the reader between Card Part 1 and Card Part 2, then Card Part 2 will fail.

## Card Part 1

1. Place card against Flipper Zero
Expand Down
11 changes: 10 additions & 1 deletion picopass_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ static bool picopass_device_save_file(
FuriString* temp_str;
temp_str = furi_string_alloc();

if(dev->format == PicopassDeviceSaveFormatPartial) {
// Clear key that may have been set when doing key tests for legacy
memset(AA1[PICOPASS_SECURE_KD_BLOCK_INDEX].data, 0, PICOPASS_BLOCK_LEN);
}

do {
if(use_load_path && !furi_string_empty(dev->load_path)) {
// Get directory name
Expand All @@ -178,7 +183,8 @@ static bool picopass_device_save_file(
furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
}

if(dev->format == PicopassDeviceSaveFormatHF) {
if(dev->format == PicopassDeviceSaveFormatHF ||
dev->format == PicopassDeviceSaveFormatPartial) {
// Open file
if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;

Expand Down Expand Up @@ -229,6 +235,9 @@ bool picopass_device_save(PicopassDevice* dev, const char* dev_name) {
} else if(dev->format == PicopassDeviceSaveFormatSeader) {
return picopass_device_save_file(
dev, dev_name, EXT_PATH("apps_data/seader"), ".credential", true);
} else if(dev->format == PicopassDeviceSaveFormatPartial) {
return picopass_device_save_file(
dev, dev_name, STORAGE_APP_DATA_PATH_PREFIX, PICOPASS_APP_EXTENSION, true);
}

return false;
Expand Down
1 change: 1 addition & 0 deletions picopass_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ typedef enum {
PicopassDeviceSaveFormatHF,
PicopassDeviceSaveFormatLF,
PicopassDeviceSaveFormatSeader,
PicopassDeviceSaveFormatPartial,
} PicopassDeviceSaveFormat;

typedef enum {
Expand Down
14 changes: 9 additions & 5 deletions protocol/picopass_poller.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,9 @@ NfcCommand picopass_poller_check_security(PicopassPoller* instance) {

if(instance->data->pacs.se_enabled) {
FURI_LOG_D(TAG, "SE enabled");
instance->state = PicopassPollerStateNrMacAuth;
} else {
instance->state = PicopassPollerStateAuth;
}
// Always try the NR-MAC auth in case we have the file.
instance->state = PicopassPollerStateNrMacAuth;
return command;
}

Expand Down Expand Up @@ -221,8 +220,13 @@ NfcCommand picopass_poller_nr_mac_auth(PicopassPoller* instance) {
FURI_LOG_D(TAG, "Looking for %s", furi_string_get_cstr(temp_str));
uint8_t nr_mac[PICOPASS_BLOCK_LEN];

// Presume failure unless all steps are successful and the state is made "read block"
instance->state = PicopassPollerStateFail;
// Set next state so breaking do/while will jump to it. If successful, do/while will set to ReadBlock
if(instance->data->pacs.se_enabled) {
instance->state = PicopassPollerStateFail;
} else {
// For non-SE, run through normal key check
instance->state = PicopassPollerStateAuth;
}
do {
//check for file
if(!flipper_format_file_open_existing(file, furi_string_get_cstr(temp_str))) break;
Expand Down
2 changes: 1 addition & 1 deletion scenes/picopass_scene_card_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ bool picopass_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
scene_manager_set_scene_state(
picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSave);
scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName);
picopass->dev->format = PicopassDeviceSaveFormatHF;
picopass->dev->format = PicopassDeviceSaveFormatPartial;
consumed = true;
} else if(event.event == SubmenuIndexSaveAsSeader) {
scene_manager_set_scene_state(
Expand Down

0 comments on commit d8303dc

Please sign in to comment.