Skip to content

Commit

Permalink
Picopass: rename AA1 to card_data (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
bettse authored Jan 30, 2024
1 parent e55f891 commit 9a26cf8
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 130 deletions.
56 changes: 28 additions & 28 deletions picopass_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static bool picopass_device_save_file_seader(
FuriString* file_path) {
furi_assert(dev);
PicopassPacs* pacs = &dev->dev_data.pacs;
PicopassBlock* AA1 = dev->dev_data.AA1;
PicopassBlock* card_data = dev->dev_data.card_data;
bool result = false;

const char* seader_file_header = "Flipper Seader Credential";
Expand All @@ -67,17 +67,17 @@ static bool picopass_device_save_file_seader(
// TODO: save SR vs SE more properly
if(pacs->sio) { // SR
for(uint8_t i = 0; i < 8; i++) {
memcpy(sio + (i * 8), AA1[10 + i].data, PICOPASS_BLOCK_LEN);
memcpy(sio + (i * 8), card_data[10 + i].data, PICOPASS_BLOCK_LEN);
}
if(!flipper_format_write_hex(file, "SIO", sio, sizeof(sio))) break;
} else if(pacs->se_enabled) { //SE
for(uint8_t i = 0; i < 8; i++) {
memcpy(sio + (i * 8), AA1[6 + i].data, PICOPASS_BLOCK_LEN);
memcpy(sio + (i * 8), card_data[6 + i].data, PICOPASS_BLOCK_LEN);
}
if(!flipper_format_write_hex(file, "SIO", sio, sizeof(sio))) break;
}
if(!flipper_format_write_hex(
file, "Diversifier", AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN))
file, "Diversifier", card_data[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN))
break;

result = true;
Expand Down Expand Up @@ -162,13 +162,13 @@ static bool picopass_device_save_file(
bool saved = false;
FlipperFormat* file = flipper_format_file_alloc(dev->storage);
PicopassPacs* pacs = &dev->dev_data.pacs;
PicopassBlock* AA1 = dev->dev_data.AA1;
PicopassBlock* card_data = dev->dev_data.card_data;
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);
memset(card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].data, 0, PICOPASS_BLOCK_LEN);
}

do {
Expand Down Expand Up @@ -197,13 +197,13 @@ static bool picopass_device_save_file(
if(!flipper_format_write_comment_cstr(file, "Picopass blocks")) break;
bool block_saved = true;

size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] < PICOPASS_MAX_APP_LIMIT ?
AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] :
size_t app_limit = card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[0] < PICOPASS_MAX_APP_LIMIT ?
card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[0] :
PICOPASS_MAX_APP_LIMIT;
for(size_t i = 0; i < app_limit; i++) {
furi_string_printf(temp_str, "Block %d", i);
if(!flipper_format_write_hex(
file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) {
file, furi_string_get_cstr(temp_str), card_data[i].data, PICOPASS_BLOCK_LEN)) {
block_saved = false;
break;
}
Expand Down Expand Up @@ -245,7 +245,7 @@ bool picopass_device_save(PicopassDevice* dev, const char* dev_name) {
static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, bool show_dialog) {
bool parsed = false;
FlipperFormat* file = flipper_format_file_alloc(dev->storage);
PicopassBlock* AA1 = dev->dev_data.AA1;
PicopassBlock* card_data = dev->dev_data.card_data;
PicopassPacs* pacs = &dev->dev_data.pacs;
FuriString* temp_str;
temp_str = furi_string_alloc();
Expand All @@ -272,26 +272,26 @@ static bool picopass_device_load_data(PicopassDevice* dev, FuriString* path, boo
for(size_t i = 0; i < 6; i++) {
furi_string_printf(temp_str, "Block %d", i);
if(!flipper_format_read_hex(
file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) {
file, furi_string_get_cstr(temp_str), card_data[i].data, PICOPASS_BLOCK_LEN)) {
block_read = false;
break;
}
}

size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0];
size_t app_limit = card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[0];
// Fix for unpersonalized cards that have app_limit set to 0xFF
if(app_limit > PICOPASS_MAX_APP_LIMIT) app_limit = PICOPASS_MAX_APP_LIMIT;
for(size_t i = 6; i < app_limit; i++) {
furi_string_printf(temp_str, "Block %d", i);
if(!flipper_format_read_hex(
file, furi_string_get_cstr(temp_str), AA1[i].data, PICOPASS_BLOCK_LEN)) {
file, furi_string_get_cstr(temp_str), card_data[i].data, PICOPASS_BLOCK_LEN)) {
block_read = false;
break;
}
}
if(!block_read) break;

picopass_device_parse_credential(AA1, pacs);
picopass_device_parse_credential(card_data, pacs);
picopass_device_parse_wiegand(pacs->credential, pacs);

parsed = true;
Expand Down Expand Up @@ -364,7 +364,7 @@ bool picopass_file_select(PicopassDevice* dev) {

void picopass_device_data_clear(PicopassDeviceData* dev_data) {
for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) {
memset(dev_data->AA1[i].data, 0, sizeof(dev_data->AA1[i].data));
memset(dev_data->card_data[i].data, 0, sizeof(dev_data->card_data[i].data));
}
dev_data->pacs.legacy = false;
dev_data->pacs.se_enabled = false;
Expand Down Expand Up @@ -419,30 +419,30 @@ void picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) {
mbedtls_des3_free(&ctx);
}

void picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) {
pacs->biometrics = AA1[6].data[4];
pacs->pin_length = AA1[6].data[6] & 0x0F;
pacs->encryption = AA1[6].data[7];
void picopass_device_parse_credential(PicopassBlock* card_data, PicopassPacs* pacs) {
pacs->biometrics = card_data[6].data[4];
pacs->pin_length = card_data[6].data[6] & 0x0F;
pacs->encryption = card_data[6].data[7];

if(pacs->encryption == PicopassDeviceEncryption3DES) {
FURI_LOG_D(TAG, "3DES Encrypted");
picopass_device_decrypt(AA1[7].data, pacs->credential);
picopass_device_decrypt(card_data[7].data, pacs->credential);

picopass_device_decrypt(AA1[8].data, pacs->pin0);
picopass_device_decrypt(card_data[8].data, pacs->pin0);

picopass_device_decrypt(AA1[9].data, pacs->pin1);
picopass_device_decrypt(card_data[9].data, pacs->pin1);
} else if(pacs->encryption == PicopassDeviceEncryptionNone) {
FURI_LOG_D(TAG, "No Encryption");
memcpy(pacs->credential, AA1[7].data, PICOPASS_BLOCK_LEN);
memcpy(pacs->pin0, AA1[8].data, PICOPASS_BLOCK_LEN);
memcpy(pacs->pin1, AA1[9].data, PICOPASS_BLOCK_LEN);
memcpy(pacs->credential, card_data[7].data, PICOPASS_BLOCK_LEN);
memcpy(pacs->pin0, card_data[8].data, PICOPASS_BLOCK_LEN);
memcpy(pacs->pin1, card_data[9].data, PICOPASS_BLOCK_LEN);
} else if(pacs->encryption == PicopassDeviceEncryptionDES) {
FURI_LOG_D(TAG, "DES Encrypted");
} else {
FURI_LOG_D(TAG, "Unknown encryption");
}

pacs->sio = (AA1[10].data[0] == 0x30); // rough check
pacs->sio = (card_data[10].data[0] == 0x30); // rough check
}

void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs) {
Expand All @@ -466,8 +466,8 @@ void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs) {

bool picopass_device_hid_csn(PicopassDevice* dev) {
furi_assert(dev);
PicopassBlock* AA1 = dev->dev_data.AA1;
uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data;
PicopassBlock* card_data = dev->dev_data.card_data;
uint8_t* csn = card_data[PICOPASS_CSN_BLOCK_INDEX].data;
// From Proxmark3 RRG sourcecode
bool isHidRange = (memcmp(csn + 5, "\xFF\x12\xE0", 3) == 0) && ((csn[4] & 0xF0) == 0xF0);

Expand Down
4 changes: 2 additions & 2 deletions picopass_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ typedef struct {
} PicopassBlock;

typedef struct {
PicopassBlock AA1[PICOPASS_MAX_APP_LIMIT];
PicopassBlock card_data[PICOPASS_MAX_APP_LIMIT];
PicopassPacs pacs;
} PicopassDeviceData;

Expand Down Expand Up @@ -148,6 +148,6 @@ void picopass_device_set_loading_callback(
PicopassLoadingCallback callback,
void* context);

void picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs);
void picopass_device_parse_credential(PicopassBlock* card_data, PicopassPacs* pacs);
void picopass_device_parse_wiegand(uint8_t* credential, PicopassPacs* pacs);
bool picopass_device_hid_csn(PicopassDevice* dev);
42 changes: 21 additions & 21 deletions protocol/picopass_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ static void picopass_listener_loclass_update_csn(PicopassListener* instance) {
// collect LOCLASS_NUM_PER_CSN nonces in a row for each CSN
const uint8_t* csn =
loclass_csns[(instance->key_block_num / LOCLASS_NUM_PER_CSN) % LOCLASS_NUM_CSNS];
memcpy(instance->data->AA1[PICOPASS_CSN_BLOCK_INDEX].data, csn, sizeof(PicopassBlock));
memcpy(instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data, csn, sizeof(PicopassBlock));

uint8_t key[PICOPASS_BLOCK_LEN] = {};
loclass_iclass_calc_div_key(csn, picopass_iclass_key, key, false);
memcpy(instance->data->AA1[PICOPASS_SECURE_KD_BLOCK_INDEX].data, key, sizeof(PicopassBlock));
memcpy(instance->data->card_data[PICOPASS_SECURE_KD_BLOCK_INDEX].data, key, sizeof(PicopassBlock));

picopass_listener_init_cipher_state_key(instance, key);
}
Expand Down Expand Up @@ -118,7 +118,7 @@ PicopassListenerCommand
(instance->state == PicopassListenerStateIdle)) {
bit_buffer_copy_bytes(
instance->tmp_buffer,
instance->data->AA1[PICOPASS_CSN_BLOCK_INDEX].data,
instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data,
sizeof(PicopassBlock));
} else {
picopass_listener_write_anticoll_csn(instance, instance->tmp_buffer);
Expand All @@ -139,7 +139,7 @@ PicopassListenerCommand
instance->state = PicopassListenerStateSelected;
bit_buffer_copy_bytes(
instance->tx_buffer,
instance->data->AA1[PICOPASS_CSN_BLOCK_INDEX].data,
instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data,
sizeof(PicopassBlock));

PicopassError error = picopass_listener_send_frame(instance, instance->tx_buffer);
Expand All @@ -162,7 +162,7 @@ PicopassListenerCommand
uint8_t block_num = bit_buffer_get_byte(buf, 1);
if(block_num > PICOPASS_MAX_APP_LIMIT) break;

bool secured = (instance->data->AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
bool secured = (instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
PICOPASS_FUSE_CRYPT10) != PICOPASS_FUSE_CRYPT0;

// TODO: Check CRC?
Expand All @@ -176,7 +176,7 @@ PicopassListenerCommand
}
} else {
bit_buffer_copy_bytes(
instance->tx_buffer, instance->data->AA1[block_num].data, sizeof(PicopassBlock));
instance->tx_buffer, instance->data->card_data[block_num].data, sizeof(PicopassBlock));
}
PicopassError error = picopass_listener_send_frame(instance, instance->tx_buffer);
if(error != PicopassErrorNone) {
Expand Down Expand Up @@ -211,7 +211,7 @@ static PicopassListenerCommand

// DATA(8)
bit_buffer_copy_bytes(
instance->tx_buffer, instance->data->AA1[block_num].data, sizeof(PicopassBlock));
instance->tx_buffer, instance->data->card_data[block_num].data, sizeof(PicopassBlock));
NfcError error = nfc_listener_tx(instance->nfc, instance->tx_buffer);
if(error != NfcErrorNone) {
FURI_LOG_D(TAG, "Failed to tx read check response: %d", error);
Expand Down Expand Up @@ -244,7 +244,7 @@ PicopassListenerCommand
#ifndef PICOPASS_DEBUG_IGNORE_LOCLASS_STD_KEY
// loclass mode stores the derived standard debit key in Kd to check

PicopassBlock key = instance->data->AA1[PICOPASS_SECURE_KD_BLOCK_INDEX];
PicopassBlock key = instance->data->card_data[PICOPASS_SECURE_KD_BLOCK_INDEX];
uint8_t rmac[4];
const uint8_t* rx_data = bit_buffer_get_data(buf);
loclass_opt_doReaderMAC_2(instance->cipher_state, &rx_data[1], rmac, key.data);
Expand Down Expand Up @@ -285,8 +285,8 @@ PicopassListenerCommand
loclass_writer_write_params(
instance->writer,
instance->key_block_num + i - LOCLASS_NUM_PER_CSN,
instance->data->AA1[PICOPASS_CSN_BLOCK_INDEX].data,
instance->data->AA1[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data,
instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data,
instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data,
instance->loclass_mac_buffer + (i * 8),
instance->loclass_mac_buffer + (i * 8) + 4);
}
Expand Down Expand Up @@ -314,8 +314,8 @@ PicopassListenerCommand

PicopassDevice* dev = picopass->dev;

const uint8_t* csn = instance->data->AA1[PICOPASS_CSN_BLOCK_INDEX].data;
const uint8_t* epurse = instance->data->AA1[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data;
const uint8_t* csn = instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data;
const uint8_t* epurse = instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data;

FuriString* temp_str = furi_string_alloc();
FuriString* filename = furi_string_alloc();
Expand Down Expand Up @@ -368,13 +368,13 @@ PicopassListenerCommand
PicopassListenerCommand command = PicopassListenerCommandSilent;

do {
bool secured = (instance->data->AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
bool secured = (instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
PICOPASS_FUSE_CRYPT10) != PICOPASS_FUSE_CRYPT0;
if(!secured) break;

uint8_t rmac[4] = {};
uint8_t tmac[4] = {};
const uint8_t* key = instance->data->AA1[instance->key_block_num].data;
const uint8_t* key = instance->data->card_data[instance->key_block_num].data;
bool no_key = picopass_is_memset(key, 0x00, PICOPASS_BLOCK_LEN);
const uint8_t* rx_data = bit_buffer_get_data(buf);

Expand Down Expand Up @@ -432,9 +432,9 @@ PicopassListenerCommand
if(instance->mode == PicopassListenerModeLoclass) break;
if(instance->state != PicopassListenerStateSelected) break;

PicopassBlock config_block = instance->data->AA1[PICOPASS_CONFIG_BLOCK_INDEX];
PicopassBlock config_block = instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX];
bool pers_mode = PICOPASS_LISTENER_HAS_MASK(config_block.data[7], PICOPASS_FUSE_PERS);
bool secured = (instance->data->AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
bool secured = (instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
PICOPASS_FUSE_CRYPT10) != PICOPASS_FUSE_CRYPT0;

const uint8_t* rx_data = bit_buffer_get_data(buf);
Expand Down Expand Up @@ -502,7 +502,7 @@ PicopassListenerCommand
// fallthrough
case PICOPASS_SECURE_KC_BLOCK_INDEX:
if(!pers_mode && secured) {
new_block = instance->data->AA1[block_num];
new_block = instance->data->card_data[block_num];
for(size_t i = 0; i < sizeof(PicopassBlock); i++) {
new_block.data[i] ^= rx_data[i + 2];
}
Expand All @@ -515,7 +515,7 @@ PicopassListenerCommand
break;
}

instance->data->AA1[block_num] = new_block;
instance->data->card_data[block_num] = new_block;
if(secured && ((block_num == instance->key_block_num) ||
(block_num == PICOPASS_SECURE_EPURSE_BLOCK_INDEX))) {
picopass_listener_init_cipher_state(instance);
Expand All @@ -530,7 +530,7 @@ PicopassListenerCommand
}
} else {
bit_buffer_copy_bytes(
instance->tx_buffer, instance->data->AA1[block_num].data, sizeof(PicopassBlock));
instance->tx_buffer, instance->data->card_data[block_num].data, sizeof(PicopassBlock));
}

PicopassError error = picopass_listener_send_frame(instance, instance->tx_buffer);
Expand All @@ -555,7 +555,7 @@ PicopassListenerCommand
uint8_t block_start = bit_buffer_get_byte(buf, 1);
if(block_start + 4 >= PICOPASS_MAX_APP_LIMIT) break;

bool secured = (instance->data->AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
bool secured = (instance->data->card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] &
PICOPASS_FUSE_CRYPT10) != PICOPASS_FUSE_CRYPT0;

// TODO: Check CRC?
Expand All @@ -570,7 +570,7 @@ PicopassListenerCommand
}
} else {
bit_buffer_append_bytes(
instance->tx_buffer, instance->data->AA1[i].data, sizeof(PicopassBlock));
instance->tx_buffer, instance->data->card_data[i].data, sizeof(PicopassBlock));
}
}

