mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge pull request #664 from bkerler/mfdes_test
HF MFDES updates. New aid create, aid delete and format card command. Auth fixed. Improved logging.
This commit is contained in:
commit
652bf0c94b
7 changed files with 891 additions and 228 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Updates `hf mfdes` functions, improved logging and added new commands (@bkerler)
|
||||
- Updated 'legic.lua' and 'legic_clone.lua' script - works with current command set (@Pizza_4u)
|
||||
- Rewrote `hf mfdes` functions and added apdu debugging (@bkerler)
|
||||
- Add Mifare Desfire GetDFNames and improve HF MFDES Enum output (@bkerler)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "util.h"
|
||||
#include "mifare.h"
|
||||
#include "ticks.h"
|
||||
|
||||
#define MAX_APPLICATION_COUNT 28
|
||||
#define MAX_FILE_COUNT 16
|
||||
|
@ -103,7 +104,7 @@ void MifareDesfireGetInformation() {
|
|||
uint8_t versionSW[7];
|
||||
uint8_t details[14];
|
||||
} PACKED payload;
|
||||
|
||||
|
||||
/*
|
||||
1 = PCB 1
|
||||
2 = cid 2
|
||||
|
@ -137,7 +138,7 @@ void MifareDesfireGetInformation() {
|
|||
memcpy(payload.uid, card.uid, sizeof(payload.uid));
|
||||
|
||||
LED_A_ON();
|
||||
uint8_t cmd[] = {GET_VERSION, 0x00, 0x00, 0x00};
|
||||
uint8_t cmd[] = {0x90, GET_VERSION, 0x00, 0x00, 0x00};
|
||||
size_t cmd_len = sizeof(cmd);
|
||||
|
||||
len = DesfireAPDU(cmd, cmd_len, resp);
|
||||
|
@ -152,7 +153,7 @@ void MifareDesfireGetInformation() {
|
|||
memcpy(payload.versionHW, resp + 1, sizeof(payload.versionHW));
|
||||
|
||||
// ADDITION_FRAME 1
|
||||
cmd[0] = ADDITIONAL_FRAME;
|
||||
cmd[1] = ADDITIONAL_FRAME;
|
||||
len = DesfireAPDU(cmd, cmd_len, resp);
|
||||
if (!len) {
|
||||
print_result("ERROR <--: ", resp, len);
|
||||
|
@ -178,7 +179,7 @@ void MifareDesfireGetInformation() {
|
|||
LED_B_ON();
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// reset the pcb_blocknum,
|
||||
pcb_blocknum = 0;
|
||||
OnSuccess();
|
||||
|
@ -246,9 +247,15 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
else if (arg1 == 1)
|
||||
Desfire_des_key_new(keybytes, key);
|
||||
|
||||
cmd[0] = AUTHENTICATE;
|
||||
cmd[1] = arg2; //keynumber
|
||||
len = DesfireAPDU(cmd, 2, resp);
|
||||
cmd[0] = 0x90;
|
||||
cmd[1] = AUTHENTICATE;
|
||||
cmd[2] = 0x0;
|
||||
cmd[3] = 0x0;
|
||||
cmd[4] = 0x1;
|
||||
cmd[5] = arg2; //keynumber
|
||||
cmd[6] = 0x0;
|
||||
len = DesfireAPDU(cmd, 7, resp);
|
||||
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -257,14 +264,13 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
return;
|
||||
}
|
||||
|
||||
if (resp[2] == 0xaf) {
|
||||
} else {
|
||||
if (resp[2] == (uint8_t)0xaf) {
|
||||
DbpString("Authentication failed. Invalid key number.");
|
||||
OnError(3);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(encRndB, resp + 3, 8);
|
||||
memcpy(encRndB, resp + 1, 8);
|
||||
if (arg1 == 2)
|
||||
tdes_dec(&decRndB, &encRndB, key->data);
|
||||
else if (arg1 == 1)
|
||||
|
@ -275,6 +281,11 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
// This should be random
|
||||
uint8_t decRndA[8] = {0x00};
|
||||
uint32_t value = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(value, 4, &decRndA[0]);
|
||||
value = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(value, 4, &decRndA[4]);
|
||||
|
||||
memcpy(RndA, decRndA, 8);
|
||||
uint8_t encRndA[8] = {0x00};
|
||||
|
||||
|
@ -297,10 +308,14 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
memcpy(both + 8, encRndB, 8);
|
||||
|
||||
cmd[0] = ADDITIONAL_FRAME;
|
||||
memcpy(cmd + 1, both, 16);
|
||||
|
||||
len = DesfireAPDU(cmd, 17, resp);
|
||||
cmd[0] = 0x90;
|
||||
cmd[1] = ADDITIONAL_FRAME;
|
||||
cmd[2] = 0x00;
|
||||
cmd[3] = 0x00;
|
||||
cmd[4] = 0x10;
|
||||
memcpy(cmd + 5, both, 16);
|
||||
cmd[16 + 5] = 0x0;
|
||||
len = DesfireAPDU(cmd, 5 + 16 + 1, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -309,14 +324,14 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
return;
|
||||
}
|
||||
|
||||
if (resp[2] == 0x00) {
|
||||
if (resp[len - 3] == 0x00) {
|
||||
|
||||
struct desfire_key sessionKey = {0};
|
||||
desfirekey_t skey = &sessionKey;
|
||||
Desfire_session_key_new(RndA, RndB, key, skey);
|
||||
//print_result("SESSION : ", skey->data, 8);
|
||||
|
||||
memcpy(encRndA, resp + 3, 8);
|
||||
memcpy(encRndA, resp + 1, 8);
|
||||
|
||||
if (arg1 == 2)
|
||||
tdes_dec(&encRndA, &encRndA, key->data);
|
||||
|
@ -326,19 +341,20 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
rol(decRndA, 8);
|
||||
for (int x = 0; x < 8; x++) {
|
||||
if (decRndA[x] != encRndA[x]) {
|
||||
DbpString("Authentication failed. Cannot varify PICC.");
|
||||
DbpString("Authentication failed. Cannot verify PICC.");
|
||||
OnError(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Change the selected key to a new value.
|
||||
/*
|
||||
|
||||
/*
|
||||
// Current key is a 3DES key, change it to a DES key
|
||||
if (arg1 == 2) {
|
||||
cmd[0] = CHANGE_KEY;
|
||||
cmd[1] = arg2;
|
||||
cmd[0] = 0x90;
|
||||
cmd[1] = CHANGE_KEY;
|
||||
cmd[2] = arg2;
|
||||
|
||||
uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
|
||||
|
||||
|
@ -367,20 +383,21 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
buff3[x] = buff3[x] ^ buff2[x];
|
||||
}
|
||||
tdes_dec(&buff3, &buff3, skey->data);
|
||||
memcpy(cmd+18,buff3,8);
|
||||
memcpy(cmd+19,buff3,8);
|
||||
|
||||
// The command always times out on the first attempt, this will retry until a response
|
||||
// is recieved.
|
||||
len = 0;
|
||||
while(!len) {
|
||||
len = DesfireAPDU(cmd,26,resp);
|
||||
len = DesfireAPDU(cmd,27,resp);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Current key is a DES key, change it to a 3DES key
|
||||
if (arg1 == 1) {
|
||||
cmd[0] = CHANGE_KEY;
|
||||
cmd[1] = arg2;
|
||||
cmd[0] = 0x90;
|
||||
cmd[1] = CHANGE_KEY;
|
||||
cmd[2] = arg2;
|
||||
|
||||
uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
|
||||
|
||||
|
@ -397,31 +414,31 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
memcpy(buff3 + 1, &second, 1);
|
||||
|
||||
des_dec(&buff1, &buff1, skey->data);
|
||||
memcpy(cmd+2,buff1,8);
|
||||
memcpy(cmd+3,buff1,8);
|
||||
|
||||
for (int x = 0; x < 8; x++) {
|
||||
buff2[x] = buff2[x] ^ buff1[x];
|
||||
}
|
||||
des_dec(&buff2, &buff2, skey->data);
|
||||
memcpy(cmd+10,buff2,8);
|
||||
memcpy(cmd+11,buff2,8);
|
||||
|
||||
for (int x = 0; x < 8; x++) {
|
||||
buff3[x] = buff3[x] ^ buff2[x];
|
||||
}
|
||||
des_dec(&buff3, &buff3, skey->data);
|
||||
memcpy(cmd+18,buff3,8);
|
||||
memcpy(cmd+19,buff3,8);
|
||||
|
||||
// The command always times out on the first attempt, this will retry until a response
|
||||
// is recieved.
|
||||
len = 0;
|
||||
while(!len) {
|
||||
len = DesfireAPDU(cmd,26,resp);
|
||||
len = DesfireAPDU(cmd,27,resp);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
OnSuccess();
|
||||
//OnSuccess();
|
||||
if (arg1 == 2)
|
||||
reply_old(CMD_ACK, 1, 0, 0, skey->data, 16);
|
||||
else if (arg1 == 1)
|
||||
|
@ -433,11 +450,139 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case 2: {
|
||||
//SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp);
|
||||
break;
|
||||
case 3: {
|
||||
uint8_t keybytes[16];
|
||||
uint8_t RndA[8] = {0x00};
|
||||
uint8_t RndB[8] = {0x00};
|
||||
|
||||
if (arg1 == 2) {
|
||||
if (datain[1] == 0xff) {
|
||||
memcpy(keybytes, PICC_MASTER_KEY16, 16);
|
||||
} else {
|
||||
memcpy(keybytes, datain + 1, datalen);
|
||||
}
|
||||
} else {
|
||||
if (arg1 == 1) {
|
||||
if (datain[1] == 0xff) {
|
||||
uint8_t null_key_data8[8] = {0x00};
|
||||
memcpy(keybytes, null_key_data8, 8);
|
||||
} else {
|
||||
memcpy(keybytes, datain + 1, datalen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct desfire_key defaultkey = {0};
|
||||
desfirekey_t key = &defaultkey;
|
||||
|
||||
if (arg1 == 2)
|
||||
Desfire_3des_key_new_with_version(keybytes, key);
|
||||
else if (arg1 == 1)
|
||||
Desfire_des_key_new(keybytes, key);
|
||||
|
||||
cmd[0] = AUTHENTICATE;
|
||||
cmd[1] = arg2; //keynumber
|
||||
len = DesfireAPDU(cmd, 2, resp);
|
||||
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
}
|
||||
OnError(3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp[2] == (uint8_t)0xaf) {
|
||||
DbpString("Authentication failed. Invalid key number.");
|
||||
OnError(3);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(encRndB, resp + 2, 8);
|
||||
if (arg1 == 2)
|
||||
tdes_dec(&decRndB, &encRndB, key->data);
|
||||
else if (arg1 == 1)
|
||||
des_dec(&decRndB, &encRndB, key->data);
|
||||
|
||||
memcpy(RndB, decRndB, 8);
|
||||
rol(decRndB, 8);
|
||||
|
||||
// This should be random
|
||||
uint8_t decRndA[8] = {0x00};
|
||||
uint32_t value = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(value, 4, &decRndA[0]);
|
||||
value = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(value, 4, &decRndA[4]);
|
||||
|
||||
memcpy(RndA, decRndA, 8);
|
||||
uint8_t encRndA[8] = {0x00};
|
||||
|
||||
if (arg1 == 2)
|
||||
tdes_dec(&encRndA, &decRndA, key->data);
|
||||
else if (arg1 == 1)
|
||||
des_dec(&encRndA, &decRndA, key->data);
|
||||
|
||||
memcpy(both, encRndA, 8);
|
||||
|
||||
for (int x = 0; x < 8; x++) {
|
||||
decRndB[x] = decRndB[x] ^ encRndA[x];
|
||||
|
||||
}
|
||||
|
||||
if (arg1 == 2)
|
||||
tdes_dec(&encRndB, &decRndB, key->data);
|
||||
else if (arg1 == 1)
|
||||
des_dec(&encRndB, &decRndB, key->data);
|
||||
|
||||
memcpy(both + 8, encRndB, 8);
|
||||
|
||||
cmd[0] = ADDITIONAL_FRAME;
|
||||
memcpy(cmd + 1, both, 16);
|
||||
len = DesfireAPDU(cmd, 1 + 16, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
}
|
||||
OnError(3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp[1] == 0x00) {
|
||||
struct desfire_key sessionKey = {0};
|
||||
desfirekey_t skey = &sessionKey;
|
||||
Desfire_session_key_new(RndA, RndB, key, skey);
|
||||
//print_result("SESSION : ", skey->data, 8);
|
||||
|
||||
memcpy(encRndA, resp + 2, 8);
|
||||
|
||||
if (arg1 == 2)
|
||||
tdes_dec(&encRndA, &encRndA, key->data);
|
||||
else if (arg1 == 1)
|
||||
des_dec(&encRndA, &encRndA, key->data);
|
||||
|
||||
rol(decRndA, 8);
|
||||
for (int x = 0; x < 8; x++) {
|
||||
if (decRndA[x] != encRndA[x]) {
|
||||
DbpString("Authentication failed. Cannot verify PICC.");
|
||||
OnError(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//OnSuccess();
|
||||
if (arg1 == 2)
|
||||
reply_old(CMD_ACK, 1, 0, 0, skey->data, 16);
|
||||
else if (arg1 == 1)
|
||||
reply_old(CMD_ACK, 1, 0, 0, skey->data, 8);
|
||||
} else {
|
||||
DbpString("Authentication failed.");
|
||||
OnError(6);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: {
|
||||
//defaultkey
|
||||
uint8_t keybytes[16] = {0x00};
|
||||
if (datain[1] == 0xff) {
|
||||
|
@ -454,13 +599,14 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
uint8_t IV[16] = {0x00};
|
||||
mbedtls_aes_init(&ctx);
|
||||
|
||||
cmd[0] = AUTHENTICATE_AES;
|
||||
cmd[1] = 0x0;
|
||||
cmd[0] = 0x90;
|
||||
cmd[1] = AUTHENTICATE_AES;
|
||||
cmd[2] = 0x0;
|
||||
cmd[3] = 0x1;
|
||||
cmd[4] = arg2; //keynumber
|
||||
cmd[5] = 0x0;
|
||||
len = DesfireAPDU(cmd, 6, resp);
|
||||
cmd[3] = 0x0;
|
||||
cmd[4] = 0x1;
|
||||
cmd[5] = arg2; //keynumber
|
||||
cmd[6] = 0x0;
|
||||
len = DesfireAPDU(cmd, 7, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -482,6 +628,14 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, decRndB);
|
||||
rol(decRndB, 16);
|
||||
uint8_t nonce[16] = {0x00};
|
||||
uint32_t val = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(val, 4, &nonce[0]);
|
||||
val = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(val, 4, &nonce[4]);
|
||||
val = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(val, 4, &nonce[8]);
|
||||
val = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(val, 4, &nonce[12]);
|
||||
memcpy(both, nonce, 16);
|
||||
memcpy(both + 16, decRndB, 16);
|
||||
uint8_t encBoth[32] = {0x00};
|
||||
|
@ -494,14 +648,15 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
}
|
||||
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, both, encBoth);
|
||||
|
||||
cmd[0] = ADDITIONAL_FRAME;
|
||||
cmd[1] = 0x00;
|
||||
cmd[0] = 0x90;
|
||||
cmd[1] = ADDITIONAL_FRAME;
|
||||
cmd[2] = 0x00;
|
||||
cmd[3] = 0x20;
|
||||
memcpy(cmd + 4, encBoth, 32);
|
||||
cmd[36]=0x0;
|
||||
cmd[3] = 0x00;
|
||||
cmd[4] = 0x20;
|
||||
memcpy(cmd + 5, encBoth, 32);
|
||||
cmd[32 + 5] = 0x0;
|
||||
|
||||
len = DesfireAPDU(cmd, 37, resp); // 4 + 32 + 1 == 37
|
||||
len = DesfireAPDU(cmd, 5 + 32 + 1, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -510,7 +665,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((resp[1+16] == 0x91)&&(resp[1+16+1] == 0x00)) {
|
||||
if ((resp[1 + 16] == 0x91) && (resp[1 + 16 + 1] == 0x00)) {
|
||||
// Create AES Session key
|
||||
struct desfire_key sessionKey = {0};
|
||||
desfirekey_t skey = &sessionKey;
|
||||
|
@ -526,7 +681,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
}
|
||||
}
|
||||
|
||||
OnSuccess();
|
||||
//OnSuccess();
|
||||
reply_mix(CMD_ACK, 1, len, 0, resp, len);
|
||||
}
|
||||
|
||||
|
@ -557,10 +712,10 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) {
|
|||
// if we received an I- or R(ACK)-Block with a block number equal to the
|
||||
// current block number, toggle the current block number
|
||||
if (len >= 4 // PCB+CID+CRC = 4 bytes
|
||||
&& ((resp[0] & 0xC0) == 0 // I-Block
|
||||
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
|
||||
pcb_blocknum ^= 1; //toggle next block
|
||||
&& ((resp[0] & 0xC0) == 0 // I-Block
|
||||
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
|
||||
pcb_blocknum ^= 1; //toggle next block
|
||||
}
|
||||
|
||||
memcpy(dataout, resp, len);
|
||||
|
@ -570,7 +725,7 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) {
|
|||
// CreateAPDU
|
||||
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
|
||||
|
||||
size_t cmdlen = MIN(len + 4, PM3_CMD_DATA_SIZE - 1);
|
||||
size_t cmdlen = MIN(len + 3, PM3_CMD_DATA_SIZE - 1);
|
||||
|
||||
uint8_t cmd[cmdlen];
|
||||
memset(cmd, 0, cmdlen);
|
||||
|
@ -578,18 +733,18 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
|
|||
cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid.
|
||||
cmd[0] |= pcb_blocknum; // OR the block number into the PCB
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0] );
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0]);
|
||||
|
||||
cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards
|
||||
//cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards
|
||||
|
||||
memcpy(cmd + 2, datain, len);
|
||||
AddCrc14A(cmd, len + 2);
|
||||
|
||||
/*
|
||||
hf 14a apdu -sk 90 60 00 00 00
|
||||
hf 14a apdu -k 90 AF 00 00 00
|
||||
hf 14a apdu 90AF000000
|
||||
*/
|
||||
memcpy(cmd + 1, datain, len);
|
||||
AddCrc14A(cmd, len + 1);
|
||||
|
||||
/*
|
||||
hf 14a apdu -sk 90 60 00 00 00
|
||||
hf 14a apdu -k 90 AF 00 00 00
|
||||
hf 14a apdu 90AF000000
|
||||
*/
|
||||
memcpy(dataout, cmd, cmdlen);
|
||||
return cmdlen;
|
||||
}
|
||||
|
|
|
@ -697,7 +697,7 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData) {
|
|||
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData) {
|
||||
|
||||
int len;
|
||||
uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME};
|
||||
uint8_t data[17] = {MFDES_ADDITIONAL_FRAME};
|
||||
memcpy(data + 1, key, 16);
|
||||
|
||||
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
|
||||
|
|
|
@ -675,7 +675,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
|
||||
// it's basically a ISO14443a tag, so try annotation from there
|
||||
if (applyIso14443a(exp, size, cmd, cmdsize) == 0) {
|
||||
|
||||
|
||||
// S-block 11xxx010
|
||||
if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
|
||||
switch ((cmd[0] & 0x30)) {
|
||||
|
@ -707,9 +707,9 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
|
||||
if ((cmd[0] & 0x04) == 0x04) // nad byte following
|
||||
pos++;
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++, pos++) {
|
||||
|
||||
|
||||
switch (cmd[pos]) {
|
||||
case MFDES_CREATE_APPLICATION:
|
||||
snprintf(exp, size, "CREATE APPLICATION");
|
||||
|
@ -819,7 +819,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
case MFDES_GET_KEY_VERSION:
|
||||
snprintf(exp, size, "GET KEY VERSION");
|
||||
break;
|
||||
case MFDES_AUTHENTICATION_FRAME:
|
||||
case MFDES_ADDITIONAL_FRAME:
|
||||
snprintf(exp, size, "AUTH FRAME / NEXT FRAME");
|
||||
break;
|
||||
default:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ int CmdHFMFDes(const char *Cmd);
|
|||
char *getCardSizeStr(uint8_t fsize);
|
||||
char *getProtocolStr(uint8_t id);
|
||||
char *getVersionStr(uint8_t major, uint8_t minor);
|
||||
void getKeySettings(uint8_t *aid);
|
||||
int getKeySettings(uint8_t *aid);
|
||||
|
||||
// Ev1 card limits
|
||||
#define MAX_NUM_KEYS 0x0F
|
||||
|
@ -28,55 +28,6 @@ void getKeySettings(uint8_t *aid);
|
|||
|
||||
#define NOT_YET_AUTHENTICATED 0xFF
|
||||
|
||||
// status- and error codes |
|
||||
#define OPERATION_OK 0x00 // Successful operation
|
||||
#define NO_CHANGES 0x0C // No changes done to backup files
|
||||
// ,CommitTransaction/
|
||||
// AbortTransaction not necessary
|
||||
#define OUT_OF_EEPROM_ERROR 0x0E // Insufficient NV-Memory to
|
||||
// complete command
|
||||
#define ILLEGAL_COMMAND_CODE 0x1C // Command code not supported
|
||||
#define INTEGRITY_ERROR 0x1E // CRC or MAC does not match data
|
||||
// Padding bytes not valid
|
||||
#define NO_SUCH_KEY 0x40 // Invalid key number specified
|
||||
#define LENGTH_ERROR 0x7E // Length of command string invalid
|
||||
#define PERMISSION_DENIED 0x9D // Current configuration status
|
||||
// does not allow the requested
|
||||
// command
|
||||
#define PARAMETER_ERROR 0x9E // Value of the parameter(s) inval.
|
||||
#define APPLICATION_NOT_FOUND 0xA0 // Requested AID not present on PIC
|
||||
#define APPL_INTEGRITY_ERROR 0xA1 // [1] // Unrecoverable error within app-
|
||||
// lication, app will be disabled
|
||||
#define AUTHENTICATION_ERROR 0xAE // Current authentication status
|
||||
// does not allow the requested
|
||||
// command
|
||||
#define ADDITIONAL_FRAME 0xAF // Additional data frame is
|
||||
// expected to be sent
|
||||
#define BOUNDARY_ERROR 0xBE // Attempt to read/write data from/
|
||||
// to beyond the file's/record's
|
||||
// limits. Attempt to exceed the
|
||||
// limits of a value file.
|
||||
#define PICC_INTEGRITY_ERROR 0xC1 // [1] // Unrecoverable error within PICC
|
||||
// ,PICC will be disabled
|
||||
#define COMMAND_ABORTED 0xCA // Previous Command was not fully
|
||||
// completed Not all Frames were
|
||||
// requested or provided by PCD
|
||||
#define PICC_DISABLED_ERROR 0xCD // [1] // PICC was disabled by an unrecoverable error
|
||||
#define COUNT_ERROR 0xCE // Number of Applications limited
|
||||
// to 28, no additional
|
||||
// CreateApplication possible
|
||||
#define DUPLICATE_ERROR 0xDE // Creation of file/application
|
||||
// failed because file/application
|
||||
// with same number already exists
|
||||
#define EEPROM_ERROR 0xEE // [1] // Could not complete NV-write
|
||||
// operation due to loss of power,
|
||||
// internal backup/rollback
|
||||
// mechanism activated
|
||||
#define FILE_NOT_FOUND_ERROR 0xF0 // Specified file number does not
|
||||
// exist
|
||||
#define FILE_INTEGRITY_ERROR 0xF1 // [1] // Unrecoverable error within file,
|
||||
// file will be disabled
|
||||
//
|
||||
// [1] These errors are not expected to appear during normal operation
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -350,21 +350,18 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
|
||||
// MIFARE DESFire command set:
|
||||
|
||||
|
||||
#define MFDES_GET_VERSION 0x60
|
||||
|
||||
#define MFDES_AUTHENTICATE 0x0A // AUTHENTICATE_NATIVE
|
||||
#define MFDES_AUTHENTICATE_ISO 0x1A // AUTHENTICATE_STANDARD
|
||||
#define MFDES_AUTHENTICATE_AES 0xAA
|
||||
|
||||
#define MFDES_CREATE_APPLICATION 0xCA
|
||||
#define MFDES_DELETE_APPLICATION 0xDA
|
||||
#define MFDES_CREDIT 0x0C
|
||||
#define MFDES_LIMITED_CREDIT 0x1C
|
||||
#define MFDES_DEBIT 0xDC
|
||||
|
||||
#define MFDES_WRITE_RECORD 0x3B
|
||||
#define MFDES_READSIG 0x3C
|
||||
#define MFDES_WRITE_DATA 0x3D
|
||||
|
||||
#define MFDES_GET_KEY_SETTINGS 0x45
|
||||
#define MFDES_CHANGE_KEY_SETTINGS 0x54
|
||||
#define MFDES_SELECT_APPLICATION 0x5A
|
||||
|
@ -376,18 +373,36 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define MFDES_GET_FREE_MEMORY 0x6E
|
||||
#define MFDES_GET_DF_NAMES 0x6D
|
||||
#define MFDES_GET_FILE_IDS 0x6F
|
||||
|
||||
|
||||
#define MFDES_ABORT_TRANSACTION 0xA7
|
||||
#define MFDES_AUTHENTICATION_FRAME 0xAF
|
||||
#define MFDES_ADDITIONAL_FRAME 0xAF
|
||||
#define MFDES_ADDITIONAL_FRAME_RESP 0x91AF
|
||||
#define MFDES_SUCCESS_FRAME_RESP 0x9100
|
||||
#define MFDES_EAUTH_RESP 0x91AE
|
||||
#define MFDES_ENO_SUCH_KEY_RESP 0x9140
|
||||
|
||||
#define MFDES_READ_RECORDS 0xBB
|
||||
#define MFDES_READ_DATA 0xBD
|
||||
#define MFDES_ABORT_TRANSACTION 0xA7
|
||||
|
||||
// MIFARE DESFire status set:
|
||||
|
||||
#define MFDES_OPERATION_OK 0x00
|
||||
#define MFDES_NO_CHANGES 0x0C
|
||||
#define MFDES_ADDITIONAL_FRAME 0xAF
|
||||
#define MFDES_E_OUT_OF_EEPROM 0x0E
|
||||
#define MFDES_E_ILLEGAL_COMMAND_CODE 0x1C
|
||||
#define MFDES_E_INTEGRITY_ERROR 0x1E
|
||||
#define MFDES_E_NO_SUCH_KEY 0x40
|
||||
#define MFDES_E_LENGTH 0x7E
|
||||
#define MFDES_E_PERMISSION_DENIED 0x9D
|
||||
#define MFDES_E_PARAMETER_ERROR 0x9E
|
||||
#define MFDES_E_APPLICATION_NOT_FOUND 0xA0
|
||||
#define MFDES_E_APPL_INTEGRITY 0xA1
|
||||
#define MFDES_E_AUTHENTIFICATION_ERROR 0xAE
|
||||
#define MFDES_E_BOUNDARY 0xBE
|
||||
#define MFDES_E_PICC_INTEGRITY 0xC1
|
||||
#define MFDES_E_COMMAND_ABORTED 0xCA
|
||||
#define MFDES_E_PICC_DISABLED 0xCD
|
||||
#define MFDES_E_COUNT 0xCE
|
||||
#define MFDES_E_DUPLICATE 0xDE
|
||||
#define MFDES_E_EEPROM 0xEE
|
||||
#define MFDES_E_FILE_NOT_FOUND 0xF0
|
||||
#define MFDES_E_FILE_INTEGRITY 0xF1
|
||||
#define MFDES_SIGNATURE 0x90
|
||||
|
||||
|
||||
#define MFDES_CREATE_CYCLIC_RECORD_FILE 0xC0
|
||||
#define MFDES_CREATE_LINEAR_RECORD_FILE 0xC1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue