Skip to content

Commit 8f9c0ee

Browse files
gornekichskotopes
andauthored
[FL-3593] Picopass rework. Part 1 (#68)
Co-authored-by: あく <alleteam@gmail.com>
1 parent f4cbee2 commit 8f9c0ee

37 files changed

+2291
-1929
lines changed

nfc_magic/.catalog/changelog.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## 1.1
2+
- Rework application with new NFC API
3+
## 1.0
4+
- Initial release

nfc_magic/application.fam

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ App(
1010
],
1111
stack_size=4 * 1024,
1212
fap_description="Application for writing to NFC tags with modifiable sector 0",
13-
fap_version="1.0",
13+
fap_version="1.1",
1414
fap_icon="assets/125_10px.png",
1515
fap_category="NFC",
1616
fap_private_libs=[

nfc_rfid_detector/.catalog/changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 1.2
2+
- Rework application with new NFC API
13
## 1.1
24
- App rename, removed About screen
35
## 1.0

nfc_rfid_detector/application.fam

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ App(
77
requires=["gui"],
88
stack_size=4 * 1024,
99
fap_description="Identify the reader type: NFC (13 MHz) and/or RFID (125 KHz).",
10-
fap_version="1.1",
10+
fap_version="1.2",
1111
fap_icon="nfc_rfid_detector_10px.png",
1212
fap_category="Tools",
1313
fap_icon_assets="images",

picopass/.catalog/changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 1.7
2+
- Rework application with new NFC API
13
## 1.6
24
- Faster loclass response collection
35
- Save as LF for all bit lengths

picopass/application.fam

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ App(
1010
],
1111
stack_size=4 * 1024,
1212
fap_description="App to communicate with NFC tags using the PicoPass(iClass) format",
13-
fap_version="1.6",
13+
fap_version="1.7",
1414
fap_icon="125_10px.png",
1515
fap_category="NFC",
1616
fap_libs=["mbedtls"],

picopass/picopass.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ void picopass_tick_event_callback(void* context) {
2323
Picopass* picopass_alloc() {
2424
Picopass* picopass = malloc(sizeof(Picopass));
2525

26-
picopass->worker = picopass_worker_alloc();
2726
picopass->view_dispatcher = view_dispatcher_alloc();
2827
picopass->scene_manager = scene_manager_alloc(&picopass_scene_handlers, picopass);
2928
view_dispatcher_enable_queue(picopass->view_dispatcher);
@@ -35,6 +34,8 @@ Picopass* picopass_alloc() {
3534
view_dispatcher_set_tick_event_callback(
3635
picopass->view_dispatcher, picopass_tick_event_callback, 100);
3736

37+
picopass->nfc = nfc_alloc();
38+
3839
// Picopass device
3940
picopass->dev = picopass_device_alloc();
4041

@@ -100,6 +101,8 @@ void picopass_free(Picopass* picopass) {
100101
picopass_device_free(picopass->dev);
101102
picopass->dev = NULL;
102103

104+
nfc_free(picopass->nfc);
105+
103106
// Submenu
104107
view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewMenu);
105108
submenu_free(picopass->submenu);
@@ -130,10 +133,6 @@ void picopass_free(Picopass* picopass) {
130133
view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewLoclass);
131134
loclass_free(picopass->loclass);
132135

133-
// Worker
134-
picopass_worker_stop(picopass->worker);
135-
picopass_worker_free(picopass->worker);
136-
137136
// View Dispatcher
138137
view_dispatcher_free(picopass->view_dispatcher);
139138

picopass/picopass_device.c

+8-27
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, boo
225225
}
226226
if(!block_read) break;
227227

228-
if(picopass_device_parse_credential(AA1, pacs) != ERR_NONE) break;
229-
if(picopass_device_parse_wiegand(pacs->credential, pacs) != ERR_NONE) break;
228+
picopass_device_parse_credential(AA1, pacs);
229+
picopass_device_parse_wiegand(pacs->credential, pacs);
230230

231231
parsed = true;
232232
} while(false);
@@ -343,43 +343,28 @@ void picopass_device_set_loading_callback(
343343
dev->loading_cb_ctx = context;
344344
}
345345

346-
ReturnCode picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) {
346+
void picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) {
347347
uint8_t key[32] = {0};
348348
memcpy(key, picopass_iclass_decryptionkey, sizeof(picopass_iclass_decryptionkey));
349349
mbedtls_des3_context ctx;
350350
mbedtls_des3_init(&ctx);
351351
mbedtls_des3_set2key_dec(&ctx, key);
352352
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
353353
mbedtls_des3_free(&ctx);
354-
return ERR_NONE;
355354
}
356355

357-
ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) {
358-
ReturnCode err;
359-
356+
void picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) {
360357
pacs->biometrics = AA1[6].data[4];
361358
pacs->pin_length = AA1[6].data[6] & 0x0F;
362359
pacs->encryption = AA1[6].data[7];
363360

364361
if(pacs->encryption == PicopassDeviceEncryption3DES) {
365362
FURI_LOG_D(TAG, "3DES Encrypted");
366-
err = picopass_device_decrypt(AA1[7].data, pacs->credential);
367-
if(err != ERR_NONE) {
368-
FURI_LOG_E(TAG, "decrypt error %d", err);
369-
return err;
370-
}
363+
picopass_device_decrypt(AA1[7].data, pacs->credential);
371364

372-
err = picopass_device_decrypt(AA1[8].data, pacs->pin0);
373-
if(err != ERR_NONE) {
374-
FURI_LOG_E(TAG, "decrypt error %d", err);
375-
return err;
376-
}
365+
picopass_device_decrypt(AA1[8].data, pacs->pin0);
377366

378-
err = picopass_device_decrypt(AA1[9].data, pacs->pin1);
379-
if(err != ERR_NONE) {
380-
FURI_LOG_E(TAG, "decrypt error %d", err);
381-
return err;
382-
}
367+
picopass_device_decrypt(AA1[9].data, pacs->pin1);
383368
} else if(pacs->encryption == PicopassDeviceEncryptionNone) {
384369
FURI_LOG_D(TAG, "No Encryption");
385370
memcpy(pacs->credential, AA1[7].data, PICOPASS_BLOCK_LEN);
@@ -392,11 +377,9 @@ ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pa
392377
}
393378

394379
pacs->sio = (AA1[10].data[0] == 0x30); // rough check
395-
396-
return ERR_NONE;
397380
}
398381

399-
ReturnCode picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs) {
382+
void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs) {
400383
uint32_t* halves = (uint32_t*)credential;
401384
if(halves[0] == 0) {
402385
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));
@@ -413,8 +396,6 @@ ReturnCode picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs
413396
swapped = swapped ^ sentinel;
414397
memcpy(credential, &swapped, sizeof(uint64_t));
415398
FURI_LOG_D(TAG, "PACS: (%d) %016llx", pacs->bitLength, swapped);
416-
417-
return ERR_NONE;
418399
}
419400