Expand Down
6 changes: 3 additions & 3 deletions protocol/picopass_listener_i.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ static PicopassError picopass_listener_process_error(NfcError error) {
void picopass_listener_init_cipher_state_key(PicopassListener* instance, const uint8_t* key) {
uint8_t cc[PICOPASS_BLOCK_LEN] = {};
memcpy(
cc, instance->data->AA1[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data, sizeof(PicopassBlock));
cc, instance->data->card_data[PICOPASS_SECURE_EPURSE_BLOCK_INDEX].data, sizeof(PicopassBlock));

instance->cipher_state = loclass_opt_doTagMAC_1(cc, key);
}

void picopass_listener_init_cipher_state(PicopassListener* instance) {
uint8_t key[PICOPASS_BLOCK_LEN] = {};
memcpy(key, instance->data->AA1[instance->key_block_num].data, sizeof(PicopassBlock));
memcpy(key, instance->data->card_data[instance->key_block_num].data, sizeof(PicopassBlock));

picopass_listener_init_cipher_state_key(instance, key);
}
Expand All @@ -42,7 +42,7 @@ PicopassError picopass_listener_send_frame(PicopassListener* instance, BitBuffer

// from proxmark3 armsrc/iclass.c rotateCSN
PicopassError picopass_listener_write_anticoll_csn(PicopassListener* instance, BitBuffer* buffer) {
const uint8_t* uid = instance->data->AA1[PICOPASS_CSN_BLOCK_INDEX].data;
const uint8_t* uid = instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data;
bit_buffer_reset(buffer);
for(size_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
bit_buffer_append_byte(buffer, (uid[i] >> 3) | (uid[(i + 1) % 8] << 5));
Expand Down
Loading

0 comments on commit 9a26cf8

Please sign in to comment.