mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 06:13:51 -07:00
chk works
This commit is contained in:
parent
882fa2334e
commit
db1780fbc1
1 changed files with 30 additions and 615 deletions
|
@ -85,8 +85,6 @@ typedef struct mfdes_authinput {
|
||||||
uint8_t kdfInput[31];
|
uint8_t kdfInput[31];
|
||||||
} PACKED mfdes_authinput_t;
|
} PACKED mfdes_authinput_t;
|
||||||
|
|
||||||
static mfdes_authinput_t currentauth[0xF] = {{.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}, {.keyno = -1}};
|
|
||||||
|
|
||||||
typedef struct mfdes_auth_res {
|
typedef struct mfdes_auth_res {
|
||||||
uint8_t sessionkeylen;
|
uint8_t sessionkeylen;
|
||||||
uint8_t sessionkey[24];
|
uint8_t sessionkey[24];
|
||||||
|
@ -261,137 +259,6 @@ static char *getVersionStr(uint8_t major, uint8_t minor) {
|
||||||
//04 01 01 01 00 1A 05
|
//04 01 01 01 00 1A 05
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) {
|
|
||||||
|
|
||||||
*result_len = 0;
|
|
||||||
if (sw) *sw = 0;
|
|
||||||
|
|
||||||
uint16_t isw = 0;
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
if (activate_field) {
|
|
||||||
DropFieldDesfire();
|
|
||||||
msleep(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
// select?
|
|
||||||
uint8_t data[APDU_RES_LEN] = {0};
|
|
||||||
|
|
||||||
// COMPUTE APDU
|
|
||||||
int datalen = 0;
|
|
||||||
//if (APDUEncodeS(&apdu, false, IncludeLe ? 0x100 : 0x00, data, &datalen)) {
|
|
||||||
if (APDUEncodeS(&apdu, false, 0x100, data, &datalen)) {
|
|
||||||
PrintAndLogEx(ERR, "APDU encoding error.");
|
|
||||||
return PM3_EAPDU_ENCODEFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetAPDULogging() || (g_debugMode > 1))
|
|
||||||
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen));
|
|
||||||
|
|
||||||
res = ExchangeAPDU14a(data, datalen, activate_field, leavefield_on, result, max_result_len, (int *)result_len);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (activate_field) {
|
|
||||||
PrintAndLogEx(DEBUG, "field up");
|
|
||||||
tag->rf_field_on = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetAPDULogging() || (g_debugMode > 1))
|
|
||||||
PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len));
|
|
||||||
|
|
||||||
if (*result_len < 2) {
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
*result_len -= 2;
|
|
||||||
isw = (result[*result_len] << 8) + result[*result_len + 1];
|
|
||||||
if (sw)
|
|
||||||
*sw = isw;
|
|
||||||
|
|
||||||
if (isw != 0x9000 && isw != status(MFDES_S_OPERATION_OK) && isw != status(MFDES_S_SIGNATURE) && isw != status(MFDES_S_ADDITIONAL_FRAME) && isw != status(MFDES_S_NO_CHANGES)) {
|
|
||||||
if (GetAPDULogging()) {
|
|
||||||
if (isw >> 8 == 0x61) {
|
|
||||||
PrintAndLogEx(ERR, "APDU chaining len: 0x%02x -->", isw & 0xff);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [0x%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(isw >> 8, isw & 0xff));
|
|
||||||
return PM3_EAPDU_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return PM3_EAPDU_FAIL;
|
|
||||||
}
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, uint32_t *recv_len, uint16_t *sw, uint32_t splitbysize, bool readalldata) {
|
|
||||||
if (apdu == NULL) {
|
|
||||||
PrintAndLogEx(DEBUG, "APDU=NULL");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
if (sw == NULL) {
|
|
||||||
PrintAndLogEx(DEBUG, "SW=NULL");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
if (recv_len == NULL) {
|
|
||||||
PrintAndLogEx(DEBUG, "RECV_LEN=NULL");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*sw = 0;
|
|
||||||
uint8_t data[255 * 5] = {0x00};
|
|
||||||
uint32_t resplen = 0;
|
|
||||||
uint32_t pos = 0;
|
|
||||||
uint32_t i = 1;
|
|
||||||
int res = DESFIRESendApdu(select, true, *apdu, data, sizeof(data), &resplen, sw);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(DEBUG, "%s", DesfireGetErrorString(res, sw));
|
|
||||||
DropFieldDesfire();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
if (dest != NULL) {
|
|
||||||
memcpy(dest, data, resplen);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += resplen;
|
|
||||||
if (!readalldata) {
|
|
||||||
if (*sw == status(MFDES_ADDITIONAL_FRAME)) {
|
|
||||||
*recv_len = pos;
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*sw == status(MFDES_ADDITIONAL_FRAME)) {
|
|
||||||
apdu->INS = MFDES_ADDITIONAL_FRAME; //0xAF
|
|
||||||
apdu->Lc = 0;
|
|
||||||
apdu->P1 = 0;
|
|
||||||
apdu->P2 = 0;
|
|
||||||
|
|
||||||
res = DESFIRESendApdu(false, true, *apdu, data, sizeof(data), &resplen, sw);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(DEBUG, "%s", DesfireGetErrorString(res, sw));
|
|
||||||
DropFieldDesfire();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dest != NULL) {
|
|
||||||
if (splitbysize) {
|
|
||||||
memcpy(&dest[i * splitbysize], data, resplen);
|
|
||||||
i += 1;
|
|
||||||
} else {
|
|
||||||
memcpy(&dest[pos], data, resplen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos += resplen;
|
|
||||||
|
|
||||||
if (*sw != status(MFDES_ADDITIONAL_FRAME)) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*recv_len = (splitbysize) ? i : pos;
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
||||||
|
|
||||||
if (major == 0x00)
|
if (major == 0x00)
|
||||||
|
@ -442,306 +309,6 @@ static int mfdes_get_info(mfdes_info_res_t *info) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload) {
|
|
||||||
// 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
|
|
||||||
// 4 different crypto arg1 DES, 3DES, 3K3DES, AES
|
|
||||||
// 3 different communication modes, PLAIN,MAC,CRYPTO
|
|
||||||
tag->authenticated_key_no = NOT_YET_AUTHENTICATED;
|
|
||||||
tag->session_key = NULL;
|
|
||||||
|
|
||||||
mbedtls_aes_context ctx;
|
|
||||||
|
|
||||||
uint8_t keybytes[24];
|
|
||||||
// Crypt constants
|
|
||||||
uint8_t IV[16] = {0x00};
|
|
||||||
uint8_t RndA[16] = {0x00};
|
|
||||||
uint8_t RndB[16] = {0x00};
|
|
||||||
uint8_t encRndB[16] = {0x00};
|
|
||||||
uint8_t rotRndB[16] = {0x00}; //RndB'
|
|
||||||
uint8_t both[32 + 1] = {0x00}; // ek/dk_keyNo(RndA+RndB')
|
|
||||||
|
|
||||||
// Generate Random Value
|
|
||||||
uint32_t ng = msclock();
|
|
||||||
uint32_t value = prng_successor(ng, 32);
|
|
||||||
num_to_bytes(value, 4, &RndA[0]);
|
|
||||||
value = prng_successor(ng, 32);
|
|
||||||
num_to_bytes(value, 4, &RndA[4]);
|
|
||||||
value = prng_successor(ng, 32);
|
|
||||||
num_to_bytes(value, 4, &RndA[8]);
|
|
||||||
value = prng_successor(ng, 32);
|
|
||||||
num_to_bytes(value, 4, &RndA[12]);
|
|
||||||
|
|
||||||
// Part 1
|
|
||||||
memcpy(keybytes, payload->key, payload->keylen);
|
|
||||||
|
|
||||||
struct desfire_key dkey = {0};
|
|
||||||
desfirekey_t key = &dkey;
|
|
||||||
|
|
||||||
if (payload->algo == MFDES_ALGO_AES) {
|
|
||||||
mbedtls_aes_init(&ctx);
|
|
||||||
Desfire_aes_key_new(keybytes, key);
|
|
||||||
} else if (payload->algo == MFDES_ALGO_3DES) {
|
|
||||||
Desfire_3des_key_new_with_version(keybytes, key);
|
|
||||||
} else if (payload->algo == MFDES_ALGO_DES) {
|
|
||||||
Desfire_des_key_new(keybytes, key);
|
|
||||||
} else if (payload->algo == MFDES_ALGO_3K3DES) {
|
|
||||||
Desfire_3k3des_key_new_with_version(keybytes, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload->kdfAlgo == MFDES_KDF_ALGO_AN10922) {
|
|
||||||
mifare_kdf_an10922(key, payload->kdfInput, payload->kdfInputLen);
|
|
||||||
PrintAndLogEx(DEBUG, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key)));
|
|
||||||
} else if (payload->kdfAlgo == MFDES_KDF_ALGO_GALLAGHER) {
|
|
||||||
// We will overrite any provided KDF input since a gallagher specific KDF was requested.
|
|
||||||
payload->kdfInputLen = 11;
|
|
||||||
|
|
||||||
if (mfdes_kdf_input_gallagher(tag->info.uid, tag->info.uidlen, payload->keyno, tag->selected_application, payload->kdfInput, &payload->kdfInputLen) != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(FAILED, "Could not generate Gallagher KDF input");
|
|
||||||
}
|
|
||||||
|
|
||||||
mifare_kdf_an10922(key, payload->kdfInput, payload->kdfInputLen);
|
|
||||||
PrintAndLogEx(DEBUG, " KDF Input: " _YELLOW_("%s"), sprint_hex(payload->kdfInput, payload->kdfInputLen));
|
|
||||||
PrintAndLogEx(DEBUG, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t subcommand = MFDES_AUTHENTICATE;
|
|
||||||
tag->authentication_scheme = AS_LEGACY;
|
|
||||||
|
|
||||||
if (payload->mode == MFDES_AUTH_AES) {
|
|
||||||
subcommand = MFDES_AUTHENTICATE_AES;
|
|
||||||
tag->authentication_scheme = AS_NEW;
|
|
||||||
} else if (payload->mode == MFDES_AUTH_ISO) {
|
|
||||||
subcommand = MFDES_AUTHENTICATE_ISO;
|
|
||||||
tag->authentication_scheme = AS_NEW;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t recv_len = 0;
|
|
||||||
uint16_t sw = 0;
|
|
||||||
uint8_t recv_data[256] = {0};
|
|
||||||
|
|
||||||
if (payload->mode != MFDES_AUTH_PICC) {
|
|
||||||
// Let's send our auth command
|
|
||||||
uint8_t data[] = {payload->keyno};
|
|
||||||
sAPDU apdu = {0x90, subcommand, 0x00, 0x00, 0x01, data};
|
|
||||||
int res = send_desfire_cmd(&apdu, false, recv_data, &recv_len, &sw, 0, false);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else {
|
|
||||||
/*
|
|
||||||
cmd[0] = AUTHENTICATE;
|
|
||||||
cmd[1] = payload->keyno;
|
|
||||||
len = DesfireAPDU(cmd, 2, resp);
|
|
||||||
*/
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (!recv_len) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sw != status(MFDES_ADDITIONAL_FRAME)) {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t expectedlen = 8;
|
|
||||||
if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3K3DES) {
|
|
||||||
expectedlen = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recv_len != expectedlen) {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
uint32_t rndlen = recv_len;
|
|
||||||
|
|
||||||
// Part 2
|
|
||||||
if (payload->mode != MFDES_AUTH_PICC) {
|
|
||||||
memcpy(encRndB, recv_data, rndlen);
|
|
||||||
} else {
|
|
||||||
memcpy(encRndB, recv_data + 2, rndlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Part 3
|
|
||||||
if (payload->algo == MFDES_ALGO_AES) {
|
|
||||||
if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndB, RndB);
|
|
||||||
} else if (payload->algo == MFDES_ALGO_DES)
|
|
||||||
des_decrypt(RndB, encRndB, key->data);
|
|
||||||
else if (payload->algo == MFDES_ALGO_3DES)
|
|
||||||
tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 2);
|
|
||||||
else if (payload->algo == MFDES_ALGO_3K3DES) {
|
|
||||||
tdes_nxp_receive(encRndB, RndB, rndlen, key->data, IV, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "encRndB: %s", sprint_hex(encRndB, 8));
|
|
||||||
PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
// - Rotate RndB by 8 bits
|
|
||||||
memcpy(rotRndB, RndB, rndlen);
|
|
||||||
rol(rotRndB, rndlen);
|
|
||||||
|
|
||||||
uint8_t encRndA[16] = {0x00};
|
|
||||||
|
|
||||||
// - Encrypt our response
|
|
||||||
if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) {
|
|
||||||
des_decrypt(encRndA, RndA, key->data);
|
|
||||||
memcpy(both, encRndA, rndlen);
|
|
||||||
|
|
||||||
for (uint32_t x = 0; x < rndlen; x++) {
|
|
||||||
rotRndB[x] = rotRndB[x] ^ encRndA[x];
|
|
||||||
}
|
|
||||||
|
|
||||||
des_decrypt(encRndB, rotRndB, key->data);
|
|
||||||
memcpy(both + rndlen, encRndB, rndlen);
|
|
||||||
} else if (payload->mode == MFDES_AUTH_ISO) {
|
|
||||||
if (payload->algo == MFDES_ALGO_3DES) {
|
|
||||||
uint8_t tmp[16] = {0x00};
|
|
||||||
memcpy(tmp, RndA, rndlen);
|
|
||||||
memcpy(tmp + rndlen, rotRndB, rndlen);
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen));
|
|
||||||
PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, 16));
|
|
||||||
}
|
|
||||||
tdes_nxp_send(tmp, both, 16, key->data, IV, 2);
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 16));
|
|
||||||
}
|
|
||||||
} else if (payload->algo == MFDES_ALGO_3K3DES) {
|
|
||||||
uint8_t tmp[32] = {0x00};
|
|
||||||
memcpy(tmp, RndA, rndlen);
|
|
||||||
memcpy(tmp + rndlen, rotRndB, rndlen);
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen));
|
|
||||||
PrintAndLogEx(DEBUG, "Both3k3: %s", sprint_hex(tmp, 32));
|
|
||||||
}
|
|
||||||
tdes_nxp_send(tmp, both, 32, key->data, IV, 3);
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (payload->mode == MFDES_AUTH_AES) {
|
|
||||||
uint8_t tmp[32] = {0x00};
|
|
||||||
memcpy(tmp, RndA, rndlen);
|
|
||||||
memcpy(tmp + rndlen, rotRndB, rndlen);
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen));
|
|
||||||
PrintAndLogEx(DEBUG, "Both3k3: %s", sprint_hex(tmp, 32));
|
|
||||||
}
|
|
||||||
if (payload->algo == MFDES_ALGO_AES) {
|
|
||||||
if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) {
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both);
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t bothlen = 16;
|
|
||||||
if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3K3DES) {
|
|
||||||
bothlen = 32;
|
|
||||||
}
|
|
||||||
if (payload->mode != MFDES_AUTH_PICC) {
|
|
||||||
sAPDU apdu = {0x90, MFDES_ADDITIONAL_FRAME, 0x00, 0x00, bothlen, both};
|
|
||||||
int res = send_desfire_cmd(&apdu, false, recv_data, &recv_len, &sw, 0, false);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*cmd[0] = ADDITIONAL_FRAME;
|
|
||||||
memcpy(cmd + 1, both, 16);
|
|
||||||
len = DesfireAPDU(cmd, 1 + 16, resp);
|
|
||||||
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(SUCCESS, "Sending auth command %02X " _RED_("failed"),subcommand);
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!recv_len) {
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload->mode != MFDES_AUTH_PICC) {
|
|
||||||
if (sw != status(MFDES_S_OPERATION_OK)) {
|
|
||||||
return 9;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*if (resp[1] != 0x00) {
|
|
||||||
PrintAndLogEx(ERR,"Authentication failed. Card timeout.");
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// Part 4
|
|
||||||
// tag->session_key = &default_key;
|
|
||||||
struct desfire_key *p = realloc(tag->session_key, sizeof(struct desfire_key));
|
|
||||||
if (!p) {
|
|
||||||
PrintAndLogEx(FAILED, "Cannot allocate memory for session keys");
|
|
||||||
free(tag->session_key);
|
|
||||||
return PM3_EMALLOC;
|
|
||||||
}
|
|
||||||
tag->session_key = p;
|
|
||||||
|
|
||||||
memset(tag->session_key, 0x00, sizeof(struct desfire_key));
|
|
||||||
|
|
||||||
Desfire_session_key_new(RndA, RndB, key, tag->session_key);
|
|
||||||
|
|
||||||
if (payload->mode != MFDES_AUTH_PICC) {
|
|
||||||
memcpy(encRndA, recv_data, rndlen);
|
|
||||||
} else {
|
|
||||||
memcpy(encRndA, recv_data + 2, rndlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_ISO || payload->mode == MFDES_AUTH_PICC) {
|
|
||||||
if (payload->algo == MFDES_ALGO_DES)
|
|
||||||
des_decrypt(encRndA, encRndA, key->data);
|
|
||||||
else if (payload->algo == MFDES_ALGO_3DES)
|
|
||||||
tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 2);
|
|
||||||
else if (payload->algo == MFDES_ALGO_3K3DES)
|
|
||||||
tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 3);
|
|
||||||
} else if (payload->mode == MFDES_AUTH_AES) {
|
|
||||||
if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, rndlen, IV, encRndA, encRndA);
|
|
||||||
}
|
|
||||||
|
|
||||||
rol(RndA, rndlen);
|
|
||||||
for (uint32_t x = 0; x < rndlen; x++) {
|
|
||||||
if (RndA[x] != encRndA[x]) {
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
PrintAndLogEx(DEBUG, "Expected_RndA : %s", sprint_hex(RndA, rndlen));
|
|
||||||
PrintAndLogEx(DEBUG, "Generated_RndA : %s", sprint_hex(encRndA, rndlen));
|
|
||||||
}
|
|
||||||
return 11;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the 3Des key first 8 bytes = 2nd 8 Bytes then we are really using Singe Des
|
|
||||||
// As such we need to set the session key such that the 2nd 8 bytes = 1st 8 Bytes
|
|
||||||
if (payload->algo == MFDES_ALGO_3DES) {
|
|
||||||
if (memcmp(key->data, &key->data[8], 8) == 0)
|
|
||||||
memcpy(&tag->session_key->data[8], tag->session_key->data, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
rpayload->sessionkeylen = payload->keylen;
|
|
||||||
memcpy(rpayload->sessionkey, tag->session_key->data, rpayload->sessionkeylen);
|
|
||||||
memset(tag->ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
|
|
||||||
tag->authenticated_key_no = payload->keyno;
|
|
||||||
|
|
||||||
if (tag->authentication_scheme == AS_NEW) {
|
|
||||||
cmac_generate_subkeys(tag->session_key, MCD_RECEIVE);
|
|
||||||
}
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t new_algo, uint8_t *old_key, uint8_t old_algo, uint8_t aes_version) {
|
/*static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t new_algo, uint8_t *old_key, uint8_t old_algo, uint8_t aes_version) {
|
||||||
|
|
||||||
if (new_key == NULL || old_key == NULL) {
|
if (new_key == NULL || old_key == NULL) {
|
||||||
|
@ -1034,54 +601,6 @@ static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signat
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handler_desfire_select_application(uint8_t *aid) {
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
if (aid == NULL) {
|
|
||||||
PrintAndLogEx(ERR, "AID=NULL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (aid == NULL) {
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a
|
|
||||||
uint32_t recv_len = 0;
|
|
||||||
uint16_t sw = 0;
|
|
||||||
|
|
||||||
int res = send_desfire_cmd(&apdu, !tag->rf_field_on, NULL, &recv_len, &sw, sizeof(dfname_t), true);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(WARNING,
|
|
||||||
_RED_(" Can't select AID 0x%X -> %s"),
|
|
||||||
(aid[2] << 16) + (aid[1] << 8) + aid[0],
|
|
||||||
DesfireGetErrorString(res, &sw)
|
|
||||||
);
|
|
||||||
DropFieldDesfire();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
memcpy(&tag->selected_application, aid, 3);
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handler_desfire_fileids(uint8_t *dest, uint32_t *file_ids_len) {
|
|
||||||
if (g_debugMode > 1) {
|
|
||||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
|
||||||
if (file_ids_len == NULL) PrintAndLogEx(ERR, "FILE_IDS_LEN=NULL");
|
|
||||||
}
|
|
||||||
if (dest == NULL || file_ids_len == NULL) return PM3_EINVARG;
|
|
||||||
sAPDU apdu = {0x90, MFDES_GET_FILE_IDS, 0x00, 0x00, 0x00, NULL}; //0x6f
|
|
||||||
uint32_t recv_len = 0;
|
|
||||||
uint16_t sw = 0;
|
|
||||||
*file_ids_len = 0;
|
|
||||||
int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0, true);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"), DesfireGetErrorString(res, &sw));
|
|
||||||
DropFieldDesfire();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
*file_ids_len = recv_len;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swap24(uint8_t *data) {
|
static void swap24(uint8_t *data) {
|
||||||
if (data == NULL) return;
|
if (data == NULL) return;
|
||||||
uint8_t tmp = data[0];
|
uint8_t tmp = data[0];
|
||||||
|
@ -1089,111 +608,6 @@ static void swap24(uint8_t *data) {
|
||||||
data[2] = tmp;
|
data[2] = tmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid, uint8_t *key, int cmdKeyNo, uint8_t cmdKdfAlgo, uint8_t kdfInputLen, uint8_t *kdfInput, mfdes_auth_res_t *rpayload) {
|
|
||||||
switch (cmdAuthMode) {
|
|
||||||
case MFDES_AUTH_DES:
|
|
||||||
if (cmdAuthAlgo != MFDES_ALGO_DES && cmdAuthAlgo != MFDES_ALGO_3DES) {
|
|
||||||
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth des mode");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MFDES_AUTH_ISO:
|
|
||||||
if (cmdAuthAlgo != MFDES_ALGO_3DES && cmdAuthAlgo != MFDES_ALGO_3K3DES) {
|
|
||||||
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth iso mode");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MFDES_AUTH_AES:
|
|
||||||
if (cmdAuthAlgo != MFDES_ALGO_AES) {
|
|
||||||
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth aes mode");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MFDES_AUTH_PICC:
|
|
||||||
if (cmdAuthAlgo != MFDES_AUTH_DES) {
|
|
||||||
PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth picc mode");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Wrong Auth mode (%d) -> (1=normal, 2=iso, 3=aes)", cmdAuthMode);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
int keylength = 16;
|
|
||||||
|
|
||||||
switch (cmdAuthAlgo) {
|
|
||||||
case MFDES_ALGO_3DES:
|
|
||||||
keylength = 16;
|
|
||||||
break;
|
|
||||||
case MFDES_ALGO_3K3DES:
|
|
||||||
keylength = 24;
|
|
||||||
break;
|
|
||||||
case MFDES_ALGO_AES:
|
|
||||||
keylength = 16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cmdAuthAlgo = MFDES_ALGO_DES;
|
|
||||||
keylength = 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cmdKdfAlgo) {
|
|
||||||
case MFDES_KDF_ALGO_AN10922:
|
|
||||||
// TODO: 2TDEA and 3TDEA keys use an input length of 1-15 bytes
|
|
||||||
if (cmdAuthAlgo != MFDES_ALGO_AES) {
|
|
||||||
PrintAndLogEx(FAILED, "Crypto algo not valid for the KDF AN10922 algo.");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
if (kdfInputLen < 1 || kdfInputLen > 31) {
|
|
||||||
PrintAndLogEx(FAILED, "KDF AN10922 algo requires an input of length 1-31 bytes.");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MFDES_KDF_ALGO_GALLAGHER:
|
|
||||||
// TODO: 2TDEA and 3TDEA keys use an input length of 1-15 bytes
|
|
||||||
if (cmdAuthAlgo != MFDES_ALGO_AES) {
|
|
||||||
PrintAndLogEx(FAILED, "Crypto algo not valid for the KDF AN10922 algo.");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
// KDF input arg is ignored as it'll be generated.
|
|
||||||
case MFDES_KDF_ALGO_NONE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "KDF algo %d is not supported.", cmdKdfAlgo);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// KEY
|
|
||||||
int res = handler_desfire_select_application(aid);
|
|
||||||
if (res != PM3_SUCCESS) return res;
|
|
||||||
|
|
||||||
if (memcmp(aid, "\x00\x00\x00", 3) != 0) {
|
|
||||||
uint8_t file_ids[33] = {0};
|
|
||||||
uint32_t file_ids_len = 0;
|
|
||||||
res = handler_desfire_fileids(file_ids, &file_ids_len);
|
|
||||||
if (res != PM3_SUCCESS) return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
mfdes_authinput_t payload;
|
|
||||||
payload.keylen = keylength;
|
|
||||||
memcpy(payload.key, key, keylength);
|
|
||||||
payload.mode = cmdAuthMode;
|
|
||||||
payload.algo = cmdAuthAlgo;
|
|
||||||
payload.keyno = cmdKeyNo;
|
|
||||||
payload.kdfAlgo = cmdKdfAlgo;
|
|
||||||
payload.kdfInputLen = kdfInputLen;
|
|
||||||
memcpy(payload.kdfInput, kdfInput, kdfInputLen);
|
|
||||||
|
|
||||||
int error = handler_desfire_auth(&payload, rpayload);
|
|
||||||
if (error == PM3_SUCCESS) {
|
|
||||||
memcpy(¤tauth[payload.keyno], &payload, sizeof(mfdes_authinput_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdHF14ADesInfo(const char *Cmd) {
|
static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes info",
|
CLIParserInit(&ctx, "hf mfdes info",
|
||||||
|
@ -1417,6 +831,7 @@ static void DesFill2bPattern(
|
||||||
}
|
}
|
||||||
|
|
||||||
static int AuthCheckDesfire(DesfireContext *dctx,
|
static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
|
DesfireSecureChannel secureChannel,
|
||||||
uint8_t *aid,
|
uint8_t *aid,
|
||||||
uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t deskeyListLen,
|
uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t deskeyListLen,
|
||||||
uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t aeskeyListLen,
|
uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t aeskeyListLen,
|
||||||
|
@ -1501,7 +916,6 @@ static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
int error;
|
|
||||||
bool badlen = false;
|
bool badlen = false;
|
||||||
|
|
||||||
if (des) {
|
if (des) {
|
||||||
|
@ -1510,18 +924,18 @@ static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
|
|
||||||
if (usedkeys[keyno] == 1 && foundKeys[0][keyno][0] == 0) {
|
if (usedkeys[keyno] == 1 && foundKeys[0][keyno][0] == 0) {
|
||||||
for (uint32_t curkey = 0; curkey < deskeyListLen; curkey++) {
|
for (uint32_t curkey = 0; curkey < deskeyListLen; curkey++) {
|
||||||
mfdes_auth_res_t rpayload;
|
DesfireSetKeyNoClear(dctx, keyno, T_DES, deskeyList[curkey]);
|
||||||
error = desfire_authenticate(MFDES_AUTH_DES, MFDES_ALGO_DES, aid, deskeyList[curkey], keyno, 0, 0, NULL, &rpayload);
|
res = DesfireAuthenticate(dctx, secureChannel, false);
|
||||||
if (error == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8));
|
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8));
|
||||||
foundKeys[0][keyno][0] = 0x01;
|
foundKeys[0][keyno][0] = 0x01;
|
||||||
*result = true;
|
*result = true;
|
||||||
memcpy(&foundKeys[0][keyno][1], deskeyList[curkey], 8);
|
memcpy(&foundKeys[0][keyno][1], deskeyList[curkey], 8);
|
||||||
break;
|
break;
|
||||||
} else if (error < 7) {
|
} else if (res < 7) {
|
||||||
badlen = true;
|
badlen = true;
|
||||||
DropFieldDesfire();
|
DropField();
|
||||||
res = handler_desfire_select_application(aid);
|
res = DesfireSelectAIDHex(dctx, curaid, false, 0);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1542,18 +956,18 @@ static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
|
|
||||||
if (usedkeys[keyno] == 1 && foundKeys[1][keyno][0] == 0) {
|
if (usedkeys[keyno] == 1 && foundKeys[1][keyno][0] == 0) {
|
||||||
for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
|
for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
|
||||||
mfdes_auth_res_t rpayload;
|
DesfireSetKeyNoClear(dctx, keyno, T_3DES, deskeyList[curkey]);
|
||||||
error = desfire_authenticate(MFDES_AUTH_DES, MFDES_ALGO_3DES, aid, aeskeyList[curkey], keyno, 0, 0, NULL, &rpayload);
|
res = DesfireAuthenticate(dctx, secureChannel, false);
|
||||||
if (error == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3DES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
|
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 2TDEA Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
|
||||||
foundKeys[1][keyno][0] = 0x01;
|
foundKeys[1][keyno][0] = 0x01;
|
||||||
*result = true;
|
*result = true;
|
||||||
memcpy(&foundKeys[1][keyno][1], aeskeyList[curkey], 16);
|
memcpy(&foundKeys[1][keyno][1], aeskeyList[curkey], 16);
|
||||||
break;
|
break;
|
||||||
} else if (error < 7) {
|
} else if (res < 7) {
|
||||||
badlen = true;
|
badlen = true;
|
||||||
DropFieldDesfire();
|
DropField();
|
||||||
res = handler_desfire_select_application(aid);
|
res = DesfireSelectAIDHex(dctx, curaid, false, 0);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1574,18 +988,18 @@ static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
|
|
||||||
if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) {
|
if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) {
|
||||||
for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
|
for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
|
||||||
mfdes_auth_res_t rpayload;
|
DesfireSetKeyNoClear(dctx, keyno, T_AES, deskeyList[curkey]);
|
||||||
error = desfire_authenticate(MFDES_AUTH_AES, MFDES_ALGO_AES, aid, aeskeyList[curkey], keyno, cmdKdfAlgo, kdfInputLen, kdfInput, &rpayload);
|
res = DesfireAuthenticate(dctx, secureChannel, false);
|
||||||
if (error == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
|
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
|
||||||
foundKeys[2][keyno][0] = 0x01;
|
foundKeys[2][keyno][0] = 0x01;
|
||||||
*result = true;
|
*result = true;
|
||||||
memcpy(&foundKeys[2][keyno][1], aeskeyList[curkey], 16);
|
memcpy(&foundKeys[2][keyno][1], aeskeyList[curkey], 16);
|
||||||
break;
|
break;
|
||||||
} else if (error < 7) {
|
} else if (res < 7) {
|
||||||
badlen = true;
|
badlen = true;
|
||||||
DropFieldDesfire();
|
DropField();
|
||||||
res = handler_desfire_select_application(aid);
|
res = DesfireSelectAIDHex(dctx, curaid, false, 0);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1606,18 +1020,18 @@ static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
|
|
||||||
if (usedkeys[keyno] == 1 && foundKeys[3][keyno][0] == 0) {
|
if (usedkeys[keyno] == 1 && foundKeys[3][keyno][0] == 0) {
|
||||||
for (uint32_t curkey = 0; curkey < k3kkeyListLen; curkey++) {
|
for (uint32_t curkey = 0; curkey < k3kkeyListLen; curkey++) {
|
||||||
mfdes_auth_res_t rpayload;
|
DesfireSetKeyNoClear(dctx, keyno, T_3K3DES, deskeyList[curkey]);
|
||||||
error = desfire_authenticate(MFDES_AUTH_ISO, MFDES_ALGO_3K3DES, aid, k3kkeyList[curkey], keyno, 0, 0, NULL, &rpayload);
|
res = DesfireAuthenticate(dctx, secureChannel, false);
|
||||||
if (error == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3K3 Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(k3kkeyList[curkey], 24));
|
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3TDEA Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(k3kkeyList[curkey], 24));
|
||||||
foundKeys[3][keyno][0] = 0x01;
|
foundKeys[3][keyno][0] = 0x01;
|
||||||
*result = true;
|
*result = true;
|
||||||
memcpy(&foundKeys[3][keyno][1], k3kkeyList[curkey], 16);
|
memcpy(&foundKeys[3][keyno][1], k3kkeyList[curkey], 16);
|
||||||
break;
|
break;
|
||||||
} else if (error < 7) {
|
} else if (res < 7) {
|
||||||
badlen = true;
|
badlen = true;
|
||||||
DropFieldDesfire();
|
DropField();
|
||||||
res = handler_desfire_select_application(aid);
|
res = DesfireSelectAIDHex(dctx, curaid, false, 0);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1631,7 +1045,7 @@ static int AuthCheckDesfire(DesfireContext *dctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DropFieldDesfire();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1826,6 +1240,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
DesfireSetKdf(&dctx, cmdKDFAlgo, kdfInput, kdfInputLen);
|
DesfireSetKdf(&dctx, cmdKDFAlgo, kdfInput, kdfInputLen);
|
||||||
DesfireSetCommandSet(&dctx, DCCNativeISO);
|
DesfireSetCommandSet(&dctx, DCCNativeISO);
|
||||||
DesfireSetCommMode(&dctx, DCMPlain);
|
DesfireSetCommMode(&dctx, DCMPlain);
|
||||||
|
DesfireSecureChannel secureChannel = DACEV1;
|
||||||
|
|
||||||
// save card UID to dctx
|
// save card UID to dctx
|
||||||
DesfireGetCardUID(&dctx);
|
DesfireGetCardUID(&dctx);
|
||||||
|
@ -1855,7 +1270,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
|
uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
|
||||||
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
|
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
|
||||||
|
|
||||||
res = AuthCheckDesfire(&dctx, &app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, cmdKDFAlgo, kdfInputLen, kdfInput, foundKeys, &result, (verbose == false));
|
res = AuthCheckDesfire(&dctx, secureChannel, &app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, cmdKDFAlgo, kdfInputLen, kdfInput, foundKeys, &result, (verbose == false));
|
||||||
if (res == PM3_EOPABORTED) {
|
if (res == PM3_EOPABORTED) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue