mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-14 16:15:07 +00:00
Handle implicitly selected DF in 'hf calypso info'
This commit is contained in:
+312
-74
@@ -82,6 +82,34 @@ typedef struct {
|
||||
uint8_t startup[CALYPSO_STARTUP_LEN];
|
||||
} calypso_fci_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t key_versions[3];
|
||||
uint8_t key_types[3];
|
||||
uint8_t rfu;
|
||||
uint16_t lid;
|
||||
} calypso_df_fcp_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t data_ref[2];
|
||||
uint8_t rfu[5];
|
||||
uint16_t lid;
|
||||
} calypso_ef_fcp_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t sfi;
|
||||
uint8_t file_type;
|
||||
uint8_t ef_type;
|
||||
uint8_t record_size;
|
||||
uint8_t num_records;
|
||||
uint8_t access_conditions[4];
|
||||
uint8_t key_indexes[4];
|
||||
uint8_t status;
|
||||
union {
|
||||
calypso_df_fcp_t df;
|
||||
calypso_ef_fcp_t ef;
|
||||
} specific;
|
||||
} calypso_fcp_t;
|
||||
|
||||
typedef struct {
|
||||
bool present;
|
||||
isodep_state_t protocol;
|
||||
@@ -94,6 +122,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint8_t requested_aid[CALYPSO_MAX_AID_LEN];
|
||||
size_t requested_aid_len;
|
||||
bool default_selection;
|
||||
bool has_df_lid;
|
||||
uint16_t df_lid;
|
||||
calypso_rf_info_t rf;
|
||||
uint8_t fci[APDU_RES_LEN];
|
||||
size_t fci_len;
|
||||
@@ -173,6 +204,11 @@ static calypso_resource_t calypso_ic_families_resource = {CALYPSO_IC_FAMILIES_RE
|
||||
static calypso_resource_t calypso_operators_resource = {CALYPSO_OPERATORS_RESOURCE, NULL, false};
|
||||
|
||||
static const char *calypso_json_lookup_name(calypso_resource_t *resource, uint32_t id);
|
||||
static void calypso_set_selected_result(bool is_implicitly_selected, const uint8_t *aid, size_t aid_len, bool has_df_lid, uint16_t df_lid, const calypso_rf_info_t *rf, const uint8_t *fci_data, size_t fci_len, uint16_t sw, const calypso_fci_t *fci, calypso_select_result_t *selected);
|
||||
static bool calypso_fcp_default_lid(const calypso_fcp_t *fcp, uint16_t *lid);
|
||||
static bool calypso_get_current_ef_lid(bool verbose, uint16_t *lid);
|
||||
static bool calypso_read_sw_has_data(uint16_t sw, size_t read_len);
|
||||
static int calypso_get_data_object(uint16_t tag, uint8_t *out, size_t out_len, size_t *read_len, uint16_t *sw);
|
||||
static void calypso_reselect_exact_df_name(const calypso_select_result_t *selected, bool verbose);
|
||||
static void calypso_print_rf_info(const calypso_rf_info_t *rf);
|
||||
|
||||
@@ -450,6 +486,43 @@ static bool calypso_parse_fci(const uint8_t *data, size_t data_len, calypso_fci_
|
||||
return fci->has_serial && fci->has_startup;
|
||||
}
|
||||
|
||||
static bool calypso_parse_fcp(const uint8_t *data, size_t data_len, calypso_fcp_t *fcp) {
|
||||
memset(fcp, 0, sizeof(*fcp));
|
||||
|
||||
struct tlvdb *tlv = tlvdb_parse_multi(data, data_len);
|
||||
if (tlv == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const struct tlv *calypso_file_header = tlvdb_get_tlv(tlvdb_find_full(tlv, 0x85));
|
||||
if (calypso_file_header != NULL && calypso_file_header->len == 0x17) {
|
||||
const uint8_t *value = calypso_file_header->value;
|
||||
fcp->sfi = value[0];
|
||||
fcp->file_type = value[1];
|
||||
fcp->ef_type = value[2];
|
||||
fcp->record_size = value[3];
|
||||
fcp->num_records = value[4];
|
||||
memcpy(fcp->access_conditions, &value[5], sizeof(fcp->access_conditions));
|
||||
memcpy(fcp->key_indexes, &value[9], sizeof(fcp->key_indexes));
|
||||
fcp->status = value[13];
|
||||
if (fcp->file_type == 0x01 || fcp->file_type == 0x02) {
|
||||
memcpy(fcp->specific.df.key_versions, &value[14], sizeof(fcp->specific.df.key_versions));
|
||||
memcpy(fcp->specific.df.key_types, &value[17], sizeof(fcp->specific.df.key_types));
|
||||
fcp->specific.df.rfu = value[20];
|
||||
fcp->specific.df.lid = ((uint16_t)value[21] << 8) | value[22];
|
||||
} else if (fcp->file_type == 0x04) {
|
||||
memcpy(fcp->specific.ef.data_ref, &value[14], sizeof(fcp->specific.ef.data_ref));
|
||||
memcpy(fcp->specific.ef.rfu, &value[16], sizeof(fcp->specific.ef.rfu));
|
||||
fcp->specific.ef.lid = ((uint16_t)value[21] << 8) | value[22];
|
||||
}
|
||||
tlvdb_free(tlv);
|
||||
return true;
|
||||
}
|
||||
|
||||
tlvdb_free(tlv);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char *calypso_json_string_get(json_t *obj, const char *name) {
|
||||
json_t *value = json_object_get(obj, name);
|
||||
return json_is_string(value) ? json_string_value(value) : NULL;
|
||||
@@ -668,7 +741,7 @@ static void calypso_aid_attribution_init(const calypso_select_result_t *selected
|
||||
return;
|
||||
}
|
||||
|
||||
calypso_find_aid_match(attribution->root, selected->requested_aid, selected->requested_aid_len, "selected AID", &attribution->selected_match);
|
||||
calypso_find_aid_match(attribution->root, selected->requested_aid, selected->requested_aid_len, selected->default_selection ? "default selection AID" : "selected AID", &attribution->selected_match);
|
||||
if (selected->parsed.has_df_name) {
|
||||
calypso_find_aid_match(attribution->root, selected->parsed.df_name, selected->parsed.df_name_len, "DF name", &attribution->df_name_match);
|
||||
}
|
||||
@@ -763,11 +836,13 @@ static int calypso_select_attribution_score(json_t *root, const calypso_select_r
|
||||
static int calypso_select_aid(const uint8_t *aid, size_t aid_len, bool verbose, const calypso_rf_info_t *rf, calypso_select_result_t *selected, bool *matched) {
|
||||
*matched = false;
|
||||
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
uint16_t sw = 0;
|
||||
uint8_t select_response[APDU_RES_LEN] = {0};
|
||||
size_t select_response_len = 0;
|
||||
uint16_t select_sw = 0;
|
||||
bool has_df_lid = false;
|
||||
uint16_t df_lid = 0;
|
||||
|
||||
int res = Iso7816Select(CC_CONTACTLESS, false, true, (uint8_t *)aid, aid_len, response, sizeof(response), &response_len, &sw);
|
||||
int res = Iso7816Select(CC_CONTACTLESS, false, true, (uint8_t *)aid, aid_len, select_response, sizeof(select_response), &select_response_len, &select_sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "Select AID %s failed: %d", sprint_hex_inrow(aid, aid_len), res);
|
||||
@@ -775,34 +850,24 @@ static int calypso_select_aid(const uint8_t *aid, size_t aid_len, bool verbose,
|
||||
return res;
|
||||
}
|
||||
|
||||
if (sw != ISO7816_OK && sw != 0x6283) {
|
||||
if (select_sw != ISO7816_OK && select_sw != 0x6283) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "Select AID %s returned %04X - %s", sprint_hex_inrow(aid, aid_len), sw, GetAPDUCodeDescription(sw >> 8, sw & 0xFF));
|
||||
PrintAndLogEx(DEBUG, "Select AID %s returned %04X - %s", sprint_hex_inrow(aid, aid_len), select_sw, GetAPDUCodeDescription(select_sw >> 8, select_sw & 0xFF));
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
calypso_fci_t fci = {0};
|
||||
if (calypso_parse_fci(response, response_len, &fci) == false) {
|
||||
if (calypso_parse_fci(select_response, select_response_len, &fci) == false) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "Select AID %s returned non-Calypso FCI", sprint_hex_inrow(aid, aid_len));
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
memset(selected, 0, sizeof(*selected));
|
||||
memcpy(selected->requested_aid, aid, aid_len);
|
||||
selected->requested_aid_len = aid_len;
|
||||
if (rf != NULL) {
|
||||
selected->rf = *rf;
|
||||
}
|
||||
if (selected->rf.present == false) {
|
||||
selected->rf.protocol = GetISODEPState();
|
||||
}
|
||||
memcpy(selected->fci, response, response_len);
|
||||
selected->fci_len = response_len;
|
||||
selected->sw = sw;
|
||||
selected->parsed = fci;
|
||||
has_df_lid = calypso_get_current_ef_lid(verbose, &df_lid);
|
||||
|
||||
calypso_set_selected_result(false, aid, aid_len, has_df_lid, df_lid, rf, select_response, select_response_len, select_sw, &fci, selected);
|
||||
|
||||
*matched = true;
|
||||
return PM3_SUCCESS;
|
||||
@@ -1125,11 +1190,182 @@ static int calypso_get_data_object(uint16_t tag, uint8_t *out, size_t out_len, s
|
||||
return calypso_exchange_apdu(apdu, true, 0, out, out_len, read_len, sw);
|
||||
}
|
||||
|
||||
static int calypso_unselect_file(uint16_t *sw) {
|
||||
static void calypso_set_selected_result(bool is_implicitly_selected, const uint8_t *aid, size_t aid_len, bool has_df_lid, uint16_t df_lid, const calypso_rf_info_t *rf, const uint8_t *fci_data, size_t fci_len, uint16_t sw, const calypso_fci_t *fci, calypso_select_result_t *selected) {
|
||||
memset(selected, 0, sizeof(*selected));
|
||||
if (aid != NULL && aid_len > 0) {
|
||||
memcpy(selected->requested_aid, aid, aid_len);
|
||||
selected->requested_aid_len = aid_len;
|
||||
}
|
||||
selected->default_selection = is_implicitly_selected;
|
||||
selected->has_df_lid = has_df_lid;
|
||||
selected->df_lid = df_lid;
|
||||
if (rf != NULL) {
|
||||
selected->rf = *rf;
|
||||
}
|
||||
if (selected->rf.present == false) {
|
||||
selected->rf.protocol = GetISODEPState();
|
||||
}
|
||||
memcpy(selected->fci, fci_data, fci_len);
|
||||
selected->fci_len = fci_len;
|
||||
selected->sw = sw;
|
||||
selected->parsed = *fci;
|
||||
}
|
||||
|
||||
static bool calypso_selected_has_fci_info(const calypso_select_result_t *selected) {
|
||||
if (selected == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return selected->parsed.has_df_name || selected->parsed.has_serial || selected->parsed.has_startup;
|
||||
}
|
||||
|
||||
static bool calypso_fcp_default_lid(const calypso_fcp_t *fcp, uint16_t *lid) {
|
||||
if (fcp == NULL || lid == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fcp->file_type == 0x01 || fcp->file_type == 0x02) {
|
||||
*lid = fcp->specific.df.lid;
|
||||
return *lid != 0x0000;
|
||||
}
|
||||
|
||||
if (fcp->file_type == 0x04) {
|
||||
*lid = fcp->specific.ef.lid;
|
||||
return *lid != 0x0000;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool calypso_get_current_ef_lid(bool verbose, uint16_t *lid) {
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
sAPDU_t apdu = {0x00, ISO7816_SELECT_FILE, CALYPSO_SELECT_CURRENT_DF_P1, CALYPSO_SELECT_CURRENT_DF_P2, 0, NULL};
|
||||
return calypso_exchange_apdu_with_cla_fallback(apdu, true, 0, response, sizeof(response), &response_len, sw);
|
||||
uint16_t sw = 0;
|
||||
int res = calypso_get_data_object(0x0062, response, sizeof(response), &response_len, &sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "GET DATA 0062 exchange failed: %d", res);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
calypso_fcp_t fcp = {0};
|
||||
if (calypso_read_sw_has_data(sw, response_len) && calypso_parse_fcp(response, response_len, &fcp)) {
|
||||
return calypso_fcp_default_lid(&fcp, lid);
|
||||
}
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "GET DATA 0062 did not return Calypso FCP (%04X - %s)", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xFF));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int calypso_select_current_df(bool include_file_id, uint8_t *response, size_t response_max, size_t *response_len, uint16_t *sw) {
|
||||
uint8_t current_df_id[] = {0x00, 0x00};
|
||||
sAPDU_t apdu = {
|
||||
0x00,
|
||||
ISO7816_SELECT_FILE,
|
||||
CALYPSO_SELECT_CURRENT_DF_P1,
|
||||
CALYPSO_SELECT_CURRENT_DF_P2,
|
||||
include_file_id ? sizeof(current_df_id) : 0,
|
||||
include_file_id ? current_df_id : NULL
|
||||
};
|
||||
|
||||
return calypso_exchange_apdu_with_cla_fallback(apdu, true, 0, response, response_max, response_len, sw);
|
||||
}
|
||||
|
||||
static int calypso_select_current_df_with_file_id_fallback(uint8_t *response, size_t response_max, size_t *response_len, uint16_t *sw) {
|
||||
int res = calypso_select_current_df(false, response, response_max, response_len, sw);
|
||||
if (res != PM3_SUCCESS || calypso_select_sw_has_file(*sw)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
*response_len = 0;
|
||||
*sw = 0;
|
||||
return calypso_select_current_df(true, response, response_max, response_len, sw);
|
||||
}
|
||||
|
||||
static int calypso_probe_current_df(const calypso_rf_info_t *rf, bool verbose, calypso_select_result_t *selected, bool *matched) {
|
||||
*matched = false;
|
||||
|
||||
bool has_df_lid = false;
|
||||
uint16_t df_lid = 0;
|
||||
const uint8_t *fci_data = NULL;
|
||||
size_t fci_len = 0;
|
||||
uint16_t fci_sw = 0;
|
||||
calypso_fci_t fci = {0};
|
||||
|
||||
uint8_t select_response[APDU_RES_LEN] = {0};
|
||||
size_t select_response_len = 0;
|
||||
uint16_t select_response_sw = 0;
|
||||
int select_res = calypso_select_current_df_with_file_id_fallback(select_response, sizeof(select_response), &select_response_len, &select_response_sw);
|
||||
if (select_res != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "Current DF SELECT exchange failed: %d", select_res);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
if (calypso_select_sw_has_file(select_response_sw) == false) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "Current DF SELECT did not select a file (%04X - %s)", select_response_sw, GetAPDUCodeDescription(select_response_sw >> 8, select_response_sw & 0xFF));
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
calypso_fci_t select_fci = {0};
|
||||
if (calypso_parse_fci(select_response, select_response_len, &select_fci)) {
|
||||
fci_data = select_response;
|
||||
fci_len = select_response_len;
|
||||
fci_sw = select_response_sw;
|
||||
fci = select_fci;
|
||||
} else {
|
||||
calypso_fcp_t fcp = {0};
|
||||
if (calypso_parse_fcp(select_response, select_response_len, &fcp)) {
|
||||
has_df_lid = calypso_fcp_default_lid(&fcp, &df_lid);
|
||||
}
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "Current DF SELECT did not return Calypso FCI (%04X - %s)", select_response_sw, GetAPDUCodeDescription(select_response_sw >> 8, select_response_sw & 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t aid[CALYPSO_MAX_AID_LEN] = {0};
|
||||
size_t aid_len = 0;
|
||||
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = calypso_get_data_object(0x006F, response, sizeof(response), &response_len, &sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "GET DATA 006F exchange failed: %d", res);
|
||||
}
|
||||
} else {
|
||||
calypso_fci_t get_data_fci = {0};
|
||||
if (calypso_read_sw_has_data(sw, response_len) && calypso_parse_fci(response, response_len, &get_data_fci)) {
|
||||
fci_data = response;
|
||||
fci_len = response_len;
|
||||
fci_sw = sw;
|
||||
fci = get_data_fci;
|
||||
} else if (verbose) {
|
||||
PrintAndLogEx(DEBUG, "GET DATA 006F did not return Calypso FCI (%04X - %s)", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t get_data_lid = 0;
|
||||
if (calypso_get_current_ef_lid(verbose, &get_data_lid)) {
|
||||
has_df_lid = true;
|
||||
df_lid = get_data_lid;
|
||||
}
|
||||
|
||||
if (fci_data != NULL) {
|
||||
if (aid_len == 0 && fci.has_df_name && fci.df_name_len <= sizeof(aid)) {
|
||||
memcpy(aid, fci.df_name, fci.df_name_len);
|
||||
aid_len = fci.df_name_len;
|
||||
}
|
||||
calypso_set_selected_result(true, aid_len > 0 ? aid : NULL, aid_len, has_df_lid, df_lid, rf, fci_data, fci_len, fci_sw, &fci, selected);
|
||||
*matched = true;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int calypso_read_sfi_record(uint8_t sfi, uint8_t record, uint16_t le, uint8_t *out, size_t out_len, size_t *read_len, uint16_t *sw) {
|
||||
@@ -1193,8 +1429,10 @@ static int calypso_read_current_record(uint8_t record, uint16_t le, uint8_t *out
|
||||
}
|
||||
|
||||
static int calypso_read_icc_file(uint8_t *icc, size_t icc_len, size_t *read_len, uint16_t *sw) {
|
||||
uint16_t unselect_sw = 0;
|
||||
calypso_unselect_file(&unselect_sw);
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
uint16_t current_df_sw = 0;
|
||||
calypso_select_current_df_with_file_id_fallback(response, sizeof(response), &response_len, ¤t_df_sw);
|
||||
|
||||
int res = calypso_select_file_by_id(CALYPSO_ICC_FILE_ID, sw);
|
||||
if (res != PM3_SUCCESS || calypso_select_sw_has_file(*sw) == false) {
|
||||
@@ -1270,8 +1508,10 @@ static bool calypso_read_icc_from_master_file(const calypso_select_result_t *sel
|
||||
}
|
||||
|
||||
static int calypso_read_ticketing_environment_file(uint8_t *env, size_t env_len, size_t *read_len, uint16_t *sw) {
|
||||
uint16_t unselect_sw = 0;
|
||||
calypso_unselect_file(&unselect_sw);
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
uint16_t current_df_sw = 0;
|
||||
calypso_select_current_df_with_file_id_fallback(response, sizeof(response), &response_len, ¤t_df_sw);
|
||||
|
||||
int res = calypso_select_file_by_id(CALYPSO_TICKET_DIR_ID, sw);
|
||||
if (res != PM3_SUCCESS || calypso_select_sw_has_file(*sw) == false) {
|
||||
@@ -1307,22 +1547,6 @@ static int calypso_read_ticketing_environment(uint8_t *env, size_t env_len, size
|
||||
return calypso_read_ticketing_environment_file(env, env_len, read_len, sw);
|
||||
}
|
||||
|
||||
static void calypso_hex_nospace(const uint8_t *data, size_t data_len, char *out, size_t out_len) {
|
||||
if (out_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < data_len && pos + 2 < out_len; i++) {
|
||||
int written = snprintf(out + pos, out_len - pos, "%02X", data[i]);
|
||||
if (written != 2) {
|
||||
break;
|
||||
}
|
||||
pos += 2;
|
||||
}
|
||||
out[pos] = '\0';
|
||||
}
|
||||
|
||||
static void calypso_dump_context_add_serial(calypso_dump_context_t *ctx, const calypso_select_result_t *selected) {
|
||||
if (ctx == NULL || selected == NULL || selected->parsed.has_serial == false) {
|
||||
return;
|
||||
@@ -1366,9 +1590,7 @@ static void calypso_dump_default_filename(const calypso_select_result_t *selecte
|
||||
serial_len -= CALYPSO_HCE_TOKEN_LEN;
|
||||
}
|
||||
|
||||
char serial[CALYPSO_SERIAL_LEN * 2 + 1] = {0};
|
||||
calypso_hex_nospace(serial_data, serial_len, serial, sizeof(serial));
|
||||
written = snprintf(serials + pos, sizeof(serials) - pos, "%s", serial);
|
||||
written = snprintf(serials + pos, sizeof(serials) - pos, "%s", sprint_hex_inrow(serial_data, serial_len));
|
||||
if (written < 0 || (size_t)written >= sizeof(serials) - pos) {
|
||||
break;
|
||||
}
|
||||
@@ -1384,7 +1606,6 @@ static void calypso_dump_default_filename(const calypso_select_result_t *selecte
|
||||
return;
|
||||
}
|
||||
|
||||
char serial[CALYPSO_SERIAL_LEN * 2 + 1] = {0};
|
||||
const uint8_t *serial_data = selected->parsed.serial;
|
||||
size_t serial_len = CALYPSO_SERIAL_LEN;
|
||||
if (hce_filename) {
|
||||
@@ -1392,14 +1613,11 @@ static void calypso_dump_default_filename(const calypso_select_result_t *selecte
|
||||
serial_len -= CALYPSO_HCE_TOKEN_LEN;
|
||||
}
|
||||
|
||||
calypso_hex_nospace(serial_data, serial_len, serial, sizeof(serial));
|
||||
snprintf(filename, filename_len, "%s%s-dump", hce_filename ? "hf-calypso-hce-" : "hf-calypso-", serial);
|
||||
snprintf(filename, filename_len, "%s%s-dump", hce_filename ? "hf-calypso-hce-" : "hf-calypso-", sprint_hex_inrow(serial_data, serial_len));
|
||||
}
|
||||
|
||||
static void calypso_json_set_hex(json_t *obj, const char *key, const uint8_t *data, size_t data_len) {
|
||||
char hex[APDU_RES_LEN * 2 + 1] = {0};
|
||||
calypso_hex_nospace(data, data_len, hex, sizeof(hex));
|
||||
json_object_set_new(obj, key, json_string(hex));
|
||||
json_object_set_new(obj, key, json_string(sprint_hex_inrow(data, data_len)));
|
||||
}
|
||||
|
||||
static void calypso_json_set_sw(json_t *obj, const char *key, uint16_t sw) {
|
||||
@@ -1419,7 +1637,9 @@ static void calypso_json_add_select(json_t *root, const calypso_select_result_t
|
||||
json_object_set_new(root, "type", json_string("calypso"));
|
||||
calypso_json_set_sw(root, "selectStatus", selected->sw);
|
||||
calypso_json_set_hex(root, "selectAid", selected->requested_aid, selected->requested_aid_len);
|
||||
calypso_json_set_hex(root, "fci", selected->fci, selected->fci_len);
|
||||
if (selected->fci_len > 0) {
|
||||
calypso_json_set_hex(root, "fci", selected->fci, selected->fci_len);
|
||||
}
|
||||
if (selected->parsed.has_df_name) {
|
||||
calypso_json_set_hex(root, "fciDfName", selected->parsed.df_name, selected->parsed.df_name_len);
|
||||
}
|
||||
@@ -1761,19 +1981,21 @@ static int calypso_read_current_binary(uint8_t *out, size_t out_len, size_t *rea
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int calypso_select_file_element(uint16_t file_id, uint8_t *fci, size_t fci_len, size_t *read_len, uint16_t *sw) {
|
||||
static int calypso_select_file_element(uint16_t file_id, uint8_t *fcp, size_t fcp_len, size_t *read_len, uint16_t *sw) {
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
int res = calypso_select_file_id_with_p1_fallback(file_id, response, sizeof(response), &response_len, sw);
|
||||
|
||||
*read_len = MIN(response_len, fci_len);
|
||||
memcpy(fci, response, *read_len);
|
||||
*read_len = MIN(response_len, fcp_len);
|
||||
memcpy(fcp, response, *read_len);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int calypso_select_file_path(const calypso_file_ref_t *file, uint8_t *fci, size_t fci_len, size_t *read_len, uint16_t *sw) {
|
||||
uint16_t unselect_sw = 0;
|
||||
calypso_unselect_file(&unselect_sw);
|
||||
static int calypso_select_file_path(const calypso_file_ref_t *file, uint8_t *fcp, size_t fcp_len, size_t *read_len, uint16_t *sw) {
|
||||
uint8_t response[APDU_RES_LEN] = {0};
|
||||
size_t response_len = 0;
|
||||
uint16_t current_df_sw = 0;
|
||||
calypso_select_current_df_with_file_id_fallback(response, sizeof(response), &response_len, ¤t_df_sw);
|
||||
|
||||
size_t last_len = 0;
|
||||
uint16_t last_sw = 0;
|
||||
@@ -1781,7 +2003,7 @@ static int calypso_select_file_path(const calypso_file_ref_t *file, uint8_t *fci
|
||||
for (size_t i = 0; i < file->path_len; i++) {
|
||||
last_len = 0;
|
||||
last_sw = 0;
|
||||
res = calypso_select_file_element(file->path[i], fci, fci_len, &last_len, &last_sw);
|
||||
res = calypso_select_file_element(file->path[i], fcp, fcp_len, &last_len, &last_sw);
|
||||
if (res != PM3_SUCCESS || calypso_select_sw_has_file(last_sw) == false) {
|
||||
break;
|
||||
}
|
||||
@@ -1961,10 +2183,10 @@ static bool calypso_dump_sfi(uint8_t sfi, json_t *sfi_files, bool verbose, size_
|
||||
}
|
||||
|
||||
static bool calypso_dump_file_path(const calypso_file_ref_t *ref, uint8_t source, json_t *files, bool verbose, size_t *file_count, size_t *record_count, int *first_error) {
|
||||
uint8_t fci[APDU_RES_LEN] = {0};
|
||||
size_t fci_len = 0;
|
||||
uint8_t fcp[APDU_RES_LEN] = {0};
|
||||
size_t fcp_len = 0;
|
||||
uint16_t select_sw = 0;
|
||||
int res = calypso_select_file_path(ref, fci, sizeof(fci), &fci_len, &select_sw);
|
||||
int res = calypso_select_file_path(ref, fcp, sizeof(fcp), &fcp_len, &select_sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (first_error != NULL && *first_error == PM3_SUCCESS) {
|
||||
*first_error = res;
|
||||
@@ -1998,8 +2220,8 @@ static bool calypso_dump_file_path(const calypso_file_ref_t *ref, uint8_t source
|
||||
calypso_file_path_string(ref, path, sizeof(path));
|
||||
json_object_set_new(file, "name", json_string(ref->name));
|
||||
json_object_set_new(file, "path", json_string(path));
|
||||
if (fci_len > 0) {
|
||||
calypso_json_set_hex(file, "fci", fci, fci_len);
|
||||
if (fcp_len > 0) {
|
||||
calypso_json_set_hex(file, "fcp", fcp, fcp_len);
|
||||
}
|
||||
if (calypso_read_sw_has_data(binary_sw, binary_len) && binary_len > 0) {
|
||||
calypso_json_set_hex(file, "binary", binary, binary_len);
|
||||
@@ -2013,8 +2235,8 @@ static bool calypso_dump_file_path(const calypso_file_ref_t *ref, uint8_t source
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("%s") " (%s) (known) --------------------", ref->name, path);
|
||||
}
|
||||
if (fci_len > 0) {
|
||||
PrintAndLogEx(SUCCESS, " fci : " _YELLOW_("%s"), sprint_hex(fci, fci_len));
|
||||
if (fcp_len > 0) {
|
||||
PrintAndLogEx(SUCCESS, " fcp : " _YELLOW_("%s"), sprint_hex(fcp, fcp_len));
|
||||
}
|
||||
if (calypso_read_sw_has_data(binary_sw, binary_len) && binary_len > 0) {
|
||||
PrintAndLogEx(SUCCESS, " binary : " _GREEN_("%s"), sprint_hex(binary, binary_len));
|
||||
@@ -2245,12 +2467,27 @@ static void calypso_print_select_info(const calypso_select_result_t *selected, b
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Calypso Information") " ---------------------");
|
||||
calypso_print_hex_ascii_line(" SELECT AID : ", selected->requested_aid, selected->requested_aid_len);
|
||||
if (selected->requested_aid_len > 0) {
|
||||
calypso_print_hex_ascii_line(selected->default_selection ? " Default AID : " : " Selected AID : ", selected->requested_aid, selected->requested_aid_len);
|
||||
}
|
||||
if (selected->has_df_lid) {
|
||||
uint8_t lid[2] = {
|
||||
(uint8_t)(selected->df_lid >> 8),
|
||||
(uint8_t)(selected->df_lid & 0xFF)
|
||||
};
|
||||
PrintAndLogEx(SUCCESS, "%s" _GREEN_("%s"), selected->default_selection ? " Default DF LID : " : " DF LID : ", sprint_hex(lid, sizeof(lid)));
|
||||
}
|
||||
|
||||
if (selected->parsed.has_df_name) {
|
||||
calypso_print_hex_ascii_line(" FCI DF Name : ", selected->parsed.df_name, selected->parsed.df_name_len);
|
||||
if (selected->parsed.has_df_name && selected->default_selection == false) {
|
||||
calypso_print_hex_ascii_line(" DF Name : ", selected->parsed.df_name, selected->parsed.df_name_len);
|
||||
}
|
||||
calypso_print_aid_match_summary(aid_line_match);
|
||||
calypso_print_aid_attribution_details(&attribution, verbose);
|
||||
|
||||
if (calypso_selected_has_fci_info(selected) == false) {
|
||||
calypso_aid_attribution_free(&attribution);
|
||||
return;
|
||||
}
|
||||
|
||||
bool hce = calypso_serial_is_hce(selected->parsed.serial);
|
||||
PrintAndLogEx(SUCCESS, " Serial number : " _GREEN_("%s"), calypso_sprint_serial(selected->parsed.serial));
|
||||
@@ -2264,8 +2501,6 @@ static void calypso_print_select_info(const calypso_select_result_t *selected, b
|
||||
|
||||
calypso_print_startup(selected->parsed.startup);
|
||||
|
||||
calypso_print_aid_attribution_details(&attribution, verbose);
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("FCI") " -------------------------------------");
|
||||
@@ -2669,7 +2904,10 @@ static int CmdHFCalypsoInfo(const char *Cmd) {
|
||||
if (user_aid_len > 0) {
|
||||
res = calypso_select_aid(user_aid, (size_t)user_aid_len, verbose, &rf, &selected, &matched);
|
||||
} else {
|
||||
res = calypso_scan_aidlist(&rf, verbose, &selected, &matched);
|
||||
res = calypso_probe_current_df(&rf, verbose, &selected, &matched);
|
||||
if (res == PM3_SUCCESS && matched == false) {
|
||||
res = calypso_scan_aidlist(&rf, verbose, &selected, &matched);
|
||||
}
|
||||
}
|
||||
|
||||
if (res != PM3_SUCCESS) {
|
||||
|
||||
Reference in New Issue
Block a user