mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-14 10:36:58 -07:00
nested authentication works ok (tested)
and code cleaning
This commit is contained in:
parent
20f9a2a1d5
commit
4abe4f5867
4 changed files with 212 additions and 95 deletions
|
@ -1502,7 +1502,6 @@ int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, u
|
|||
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
|
||||
|
||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
|
||||
//uint8_t* uid = resp + 7;
|
||||
|
||||
uint8_t sak = 0x04; // cascade uid
|
||||
int cascade_level = 0;
|
||||
|
@ -1520,9 +1519,6 @@ int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, u
|
|||
if(resp_data)
|
||||
memcpy(resp_data->atqa, resp, 2);
|
||||
|
||||
//ReaderTransmit(sel_all,sizeof(sel_all)); --- avoid duplicate SELECT request
|
||||
//if(!ReaderReceive(uid)) return 0;
|
||||
|
||||
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||
|
@ -1778,17 +1774,17 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
ui64Key = bytes_to_num(datain, 6);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
byte_t dataoutbuf[16];
|
||||
byte_t isOK = 0;
|
||||
byte_t dataoutbuf[16];
|
||||
uint8_t uid[7];
|
||||
uint32_t cuid;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
// clear trace
|
||||
traceLen = 0;
|
||||
// tracing = false;
|
||||
traceLen = 0;
|
||||
// tracing = false;
|
||||
|
||||
iso14443a_setup();
|
||||
|
||||
|
@ -1802,7 +1798,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, 0)) {
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
@ -1831,14 +1827,14 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
uid[1] = 0xff;
|
||||
uid[2] = 0xff;
|
||||
uid[3] = 0xff;
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
|
||||
memcpy(ack.d.asBytes, dataoutbuf, 16);
|
||||
|
||||
LED_B_ON();
|
||||
UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
|
||||
LED_B_OFF();
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// Thats it...
|
||||
|
@ -1861,17 +1857,17 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
ui64Key = bytes_to_num(datain, 6);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
byte_t dataoutbuf[16 * 4];
|
||||
byte_t isOK = 0;
|
||||
byte_t dataoutbuf[16 * 4];
|
||||
uint8_t uid[8];
|
||||
uint32_t cuid;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
// clear trace
|
||||
traceLen = 0;
|
||||
// tracing = false;
|
||||
traceLen = 0;
|
||||
// tracing = false;
|
||||
|
||||
iso14443a_setup();
|
||||
|
||||
|
@ -1885,7 +1881,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, 0)) {
|
||||
if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {
|
||||
Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
@ -1926,7 +1922,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
uid[1] = 0xff;
|
||||
uid[2] = 0xff;
|
||||
uid[3] = 0xff;
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
|
||||
memcpy(ack.d.asBytes, dataoutbuf, 16 * 2);
|
||||
|
@ -1940,7 +1936,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
|
||||
LED_B_OFF();
|
||||
|
||||
// Thats it...
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// tracing = TRUE;
|
||||
|
@ -1953,25 +1949,25 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
//-----------------------------------------------------------------------------
|
||||
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
uint8_t keyType = arg1;
|
||||
uint64_t ui64Key = 0;
|
||||
byte_t blockdata[16];
|
||||
byte_t blockdata[16];
|
||||
|
||||
ui64Key = bytes_to_num(datain, 6);
|
||||
memcpy(blockdata, datain + 10, 16);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[8];
|
||||
uint32_t cuid;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
// clear trace
|
||||
traceLen = 0;
|
||||
traceLen = 0;
|
||||
// tracing = false;
|
||||
|
||||
iso14443a_setup();
|
||||
|
@ -1986,7 +1982,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, 0)) {
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
@ -2015,7 +2011,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
uid[1] = 0xff;
|
||||
uid[2] = 0xff;
|
||||
uid[3] = 0xff;
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
|
||||
|
||||
|
@ -2024,7 +2020,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
LED_B_OFF();
|
||||
|
||||
|
||||
// Thats it...
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// tracing = TRUE;
|
||||
|
@ -2037,7 +2033,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
//-----------------------------------------------------------------------------
|
||||
void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
{
|
||||
// params
|
||||
// params
|
||||
uint8_t blockNo = arg0;
|
||||
uint8_t keyType = arg1;
|
||||
uint64_t ui64Key = 0;
|
||||
|
@ -2045,16 +2041,16 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
ui64Key = bytes_to_num(datain, 6);
|
||||
|
||||
// variables
|
||||
byte_t isOK = 0;
|
||||
byte_t isOK = 0;
|
||||
uint8_t uid[8];
|
||||
uint32_t cuid;
|
||||
uint8_t dataoutbuf[16];
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
// clear trace
|
||||
traceLen = 0;
|
||||
traceLen = 0;
|
||||
// tracing = false;
|
||||
|
||||
iso14443a_setup();
|
||||
|
@ -2069,13 +2065,13 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
break;
|
||||
};
|
||||
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, 0)) {
|
||||
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
|
||||
Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
||||
// nested authenticate block = (blockNo + 1)
|
||||
if(mifare_classic_auth(pcs, (uint32_t)bytes_to_num(uid, 4), blockNo + 1, keyType, ui64Key, 1)) {
|
||||
if(mifare_classic_auth(pcs, (uint32_t)bytes_to_num(uid, 4), blockNo + 1, keyType, ui64Key, AUTH_NESTED)) {
|
||||
Dbprintf("Auth error");
|
||||
break;
|
||||
};
|
||||
|
@ -2097,14 +2093,14 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
// ----------------------------- crypto1 destroy
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
DbpString("NESTED FINISHED");
|
||||
DbpString("NESTED FINISHED");
|
||||
|
||||
// add trace trailer
|
||||
uid[0] = 0xff;
|
||||
uid[1] = 0xff;
|
||||
uid[2] = 0xff;
|
||||
uid[3] = 0xff;
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
LogTrace(uid, 4, 0, 0, TRUE);
|
||||
|
||||
UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
|
||||
memcpy(ack.d.asBytes, dataoutbuf, 16);
|
||||
|
@ -2113,7 +2109,7 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
|
||||
LED_B_OFF();
|
||||
|
||||
// Thats it...
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
// tracing = TRUE;
|
||||
|
|
|
@ -50,7 +50,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
|
|||
|
||||
int len = ReaderReceive(answer);
|
||||
|
||||
if (crypted) {
|
||||
if (crypted == CRYPT_ALL) {
|
||||
if (len == 1) {
|
||||
res = 0;
|
||||
for (pos = 0; pos < 4; pos++)
|
||||
|
@ -72,20 +72,20 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
|
|||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
int len;
|
||||
uint32_t pos;
|
||||
uint8_t tmp4[4];
|
||||
byte_t par = 0;
|
||||
byte_t ar[4];
|
||||
byte_t par = 0;
|
||||
byte_t ar[4];
|
||||
uint32_t nt, ntpp; // Supplied tag nonce
|
||||
|
||||
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
// Transmit MIFARE_CLASSIC_AUTH
|
||||
// Transmit MIFARE_CLASSIC_AUTH
|
||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer);
|
||||
// Dbprintf("rand nonce len: %x", len);
|
||||
if (len != 4) return 1;
|
||||
if (len != 4) return 1;
|
||||
|
||||
ar[0] = 0x55;
|
||||
ar[1] = 0x41;
|
||||
|
@ -94,50 +94,60 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
|
|||
|
||||
// Save the tag nonce (nt)
|
||||
nt = bytes_to_num(receivedAnswer, 4);
|
||||
Dbprintf("uid: %x nt: %x", uid, nt);
|
||||
|
||||
// ----------------------------- crypto1 create
|
||||
// Init cipher with key
|
||||
if (isNested)
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
// Init cipher with key
|
||||
crypto1_create(pcs, ui64Key);
|
||||
|
||||
// Load (plain) uid^nt into the cipher
|
||||
crypto1_word(pcs, nt ^ uid, 0);
|
||||
if (isNested == AUTH_NESTED) {
|
||||
// decrypt nt with help of new key
|
||||
nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt;
|
||||
} else {
|
||||
// Load (plain) uid^nt into the cipher
|
||||
crypto1_word(pcs, nt ^ uid, 0);
|
||||
}
|
||||
|
||||
// some statistic
|
||||
Dbprintf("auth uid: %08x nt: %08x", uid, nt);
|
||||
|
||||
par = 0;
|
||||
// Generate (encrypted) nr+parity by loading it into the cipher (Nr)
|
||||
for (pos = 0; pos < 4; pos++)
|
||||
{
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs, ar[pos], 0) ^ ar[pos];
|
||||
// Generate (encrypted) nr+parity by loading it into the cipher (Nr)
|
||||
for (pos = 0; pos < 4; pos++)
|
||||
{
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs, ar[pos], 0) ^ ar[pos];
|
||||
par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(ar[pos])) & 0x01) * 0x80 );
|
||||
}
|
||||
}
|
||||
|
||||
// Skip 32 bits in pseudo random generator
|
||||
nt = prng_successor(nt,32);
|
||||
// Skip 32 bits in pseudo random generator
|
||||
nt = prng_successor(nt,32);
|
||||
|
||||
// ar+parity
|
||||
for (pos = 4; pos < 8; pos++)
|
||||
{
|
||||
for (pos = 4; pos < 8; pos++)
|
||||
{
|
||||
nt = prng_successor(nt,8);
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
|
||||
par = (par >> 1)| ( ((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) * 0x80 );
|
||||
}
|
||||
}
|
||||
|
||||
// Transmit reader nonce and reader answer
|
||||
ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par);
|
||||
// Transmit reader nonce and reader answer
|
||||
ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par);
|
||||
|
||||
// Receive 4 bit answer
|
||||
// Receive 4 bit answer
|
||||
len = ReaderReceive(receivedAnswer);
|
||||
if (!len)
|
||||
{
|
||||
Dbprintf("Authentication failed. Card timeout.");
|
||||
if (!len)
|
||||
{
|
||||
Dbprintf("Authentication failed. Card timeout.");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(tmp4, receivedAnswer, 4);
|
||||
memcpy(tmp4, receivedAnswer, 4);
|
||||
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0);
|
||||
|
||||
if (ntpp != bytes_to_num(tmp4, 4)) {
|
||||
Dbprintf("Authentication failed. Error card response.");
|
||||
Dbprintf("Authentication failed. Error card response.");
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -147,12 +157,12 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
|
|||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
int len;
|
||||
uint8_t bt[2];
|
||||
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
// command MIFARE_CLASSIC_READBLOCK
|
||||
// command MIFARE_CLASSIC_READBLOCK
|
||||
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer);
|
||||
if (len == 1) {
|
||||
Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||
|
@ -164,7 +174,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
}
|
||||
|
||||
memcpy(bt, receivedAnswer + 16, 2);
|
||||
AppendCrc14443a(receivedAnswer, 16);
|
||||
AppendCrc14443a(receivedAnswer, 16);
|
||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||
Dbprintf("Cmd CRC response error.");
|
||||
return 3;
|
||||
|
@ -177,15 +187,15 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
|||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||
{
|
||||
// variables
|
||||
int len, i;
|
||||
int len, i;
|
||||
uint32_t pos;
|
||||
uint32_t par = 0;
|
||||
byte_t res;
|
||||
uint32_t par = 0;
|
||||
byte_t res;
|
||||
|
||||
uint8_t d_block[18], d_block_enc[18];
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer);
|
||||
|
||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||
|
@ -198,15 +208,15 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
|||
|
||||
// crypto
|
||||
par = 0;
|
||||
for (pos = 0; pos < 18; pos++)
|
||||
{
|
||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
||||
for (pos = 0; pos < 18; pos++)
|
||||
{
|
||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
||||
par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) * 0x20000 );
|
||||
}
|
||||
}
|
||||
|
||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par);
|
||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par);
|
||||
|
||||
// Receive the response
|
||||
// Receive the response
|
||||
len = ReaderReceive(receivedAnswer);
|
||||
|
||||
res = 0;
|
||||
|
@ -224,13 +234,13 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
|||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||
{
|
||||
// variables
|
||||
int len;
|
||||
int len;
|
||||
|
||||
// Mifare HALT
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
||||
|
||||
len = mifare_sendcmd_short(pcs, 1, 0x50, 0x00, receivedAnswer);
|
||||
if (len != 0) {
|
||||
if (len != 0) {
|
||||
Dbprintf("halt error. response len: %x", len);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
// code for work with mifare cards.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define CRYPT_NONE 0
|
||||
#define CRYPT_ALL 1
|
||||
#define CRYPT_REQUEST 2
|
||||
#define AUTH_FIRST 0
|
||||
#define AUTH_NESTED 2
|
||||
|
||||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \
|
||||
uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested);
|
||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue