|
@@ -70,6 +70,20 @@ NfcCommand picopass_poller_select_handler(PicopassPoller* instance) {
|
|
|
return command;
|
|
return command;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void picopass_poller_print_block(char* str, PicopassBlock block) {
|
|
|
|
|
+ FURI_LOG_D(
|
|
|
|
|
+ TAG,
|
|
|
|
|
+ str,
|
|
|
|
|
+ block.data[0],
|
|
|
|
|
+ block.data[1],
|
|
|
|
|
+ block.data[2],
|
|
|
|
|
+ block.data[3],
|
|
|
|
|
+ block.data[4],
|
|
|
|
|
+ block.data[5],
|
|
|
|
|
+ block.data[6],
|
|
|
|
|
+ block.data[7]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) {
|
|
NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) {
|
|
|
NfcCommand command = NfcCommandContinue;
|
|
NfcCommand command = NfcCommandContinue;
|
|
|
PicopassError error = PicopassErrorNone;
|
|
PicopassError error = PicopassErrorNone;
|
|
@@ -79,17 +93,10 @@ NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) {
|
|
|
instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data,
|
|
instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data,
|
|
|
instance->serial_num.data,
|
|
instance->serial_num.data,
|
|
|
sizeof(PicopassSerialNum));
|
|
sizeof(PicopassSerialNum));
|
|
|
- FURI_LOG_D(
|
|
|
|
|
- TAG,
|
|
|
|
|
|
|
+ instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].valid = true;
|
|
|
|
|
+ picopass_poller_print_block(
|
|
|
"csn %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
"csn %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[0],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[1],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[2],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[3],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[4],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[5],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[6],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data[7]);
|
|
|
|
|
|
|
+ instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX]);
|
|
|
|
|
|
|
|
PicopassBlock block = {};
|
|
PicopassBlock block = {};
|
|
|
error = picopass_poller_read_block(instance, PICOPASS_CONFIG_BLOCK_INDEX, &block);
|
|
error = picopass_poller_read_block(instance, PICOPASS_CONFIG_BLOCK_INDEX, &block);
|
|
@@ -100,18 +107,11 @@ NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) {
|
|
|
memcpy(
|
|
memcpy(
|
|
|
instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data,
|
|
instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data,
|
|
|
block.data,
|
|
block.data,
|
|
|
- sizeof(PicopassBlock));
|
|
|
|
|
- FURI_LOG_D(
|
|
|
|
|
- TAG,
|
|
|
|
|
|
|
+ PICOPASS_BLOCK_LEN);
|
|
|
|
|
+ instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].valid = true;
|
|
|
|
|
+ picopass_poller_print_block(
|
|
|
"config %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
"config %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[0],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[1],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[2],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[3],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[4],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[5],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[6],
|
|
|
|
|
- instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7]);
|
|
|
|
|
|
|
+ instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX]);
|
|
|
|
|
|
|
|
error = picopass_poller_read_block(instance, PICOPASS_SECURE_EPURSE_BLOCK_INDEX, &block);
|
|
error = picopass_poller_read_block(instance, PICOPASS_SECURE_EPURSE_BLOCK_INDEX, &block);
|
|
|
if(error != PicopassErrorNone) {
|
|
if(error != PicopassErrorNone) {
|
|
@@ -121,18 +121,11 @@ NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) {
|
|
|
memcpy(
|
|
memcpy(
|
|
|
instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data,
|
|
instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data,
|
|
|
block.data,
|
|
block.data,
|
|
|
- sizeof(PicopassBlock));
|
|
|
|
|
- FURI_LOG_D(
|
|
|
|
|
- TAG,
|
|
|
|
|
|
|
+ PICOPASS_BLOCK_LEN);
|
|
|
|
|
+ instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].valid = true;
|
|
|
|
|
+ picopass_poller_print_block(
|
|
|
"epurse %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
"epurse %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[0],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[1],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[2],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[3],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[4],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[5],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[6],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data[7]);
|
|
|
|
|
|
|
+ instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX]);
|
|
|
|
|
|
|
|
error = picopass_poller_read_block(instance, PICOPASS_SECURE_AIA_BLOCK_INDEX, &block);
|
|
error = picopass_poller_read_block(instance, PICOPASS_SECURE_AIA_BLOCK_INDEX, &block);
|
|
|
if(error != PicopassErrorNone) {
|
|
if(error != PicopassErrorNone) {
|
|
@@ -142,18 +135,11 @@ NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) {
|
|
|
memcpy(
|
|
memcpy(
|
|
|
instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data,
|
|
instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data,
|
|
|
block.data,
|
|
block.data,
|
|
|
- sizeof(PicopassBlock));
|
|
|
|
|
- FURI_LOG_D(
|
|
|
|
|
- TAG,
|
|
|
|
|
|
|
+ PICOPASS_BLOCK_LEN);
|
|
|
|
|
+ instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].valid = true;
|
|
|
|
|
+ picopass_poller_print_block(
|
|
|
"aia %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
"aia %02x%02x%02x%02x%02x%02x%02x%02x",
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[0],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[1],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[2],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[3],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[4],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[5],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[6],
|
|
|
|
|
- instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data[7]);
|
|
|
|
|
|
|
+ instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX]);
|
|
|
|
|
|
|
|
instance->state = PicopassPollerStateCheckSecurity;
|
|
instance->state = PicopassPollerStateCheckSecurity;
|
|
|
} while(false);
|
|
} while(false);
|
|
@@ -188,12 +174,12 @@ NfcCommand picopass_poller_check_security(PicopassPoller* instance) {
|
|
|
|
|
|
|
|
// Thank you proxmark!
|
|
// Thank you proxmark!
|
|
|
PicopassBlock temp_block = {};
|
|
PicopassBlock temp_block = {};
|
|
|
- memset(temp_block.data, 0xff, sizeof(PicopassBlock));
|
|
|
|
|
|
|
+ memset(temp_block.data, 0xff, PICOPASS_BLOCK_LEN);
|
|
|
instance->data->pacs.legacy =
|
|
instance->data->pacs.legacy =
|
|
|
(memcmp(
|
|
(memcmp(
|
|
|
instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data,
|
|
instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data,
|
|
|
temp_block.data,
|
|
temp_block.data,
|
|
|
- sizeof(PicopassBlock)) == 0);
|
|
|
|
|
|
|
+ PICOPASS_BLOCK_LEN) == 0);
|
|
|
|
|
|
|
|
temp_block.data[3] = 0x00;
|
|
temp_block.data[3] = 0x00;
|
|
|
temp_block.data[4] = 0x06;
|
|
temp_block.data[4] = 0x06;
|
|
@@ -201,7 +187,7 @@ NfcCommand picopass_poller_check_security(PicopassPoller* instance) {
|
|
|
(memcmp(
|
|
(memcmp(
|
|
|
instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data,
|
|
instance->data->card_data[PICOPASS_SECURE_AIA_BLOCK_INDEX].data,
|
|
|
temp_block.data,
|
|
temp_block.data,
|
|
|
- sizeof(PicopassBlock)) == 0);
|
|
|
|
|
|
|
+ PICOPASS_BLOCK_LEN) == 0);
|
|
|
|
|
|
|
|
if(instance->data->pacs.se_enabled) {
|
|
if(instance->data->pacs.se_enabled) {
|
|
|
FURI_LOG_D(TAG, "SE enabled");
|
|
FURI_LOG_D(TAG, "SE enabled");
|
|
@@ -401,6 +387,7 @@ NfcCommand picopass_poller_auth_handler(PicopassPoller* instance) {
|
|
|
if(instance->mode == PicopassPollerModeRead) {
|
|
if(instance->mode == PicopassPollerModeRead) {
|
|
|
memcpy(
|
|
memcpy(
|
|
|
instance->data->pacs.key, instance->event_data.req_key.key, PICOPASS_KEY_LEN);
|
|
instance->data->pacs.key, instance->event_data.req_key.key, PICOPASS_KEY_LEN);
|
|
|
|
|
+ instance->data->card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].valid = true;
|
|
|
instance->data->pacs.elite_kdf = instance->event_data.req_key.is_elite_key;
|
|
instance->data->pacs.elite_kdf = instance->event_data.req_key.is_elite_key;
|
|
|
picopass_poller_prepare_read(instance);
|
|
picopass_poller_prepare_read(instance);
|
|
|
instance->state = PicopassPollerStateReadBlock;
|
|
instance->state = PicopassPollerStateReadBlock;
|
|
@@ -457,7 +444,8 @@ NfcCommand picopass_poller_read_block_handler(PicopassPoller* instance) {
|
|
|
memcpy(
|
|
memcpy(
|
|
|
instance->data->card_data[instance->current_block].data,
|
|
instance->data->card_data[instance->current_block].data,
|
|
|
block.data,
|
|
block.data,
|
|
|
- sizeof(PicopassBlock));
|
|
|
|
|
|
|
+ PICOPASS_BLOCK_LEN);
|
|
|
|
|
+ instance->data->card_data[instance->current_block].valid = true;
|
|
|
instance->current_block++;
|
|
instance->current_block++;
|
|
|
} while(false);
|
|
} while(false);
|
|
|
|
|
|