420401
bool picopass_device_hid_csn(PicopassDevice* dev) {

picopass/picopass_device.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ typedef struct {
102102
typedef struct {
103103
PicopassBlock AA1[PICOPASS_MAX_APP_LIMIT];
104104
PicopassPacs pacs;
105-
IclassEliteDictAttackData iclass_elite_dict_attack_data;
106105
} PicopassDeviceData;
107106

108107
typedef struct {
@@ -147,6 +146,6 @@ void picopass_device_set_loading_callback(
147146
PicopassLoadingCallback callback,
148147
void* context);
149148

150-
ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs);
151-
ReturnCode picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs);
149+
void picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs);
150+
void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs);
152151
bool picopass_device_hid_csn(PicopassDevice* dev);

picopass/picopass_i.h

+40-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#pragma once
22

33
#include "picopass.h"
4-
#include "picopass_worker.h"
54
#include "picopass_device.h"
65

76
#include "rfal_picopass.h"
@@ -29,8 +28,17 @@
2928
#include <lib/toolbox/path.h>
3029
#include <picopass_icons.h>
3130

31+
#include <nfc/nfc.h>
32+
#include <nfc/helpers/nfc_dict.h>
33+
#include "protocol/picopass_poller.h"
34+
#include "protocol/picopass_listener.h"
35+
3236
#define PICOPASS_TEXT_STORE_SIZE 128
3337

38+
#define PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME APP_ASSETS_PATH("iclass_elite_dict.txt")
39+
#define PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME APP_ASSETS_PATH("iclass_standard_dict.txt")
40+
#define PICOPASS_ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt")
41+
3442
enum PicopassCustomEvent {
3543
// Reserve first 100 events for button types and indexes, starting from 0
3644
PicopassCustomEventReserved = 100,
@@ -40,21 +48,47 @@ enum PicopassCustomEvent {
4048
PicopassCustomEventByteInputDone,
4149
PicopassCustomEventTextInputDone,
4250
PicopassCustomEventDictAttackSkip,
51+
PicopassCustomEventDictAttackUpdateView,
52+
PicopassCustomEventLoclassGotMac,
53+
PicopassCustomEventLoclassGotStandardKey,
54+
55+
PicopassCustomEventPollerSuccess,
56+
PicopassCustomEventPollerFail,
4357
};
4458

4559
typedef enum {
4660
EventTypeTick,
4761
EventTypeKey,
4862
} EventType;
4963

64+
typedef struct {
65+
const char* name;
66+
uint16_t total_keys;
67+
uint16_t current_key;
68+
bool card_detected;
69+
} PicopassDictAttackContext;
70+
71+
typedef struct {
72+
uint8_t key_to_write[PICOPASS_BLOCK_LEN];
73+
bool is_elite;
74+
} PicopassWriteKeyContext;
75+
76+
typedef struct {
77+
size_t macs_collected;
78+
} PicopassLoclassContext;
79+
5080
struct Picopass {
51-
PicopassWorker* worker;
5281
ViewDispatcher* view_dispatcher;
5382
Gui* gui;
5483
NotificationApp* notifications;
5584
SceneManager* scene_manager;
5685
PicopassDevice* dev;
5786

87+
Nfc* nfc;
88+
PicopassPoller* poller;
89+
PicopassListener* listener;
90+
NfcDict* dict;
91+
5892
char text_store[PICOPASS_TEXT_STORE_SIZE + 1];
5993
FuriString* text_box_store;
6094
uint8_t byte_input_store[PICOPASS_BLOCK_LEN];
@@ -68,6 +102,10 @@ struct Picopass {
68102
Widget* widget;
69103
DictAttack* dict_attack;
70104
Loclass* loclass;
105+
106+
PicopassDictAttackContext dict_attack_ctx;
107+
PicopassWriteKeyContext write_key_context;
108+
PicopassLoclassContext loclass_context;
71109
};
72110

73111
typedef enum {

0 commit comments

Comments
 (0)