Merge branch 'master' into cmds

This commit is contained in:
Oleg Moiseenko 2017-10-19 12:24:28 +03:00 committed by GitHub
commit 3f10c215a1
16 changed files with 540 additions and 341 deletions

View file

@ -10,6 +10,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Deleted wipe functionality from `hf mf csetuid` (Merlok) - Deleted wipe functionality from `hf mf csetuid` (Merlok)
- Changed `hf mf nested` logic (Merlok) - Changed `hf mf nested` logic (Merlok)
- Added `hf mf nested` mode: autosearch keys for attack (from well known keys) (Merlok) - Added `hf mf nested` mode: autosearch keys for attack (from well known keys) (Merlok)
- `hf mf nested` Check keys after they have found (Merlok)
- `hf mf chk` Move main cycle to arm (Merlok)
- Changed proxmark command line parameter `flush` to `-f` or `-flush` (Merlok) - Changed proxmark command line parameter `flush` to `-f` or `-flush` (Merlok)
### Fixed ### Fixed
@ -25,6 +27,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `hf mf cwipe` command. It wipes "magic Chinese" card. For 1a generation it uses card's "wipe" command. For gen1a and gen1b it uses a write command. (Merlok) - Added `hf mf cwipe` command. It wipes "magic Chinese" card. For 1a generation it uses card's "wipe" command. For gen1a and gen1b it uses a write command. (Merlok)
- Added to `hf mf nested` source key check before attack (Merlok) - Added to `hf mf nested` source key check before attack (Merlok)
- Added to `hf mf nested` after attack it checks all found keys on non-open sectors (Merlok) - Added to `hf mf nested` after attack it checks all found keys on non-open sectors (Merlok)
- `hf mf chk` Added setings to set iso14443a operations timeout. default timeout set to 500us (Merlok)
- Added to `hf mf nested` parameters `s` and `ss` for checking slow cards (Merlok)
- Added to proxmark command line parameters `w` - wait 20s for serial port (Merlok) - Added to proxmark command line parameters `w` - wait 20s for serial port (Merlok)
- Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (Merlok) - Added to proxmark command line parameters `c` and `l` - execute command and lua script from command line (Merlok)
- Added to proxmark ability to execute commands from stdin (pipe) (Merlok) - Added to proxmark ability to execute commands from stdin (pipe) (Merlok)

View file

@ -127,7 +127,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);

View file

@ -29,4 +29,5 @@ extern void iso14443a_setup(uint8_t fpga_minor_mode);
extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data);
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
extern void iso14a_set_trigger(bool enable); extern void iso14a_set_trigger(bool enable);
extern void iso14a_set_timeout(uint32_t timeout);
#endif /* __ISO14443A_H */ #endif /* __ISO14443A_H */

View file

@ -7,7 +7,7 @@
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Routines to support ISO 14443 type A. // Routines to support ISO 14443 type B.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __ISO14443B_H #ifndef __ISO14443B_H

View file

@ -20,10 +20,6 @@
#include "parity.h" #include "parity.h"
#include "crc.h" #include "crc.h"
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// the block number for the ISO14443-4 PCB // the block number for the ISO14443-4 PCB
static uint8_t pcb_blocknum = 0; static uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed // Deselect card by sending a s-block. the crc is precalced for speed
@ -961,24 +957,14 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
// MIFARE check keys. key count up to 85. // MIFARE check keys. key count up to 85.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
{ {
uint8_t blockNo = arg0 & 0xff; uint8_t blockNo = arg0 & 0xff;
uint8_t keyType = (arg0 >> 8) & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff;
bool clearTrace = arg1; bool clearTrace = arg1 & 0x01;
bool multisectorCheck = arg1 & 0x02;
uint8_t set14aTimeout = (arg1 >> 8) & 0xff;
uint8_t keyCount = arg2; uint8_t keyCount = arg2;
uint64_t ui64Key = 0;
bool have_uid = false;
uint8_t cascade_levels = 0;
uint32_t timeout = 0;
int i;
byte_t isOK = 0;
uint8_t uid[10];
uint32_t cuid;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
// clear debug level // clear debug level
int OLD_MF_DBGLEVEL = MF_DBGLEVEL; int OLD_MF_DBGLEVEL = MF_DBGLEVEL;
@ -992,52 +978,33 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
if (clearTrace) clear_trace(); if (clearTrace) clear_trace();
set_tracing(true); set_tracing(true);
for (i = 0; i < keyCount; i++) { if (set14aTimeout){
// if(mifare_classic_halt(pcs, cuid)) { iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe
// if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error");
// }
// Iceman: use piwi's faster nonce collecting part in hardnested.
if (!have_uid) { // need a full select cycle to get the uid first
iso14a_card_select_t card_info;
if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card");
--i; // try same key once again
continue;
}
switch (card_info.uidlen) {
case 4 : cascade_levels = 1; break;
case 7 : cascade_levels = 2; break;
case 10: cascade_levels = 3; break;
default: break;
}
have_uid = true;
} else { // no need for anticollision. We can directly select the card
if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {
if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)");
--i; // try same key once again
continue;
}
}
ui64Key = bytes_to_num(datain + i * 6, 6);
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL);
timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
// wait for the card to become ready again
while(GetCountSspClk() < timeout);
continue;
}
isOK = 1;
break;
} }
LED_B_ON(); if (multisectorCheck) {
cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6); TKeyIndex keyIndex = {{0}};
LED_B_OFF(); uint8_t sectorCnt = blockNo;
int res = MifareMultisectorChk(datain, keyCount, sectorCnt, keyType, OLD_MF_DBGLEVEL, &keyIndex);
LED_B_ON();
if (res >= 0) {
cmd_send(CMD_ACK, 1, 0, 0, keyIndex, 80);
} else {
cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
}
LED_B_OFF();
} else {
int res = MifareChkBlockKeys(datain, keyCount, blockNo, keyType, OLD_MF_DBGLEVEL);
LED_B_ON();
if (res > 0) {
cmd_send(CMD_ACK, 1, 0, 0, datain + (res - 1) * 6, 6);
} else {
cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
}
LED_B_OFF();
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();

View file

@ -764,3 +764,125 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
} }
return 1; return 1;
} }
//-----------------------------------------------------------------------------
// MIFARE check keys
//
//-----------------------------------------------------------------------------
// one key check
int MifareChkBlockKey(uint8_t *uid, uint32_t *cuid, uint8_t *cascade_levels, uint64_t ui64Key, uint8_t blockNo, uint8_t keyType, uint8_t debugLevel) {
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
// Iceman: use piwi's faster nonce collecting part in hardnested.
if (*cascade_levels == 0) { // need a full select cycle to get the uid first
iso14a_card_select_t card_info;
if(!iso14443a_select_card(uid, &card_info, cuid, true, 0, true)) {
if (debugLevel >= 1) Dbprintf("ChkKeys: Can't select card");
return 1;
}
switch (card_info.uidlen) {
case 4 : *cascade_levels = 1; break;
case 7 : *cascade_levels = 2; break;
case 10: *cascade_levels = 3; break;
default: break;
}
} else { // no need for anticollision. We can directly select the card
if(!iso14443a_select_card(uid, NULL, NULL, false, *cascade_levels, true)) {
if (debugLevel >= 1) Dbprintf("ChkKeys: Can't select card (UID) lvl=%d", *cascade_levels);
return 1;
}
}
if(mifare_classic_auth(pcs, *cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
// SpinDelayUs(AUTHENTICATION_TIMEOUT); // it not needs because mifare_classic_auth have timeout from iso14a_set_timeout()
return 2;
} else {
/* // let it be here. it like halt command, but maybe it will work in some strange cases
uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL);
int timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
// wait for the card to become ready again
while(GetCountSspClk() < timeout) {};
*/
// it needs after success authentication
mifare_classic_halt(pcs, *cuid);
}
return 0;
}
// multi key check
int MifareChkBlockKeys(uint8_t *keys, uint8_t keyCount, uint8_t blockNo, uint8_t keyType, uint8_t debugLevel) {
uint8_t uid[10];
uint32_t cuid = 0;
uint8_t cascade_levels = 0;
uint64_t ui64Key = 0;
int retryCount = 0;
for (uint8_t i = 0; i < keyCount; i++) {
// Allow button press / usb cmd to interrupt device
if (BUTTON_PRESS() && !usb_poll_validate_length()) {
Dbprintf("ChkKeys: Cancel operation. Exit...");
return -2;
}
ui64Key = bytes_to_num(keys + i * 6, 6);
int res = MifareChkBlockKey(uid, &cuid, &cascade_levels, ui64Key, blockNo, keyType, debugLevel);
// can't select
if (res == 1) {
retryCount++;
if (retryCount >= 5) {
Dbprintf("ChkKeys: block=%d key=%d. Can't select. Exit...", blockNo, keyType);
return -1;
}
--i; // try the same key once again
SpinDelay(20);
// Dbprintf("ChkKeys: block=%d key=%d. Try the same key once again...", blockNo, keyType);
continue;
}
// can't authenticate
if (res == 2) {
retryCount = 0;
continue; // can't auth. wrong key.
}
return i + 1;
}
return 0;
}
// multisector multikey check
int MifareMultisectorChk(uint8_t *keys, uint8_t keyCount, uint8_t SectorCount, uint8_t keyType, uint8_t debugLevel, TKeyIndex *keyIndex) {
int res = 0;
// int clk = GetCountSspClk();
for(int sc = 0; sc < SectorCount; sc++){
WDT_HIT();
int keyAB = keyType;
do {
res = MifareChkBlockKeys(keys, keyCount, FirstBlockOfSector(sc), keyAB & 0x01, debugLevel);
if (res < 0){
return res;
}
if (res > 0){
(*keyIndex)[keyAB & 0x01][sc] = res;
}
} while(--keyAB > 0);
}
// Dbprintf("%d %d", GetCountSspClk() - clk, (GetCountSspClk() - clk)/(SectorCount*keyCount*(keyType==2?2:1)));
return 0;
}

View file

@ -13,6 +13,7 @@
#define __MIFAREUTIL_H #define __MIFAREUTIL_H
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "usb_cdc.h"
// mifare authentication // mifare authentication
#define CRYPT_NONE 0 #define CRYPT_NONE 0
@ -20,6 +21,8 @@
#define CRYPT_REQUEST 2 #define CRYPT_REQUEST 2
#define AUTH_FIRST 0 #define AUTH_FIRST 0
#define AUTH_NESTED 2 #define AUTH_NESTED 2
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// mifare 4bit card answers // mifare 4bit card answers
#define CARD_ACK 0x0A // 1010 - ACK #define CARD_ACK 0x0A // 1010 - ACK
@ -99,4 +102,10 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
int emlCheckValBl(int blockNum); int emlCheckValBl(int blockNum);
// mifare check keys
typedef uint8_t TKeyIndex[2][40];
int MifareChkBlockKey(uint8_t *uid, uint32_t *cuid, uint8_t *cascade_levels, uint64_t ui64Key, uint8_t blockNo, uint8_t keyType, uint8_t debugLevel);
int MifareChkBlockKeys(uint8_t *keys, uint8_t keyCount, uint8_t blockNo, uint8_t keyType, uint8_t debugLevel);
int MifareMultisectorChk(uint8_t *keys, uint8_t keyCount, uint8_t SectorCount, uint8_t keyType, uint8_t debugLevel, TKeyIndex *keyIndex);
#endif #endif

View file

@ -546,7 +546,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) { if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", PrintAndLog(" %10d | %10d | %s | fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp), (EndOfTransmissionTimestamp - first_timestamp),
(next_timestamp - first_timestamp), (next_timestamp - first_timestamp),
" ", " ",

View file

@ -524,14 +524,35 @@ int CmdHF14AMfRestore(const char *Cmd)
return 0; return 0;
} }
//----------------------------------------------
typedef struct { // Nested
uint64_t Key[2]; //----------------------------------------------
int foundKey[2];
} sector_t;
# define NESTED_KEY_COUNT 15 # define NESTED_KEY_COUNT 15
static void parseParamTDS(const char *Cmd, const uint8_t indx, bool *paramT, bool *paramD, uint8_t *timeout) {
char ctmp3[3] = {0};
int len = param_getlength(Cmd, indx);
if (len > 0 && len < 4){
param_getstr(Cmd, indx, ctmp3);
*paramT |= (ctmp3[0] == 't' || ctmp3[0] == 'T');
*paramD |= (ctmp3[0] == 'd' || ctmp3[0] == 'D');
bool paramS1 = *paramT || *paramD;
// slow and very slow
if (ctmp3[0] == 's' || ctmp3[0] == 'S' || ctmp3[1] == 's' || ctmp3[1] == 'S') {
*timeout = 11; // slow
if (!paramS1 && (ctmp3[1] == 's' || ctmp3[1] == 'S')) {
*timeout = 53; // very slow
}
if (paramS1 && (ctmp3[2] == 's' || ctmp3[2] == 'S')) {
*timeout = 53; // very slow
}
}
}
}
int CmdHF14AMfNested(const char *Cmd) int CmdHF14AMfNested(const char *Cmd)
{ {
int i, j, res, iterations; int i, j, res, iterations;
@ -544,6 +565,8 @@ int CmdHF14AMfNested(const char *Cmd)
uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t keyBlock[NESTED_KEY_COUNT * 6]; uint8_t keyBlock[NESTED_KEY_COUNT * 6];
uint64_t key64 = 0; uint64_t key64 = 0;
// timeout in units. (ms * 106)/10 or us*0.0106
uint8_t btimeout14a = MF_CHKKEYS_DEFTIMEOUT; // fast by default
bool autosearchKey = false; bool autosearchKey = false;
@ -557,20 +580,23 @@ int CmdHF14AMfNested(const char *Cmd)
if (strlen(Cmd)<3) { if (strlen(Cmd)<3) {
PrintAndLog("Usage:"); PrintAndLog("Usage:");
PrintAndLog(" all sectors: hf mf nested <card memory> <block number> <key A/B> <key (12 hex symbols)> [t,d]"); PrintAndLog(" all sectors: hf mf nested <card memory> <block number> <key A/B> <key (12 hex symbols)> [t|d|s|ss]");
PrintAndLog(" all sectors autosearch key: hf mf nested <card memory> * [t,d]"); PrintAndLog(" all sectors autosearch key: hf mf nested <card memory> * [t|d|s|ss]");
PrintAndLog(" one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)>"); PrintAndLog(" one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)>");
PrintAndLog(" <target block number> <target key A/B> [t]"); PrintAndLog(" <target block number> <target key A/B> [t]");
PrintAndLog(" "); PrintAndLog(" ");
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K"); PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
PrintAndLog("t - transfer keys to emulator memory"); PrintAndLog("t - transfer keys to emulator memory");
PrintAndLog("d - write keys to binary file dumpkeys.bin"); PrintAndLog("d - write keys to binary file dumpkeys.bin");
PrintAndLog("s - Slow (1ms) check keys (required by some non standard cards)");
PrintAndLog("ss - Very slow (5ms) check keys");
PrintAndLog(" "); PrintAndLog(" ");
PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF "); PrintAndLog(" sample1: hf mf nested 1 0 A FFFFFFFFFFFF ");
PrintAndLog(" sample2: hf mf nested 1 0 A FFFFFFFFFFFF t "); PrintAndLog(" sample2: hf mf nested 1 0 A FFFFFFFFFFFF t ");
PrintAndLog(" sample3: hf mf nested 1 0 A FFFFFFFFFFFF d "); PrintAndLog(" sample3: hf mf nested 1 0 A FFFFFFFFFFFF d ");
PrintAndLog(" sample4: hf mf nested o 0 A FFFFFFFFFFFF 4 A"); PrintAndLog(" sample4: hf mf nested o 0 A FFFFFFFFFFFF 4 A");
PrintAndLog(" sample5: hf mf nested 1 * t"); PrintAndLog(" sample5: hf mf nested 1 * t");
PrintAndLog(" sample6: hf mf nested 1 * ss");
return 0; return 0;
} }
@ -587,11 +613,10 @@ int CmdHF14AMfNested(const char *Cmd)
if (param_getchar(Cmd, 1) == '*') { if (param_getchar(Cmd, 1) == '*') {
autosearchKey = true; autosearchKey = true;
ctmp = param_getchar(Cmd, 2); parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a);
transferToEml |= (ctmp == 't' || ctmp == 'T');
createDumpFile |= (ctmp == 'd' || ctmp == 'D');
PrintAndLog("--nested. sectors:%2d, block no:*, eml:%c, dmp=%c ", SectorsCnt, transferToEml?'y':'n', createDumpFile?'y':'n'); PrintAndLog("--nested. sectors:%2d, block no:*, eml:%c, dmp=%c checktimeout=%d us",
SectorsCnt, transferToEml?'y':'n', createDumpFile?'y':'n', ((int)btimeout14a * 10000) / 106);
} else { } else {
blockNo = param_get8(Cmd, 1); blockNo = param_get8(Cmd, 1);
@ -628,16 +653,13 @@ int CmdHF14AMfNested(const char *Cmd)
if (ctmp != 'A' && ctmp != 'a') if (ctmp != 'A' && ctmp != 'a')
trgKeyType = 1; trgKeyType = 1;
ctmp = param_getchar(Cmd, 6); parseParamTDS(Cmd, 6, &transferToEml, &createDumpFile, &btimeout14a);
transferToEml |= (ctmp == 't' || ctmp == 'T');
createDumpFile |= (ctmp == 'd' || ctmp == 'D');
} else { } else {
ctmp = param_getchar(Cmd, 4); parseParamTDS(Cmd, 4, &transferToEml, &createDumpFile, &btimeout14a);
transferToEml |= (ctmp == 't' || ctmp == 'T');
createDumpFile |= (ctmp == 'd' || ctmp == 'D');
} }
PrintAndLog("--nested. sectors:%2d, block no:%3d, key type:%c, eml:%c, dmp=%c ", SectorsCnt, blockNo, keyType?'B':'A', transferToEml?'y':'n', createDumpFile?'y':'n'); PrintAndLog("--nested. sectors:%2d, block no:%3d, key type:%c, eml:%c, dmp=%c checktimeout=%d us",
SectorsCnt, blockNo, keyType?'B':'A', transferToEml?'y':'n', createDumpFile?'y':'n', ((int)btimeout14a * 10000) / 106);
} }
// one-sector nested // one-sector nested
@ -686,35 +708,12 @@ int CmdHF14AMfNested(const char *Cmd)
if (e_sector == NULL) return 1; if (e_sector == NULL) return 1;
//test current key and additional standard keys first //test current key and additional standard keys first
memcpy(keyBlock, key, 6); for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){
num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 1 * 6)); num_to_bytes(MifareDefaultKeys[defaultKeyCounter], 6, (uint8_t*)(keyBlock + defaultKeyCounter * 6));
num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 2 * 6)); }
num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6));
num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6));
num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6));
num_to_bytes(0x4d3a99c351dd, 6, (uint8_t*)(keyBlock + 6 * 6));
num_to_bytes(0x1a982c7e459a, 6, (uint8_t*)(keyBlock + 7 * 6));
num_to_bytes(0xd3f7d3f7d3f7, 6, (uint8_t*)(keyBlock + 8 * 6));
num_to_bytes(0x714c5c886e97, 6, (uint8_t*)(keyBlock + 9 * 6));
num_to_bytes(0x587ee5f9350f, 6, (uint8_t*)(keyBlock + 10 * 6));
num_to_bytes(0xa0478cc39091, 6, (uint8_t*)(keyBlock + 11 * 6));
num_to_bytes(0x533cb6c723f6, 6, (uint8_t*)(keyBlock + 12 * 6));
num_to_bytes(0x8fd0a4f256e9, 6, (uint8_t*)(keyBlock + 13 * 6));
num_to_bytes(0x1a2b3c4d5e6f, 6, (uint8_t*)(keyBlock + 14 * 6));
PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt); PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);
for (i = 0; i < SectorsCnt; i++) { mfCheckKeysSec(SectorsCnt, 2, btimeout14a, true, NESTED_KEY_COUNT, keyBlock, e_sector);
for (j = 0; j < 2; j++) {
if (e_sector[i].foundKey[j]) continue;
res = mfCheckKeys(FirstBlockOfSector(i), j, true, NESTED_KEY_COUNT, keyBlock, &key64);
if (!res) {
e_sector[i].Key[j] = key64;
e_sector[i].foundKey[j] = 1;
}
}
}
// get known key from array // get known key from array
bool keyFound = false; bool keyFound = false;
@ -772,6 +771,9 @@ int CmdHF14AMfNested(const char *Cmd)
PrintAndLog("Found valid key:%012" PRIx64, key64); PrintAndLog("Found valid key:%012" PRIx64, key64);
e_sector[sectorNo].foundKey[trgKeyType] = 1; e_sector[sectorNo].foundKey[trgKeyType] = 1;
e_sector[sectorNo].Key[trgKeyType] = key64; e_sector[sectorNo].Key[trgKeyType] = key64;
// try to check this key as a key to the other sectors
mfCheckKeysSec(SectorsCnt, 2, btimeout14a, true, 1, keyBlock, e_sector);
} }
} }
} }
@ -781,66 +783,6 @@ int CmdHF14AMfNested(const char *Cmd)
PrintAndLog("\n\n-----------------------------------------------\nNested statistic:\nIterations count: %d", iterations); PrintAndLog("\n\n-----------------------------------------------\nNested statistic:\nIterations count: %d", iterations);
PrintAndLog("Time in nested: %1.3f (%1.3f sec per key)", ((float)(msclock() - msclock1))/1000.0, ((float)(msclock() - msclock1))/iterations/1000.0); PrintAndLog("Time in nested: %1.3f (%1.3f sec per key)", ((float)(msclock() - msclock1))/1000.0, ((float)(msclock() - msclock1))/iterations/1000.0);
// check if we have unrecognized keys
bool notFoundKeys = false;
for (i = 0; i < SectorsCnt; i++) {
for (j = 0; j < 2; j++) {
if (!e_sector[i].foundKey[j]) {
notFoundKeys = true;
break;
}
}
if (notFoundKeys) break;
}
if (notFoundKeys) {
PrintAndLog("-----------------------------------------------\n");
PrintAndLog("We have unrecognized keys. Trying to check if we have this keys on key buffer...");
// fill keyBlock with known keys
int cnt = 0;
for (i = 0; i < SectorsCnt; i++) {
for (j = 0; j < 2; j++) {
if (e_sector[i].foundKey[j]) {
// try to insert key to keyBlock
if (cnt < NESTED_KEY_COUNT) {
// search for dublicates
bool dubl = false;
for (int v = 0; v < NESTED_KEY_COUNT; v++) {
if (e_sector[i].Key[j] == bytes_to_num((uint8_t*)(keyBlock + v * 6), 6)) {
dubl = true;
break;
}
}
// insert
if (!dubl) {
num_to_bytes(e_sector[i].Key[j], 6, (uint8_t*)(keyBlock + cnt * 6));
cnt++;
}
}
}
}
}
// try to auth with known keys to not recognized sectors keys
PrintAndLog("Testing keys. Sector count=%d known keys count:%d", SectorsCnt, cnt);
for (i = 0; i < SectorsCnt; i++) {
for (j = 0; j < 2; j++) {
if (e_sector[i].foundKey[j]) continue;
res = mfCheckKeys(FirstBlockOfSector(i), j, true, cnt, keyBlock, &key64);
if (!res) {
e_sector[i].Key[j] = key64;
e_sector[i].foundKey[j] = 1;
}
}
}
} // if (notFoundKeys)
// print result // print result
PrintAndLog("|---|----------------|---|----------------|---|"); PrintAndLog("|---|----------------|---|----------------|---|");
PrintAndLog("|sec|key A |res|key B |res|"); PrintAndLog("|sec|key A |res|key B |res|");
@ -1022,14 +964,18 @@ int CmdHF14AMfNestedHard(const char *Cmd)
int CmdHF14AMfChk(const char *Cmd) int CmdHF14AMfChk(const char *Cmd)
{ {
if (strlen(Cmd)<3) { if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]"); PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d|s|ss] [<key (12 hex symbols)>] [<dic (*.dic)>]");
PrintAndLog(" * - all sectors"); PrintAndLog(" * - all sectors");
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K"); PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
PrintAndLog("d - write keys to binary file\n"); PrintAndLog("d - write keys to binary file\n");
PrintAndLog("t - write keys to emulator memory"); PrintAndLog("t - write keys to emulator memory");
PrintAndLog("s - slow execute. timeout 1ms");
PrintAndLog("ss- very slow execute. timeout 5ms");
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");
PrintAndLog(" hf mf chk *1 ? t"); PrintAndLog(" hf mf chk *1 ? t");
PrintAndLog(" hf mf chk *1 ? d"); PrintAndLog(" hf mf chk *1 ? d");
PrintAndLog(" hf mf chk *1 ? s");
PrintAndLog(" hf mf chk *1 ? dss");
return 0; return 0;
} }
@ -1042,42 +988,28 @@ int CmdHF14AMfChk(const char *Cmd)
int i, res; int i, res;
int keycnt = 0; int keycnt = 0;
char ctmp = 0x00; char ctmp = 0x00;
char ctmp3[3] = {0x00};
uint8_t blockNo = 0; uint8_t blockNo = 0;
uint8_t SectorsCnt = 1; uint8_t SectorsCnt = 0;
uint8_t keyType = 0; uint8_t keyType = 0;
uint64_t key64 = 0; uint64_t key64 = 0;
uint32_t timeout14a = 0; // timeout in us
bool param3InUse = false;
int transferToEml = 0; int transferToEml = 0;
int createDumpFile = 0; int createDumpFile = 0;
sector_t *e_sector = NULL;
keyBlock = calloc(stKeyBlock, 6); keyBlock = calloc(stKeyBlock, 6);
if (keyBlock == NULL) return 1; if (keyBlock == NULL) return 1;
uint64_t defaultKeys[] = int defaultKeysSize = MifareDefaultKeysSize;
{ for (int defaultKeyCounter = 0; defaultKeyCounter < defaultKeysSize; defaultKeyCounter++){
0xffffffffffff, // Default key (first key used by program if no user defined key) num_to_bytes(MifareDefaultKeys[defaultKeyCounter], 6, (uint8_t*)(keyBlock + defaultKeyCounter * 6));
0x000000000000, // Blank key
0xa0a1a2a3a4a5, // NFCForum MAD key
0xb0b1b2b3b4b5,
0xaabbccddeeff,
0x4d3a99c351dd,
0x1a982c7e459a,
0xd3f7d3f7d3f7,
0x714c5c886e97,
0x587ee5f9350f,
0xa0478cc39091,
0x533cb6c723f6,
0x8fd0a4f256e9
};
int defaultKeysSize = sizeof(defaultKeys) / sizeof(uint64_t);
for (int defaultKeyCounter = 0; defaultKeyCounter < defaultKeysSize; defaultKeyCounter++)
{
num_to_bytes(defaultKeys[defaultKeyCounter], 6, (uint8_t*)(keyBlock + defaultKeyCounter * 6));
} }
if (param_getchar(Cmd, 0)=='*') { if (param_getchar(Cmd, 0)=='*') {
blockNo = 3;
SectorsCnt = ParamCardSizeSectors(param_getchar(Cmd + 1, 0)); SectorsCnt = ParamCardSizeSectors(param_getchar(Cmd + 1, 0));
} }
else else
@ -1086,10 +1018,10 @@ int CmdHF14AMfChk(const char *Cmd)
ctmp = param_getchar(Cmd, 1); ctmp = param_getchar(Cmd, 1);
switch (ctmp) { switch (ctmp) {
case 'a': case 'A': case 'a': case 'A':
keyType = !0; keyType = 0;
break; break;
case 'b': case 'B': case 'b': case 'B':
keyType = !1; keyType = 1;
break; break;
case '?': case '?':
keyType = 2; keyType = 2;
@ -1100,11 +1032,33 @@ int CmdHF14AMfChk(const char *Cmd)
return 1; return 1;
}; };
// transfer to emulator & create dump file
ctmp = param_getchar(Cmd, 2); ctmp = param_getchar(Cmd, 2);
if (ctmp == 't' || ctmp == 'T') transferToEml = 1; if (ctmp == 't' || ctmp == 'T') transferToEml = 1;
else if (ctmp == 'd' || ctmp == 'D') createDumpFile = 1; if (ctmp == 'd' || ctmp == 'D') createDumpFile = 1;
for (i = transferToEml || createDumpFile; param_getchar(Cmd, 2 + i); i++) { param3InUse = transferToEml | createDumpFile;
timeout14a = 500; // fast by default
// double parameters - ts, ds
int clen = param_getlength(Cmd, 2);
if (clen == 2 || clen == 3){
param_getstr(Cmd, 2, ctmp3);
ctmp = ctmp3[1];
}
//parse
if (ctmp == 's' || ctmp == 'S') {
timeout14a = 1000; // slow
if (!param3InUse && clen == 2 && (ctmp3[1] == 's' || ctmp3[1] == 'S')) {
timeout14a = 5000; // very slow
}
if (param3InUse && clen == 3 && (ctmp3[2] == 's' || ctmp3[2] == 'S')) {
timeout14a = 5000; // very slow
}
param3InUse = true;
}
for (i = param3InUse; param_getchar(Cmd, 2 + i); i++) {
if (!param_gethex(Cmd, 2 + i, keyBlock + 6 * keycnt, 12)) { if (!param_gethex(Cmd, 2 + i, keyBlock + 6 * keycnt, 12)) {
if ( stKeyBlock - keycnt < 2) { if ( stKeyBlock - keycnt < 2) {
p = realloc(keyBlock, 6*(stKeyBlock+=10)); p = realloc(keyBlock, 6*(stKeyBlock+=10));
@ -1169,6 +1123,7 @@ int CmdHF14AMfChk(const char *Cmd)
} }
} }
// fill with default keys
if (keycnt == 0) { if (keycnt == 0) {
PrintAndLog("No key specified, trying default keys"); PrintAndLog("No key specified, trying default keys");
for (;keycnt < defaultKeysSize; keycnt++) for (;keycnt < defaultKeysSize; keycnt++)
@ -1178,47 +1133,84 @@ int CmdHF14AMfChk(const char *Cmd)
} }
// initialize storage for found keys // initialize storage for found keys
bool validKey[2][40]; e_sector = calloc(SectorsCnt, sizeof(sector_t));
uint8_t foundKey[2][40][6]; if (e_sector == NULL) return 1;
for (uint16_t t = 0; t < 2; t++) { for (uint8_t keyAB = 0; keyAB < 2; keyAB++) {
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
validKey[t][sectorNo] = false; e_sector[sectorNo].Key[keyAB] = 0xffffffffffff;
for (uint16_t i = 0; i < 6; i++) { e_sector[sectorNo].foundKey[keyAB] = 0;
foundKey[t][sectorNo][i] = 0xff;
}
} }
} }
printf("\n");
for ( int t = !keyType; t < 2; keyType==2?(t++):(t=2) ) { bool foundAKey = false;
int b=blockNo; uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;
for (int i = 0; i < SectorsCnt; ++i) { if (SectorsCnt) {
PrintAndLog("--sector:%2d, block:%3d, key type:%C, key count:%2d ", i, b, t?'B':'A', keycnt); PrintAndLog("To cancel this operation press the button on the proxmark...");
uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt; printf("--");
for (uint32_t c = 0; c < keycnt; c += max_keys) {
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;
res = mfCheckKeysSec(SectorsCnt, keyType, timeout14a * 1.06 / 100, true, size, &keyBlock[6 * c], e_sector); // timeout is (ms * 106)/10 or us*0.0106
if (res != 1) {
if (!res) {
printf("o");
foundAKey = true;
} else {
printf(".");
}
} else {
printf("\n");
PrintAndLog("Command execute timeout");
}
}
} else {
int keyAB = keyType;
do {
for (uint32_t c = 0; c < keycnt; c+=max_keys) { for (uint32_t c = 0; c < keycnt; c+=max_keys) {
uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c;
res = mfCheckKeys(b, t, true, size, &keyBlock[6*c], &key64); uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;
res = mfCheckKeys(blockNo, keyAB & 0x01, true, size, &keyBlock[6 * c], &key64);
if (res != 1) { if (res != 1) {
if (!res) { if (!res) {
PrintAndLog("Found valid key:[%012" PRIx64 "]",key64); PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64);
num_to_bytes(key64, 6, foundKey[t][i]); foundAKey = true;
validKey[t][i] = true;
} }
} else { } else {
PrintAndLog("Command execute timeout"); PrintAndLog("Command execute timeout");
} }
} }
b<127?(b+=4):(b+=16); } while(--keyAB > 0);
}
// print result
if (foundAKey) {
if (SectorsCnt) {
PrintAndLog("");
PrintAndLog("|---|----------------|---|----------------|---|");
PrintAndLog("|sec|key A |res|key B |res|");
PrintAndLog("|---|----------------|---|----------------|---|");
for (i = 0; i < SectorsCnt; i++) {
PrintAndLog("|%03d| %012" PRIx64 " | %d | %012" PRIx64 " | %d |", i,
e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]);
}
PrintAndLog("|---|----------------|---|----------------|---|");
} }
} else {
PrintAndLog("");
PrintAndLog("No valid keys found.");
} }
if (transferToEml) { if (transferToEml) {
uint8_t block[16]; uint8_t block[16];
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
if (validKey[0][sectorNo] || validKey[1][sectorNo]) { if (e_sector[sectorNo].foundKey[0] || e_sector[sectorNo].foundKey[1]) {
mfEmlGetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); mfEmlGetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
for (uint16_t t = 0; t < 2; t++) { for (uint16_t t = 0; t < 2; t++) {
if (validKey[t][sectorNo]) { if (e_sector[sectorNo].foundKey[t]) {
memcpy(block + t*10, foundKey[t][sectorNo], 6); num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10);
} }
} }
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
@ -1231,16 +1223,22 @@ int CmdHF14AMfChk(const char *Cmd)
FILE *fkeys = fopen("dumpkeys.bin","wb"); FILE *fkeys = fopen("dumpkeys.bin","wb");
if (fkeys == NULL) { if (fkeys == NULL) {
PrintAndLog("Could not create file dumpkeys.bin"); PrintAndLog("Could not create file dumpkeys.bin");
free(e_sector);
free(keyBlock); free(keyBlock);
return 1; return 1;
} }
for (uint16_t t = 0; t < 2; t++) { uint8_t mkey[6];
fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys); for (uint8_t t = 0; t < 2; t++) {
for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
num_to_bytes(e_sector[sectorNo].Key[t], 6, mkey);
fwrite(mkey, 1, 6, fkeys);
}
} }
fclose(fkeys); fclose(fkeys);
PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys."); PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys.");
} }
free(e_sector);
free(keyBlock); free(keyBlock);
PrintAndLog(""); PrintAndLog("");
return 0; return 0;

View file

@ -11,6 +11,8 @@
#ifndef CMDHFMF_H__ #ifndef CMDHFMF_H__
#define CMDHFMF_H__ #define CMDHFMF_H__
#include "mifaredefault.h"
extern int CmdHFMF(const char *Cmd); extern int CmdHFMF(const char *Cmd);
extern int CmdHF14AMfDbg(const char* cmd); extern int CmdHF14AMfDbg(const char* cmd);

View file

@ -139,7 +139,7 @@ int getCommand(UsbCommand* response)
* @param ms_timeout * @param ms_timeout
* @return true if command was returned, otherwise false * @return true if command was returned, otherwise false
*/ */
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) {
UsbCommand resp; UsbCommand resp;
@ -155,7 +155,7 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou
} }
} }
msleep(10); // XXX ugh msleep(10); // XXX ugh
if (dm_seconds == 200) { // Two seconds elapsed if (dm_seconds == 200 && show_warning) { // Two seconds elapsed
PrintAndLog("Waiting for a response from the proxmark..."); PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
} }
@ -163,9 +163,12 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou
return false; return false;
} }
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) {
return WaitForResponseTimeoutW(cmd, response, ms_timeout, true);
}
bool WaitForResponse(uint32_t cmd, UsbCommand* response) { bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
return WaitForResponseTimeout(cmd,response,-1); return WaitForResponseTimeoutW(cmd, response, -1, true);
} }

View file

@ -18,6 +18,7 @@
extern void UsbCommandReceived(UsbCommand *UC); extern void UsbCommandReceived(UsbCommand *UC);
extern int CommandReceived(char *Cmd); extern int CommandReceived(char *Cmd);
extern bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning);
extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
extern bool WaitForResponse(uint32_t cmd, UsbCommand* response); extern bool WaitForResponse(uint32_t cmd, UsbCommand* response);
extern void clearCommandBuffer(); extern void clearCommandBuffer();

40
client/mifaredefault.h Normal file
View file

@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2017 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Mifare default constants
//-----------------------------------------------------------------------------
#ifndef MIFAREDEFAULT_H__
#define MIFAREDEFAULT_H__
#include <inttypes.h>
#define MifareDefaultKeysSize sizeof(MifareDefaultKeys) / sizeof(uint64_t)
static const uint64_t MifareDefaultKeys[] =
{
0xffffffffffff, // Default key (first key used by program if no user defined key)
0x000000000000, // Blank key
0xa0a1a2a3a4a5, // NFCForum MAD key
0xb0b1b2b3b4b5,
0xaabbccddeeff,
0x1a2b3c4d5e6f,
0x123456789abc,
0x010203040506,
0x123456abcdef,
0xabcdef123456,
0x4d3a99c351dd,
0x1a982c7e459a,
0xd3f7d3f7d3f7,
0x714c5c886e97,
0x587ee5f9350f,
0xa0478cc39091,
0x533cb6c723f6,
0x8fd0a4f256e9
};
#endif

View file

@ -228,7 +228,7 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
*key = -1; *key = -1;
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}}; UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType & 0xff) << 8)), clear_trace, keycnt}};
memcpy(c.d.asBytes, keyBlock, 6 * keycnt); memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
SendCommand(&c); SendCommand(&c);
@ -239,6 +239,35 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key
return 0; return 0;
} }
int mfCheckKeysSec(uint8_t sectorCnt, uint8_t keyType, uint8_t timeout14a, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, sector_t * e_sector){
uint8_t keyPtr = 0;
if (e_sector == NULL)
return -1;
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((sectorCnt & 0xff) | ((keyType & 0xff) << 8)), (clear_trace | 0x02)|((timeout14a & 0xff) << 8), keycnt}};
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeoutW(CMD_ACK, &resp, MAX(3000, 1000 + 13 * sectorCnt * keycnt * (keyType == 2 ? 2 : 1)), false)) return 1; // timeout: 13 ms / fail auth
if ((resp.arg[0] & 0xff) != 0x01) return 2;
bool foundAKey = false;
for(int sec = 0; sec < sectorCnt; sec++){
for(int keyAB = 0; keyAB < 2; keyAB++){
keyPtr = *(resp.d.asBytes + keyAB * 40 + sec);
if (keyPtr){
e_sector[sec].foundKey[keyAB] = true;
e_sector[sec].Key[keyAB] = bytes_to_num(keyBlock + (keyPtr - 1) * 6, 6);
foundAKey = true;
}
}
}
return foundAKey ? 0 : 3;
}
// Compare 16 Bits out of cryptostate // Compare 16 Bits out of cryptostate
int Compare16Bits(const void * a, const void * b) { int Compare16Bits(const void * a, const void * b) {
if ((*(uint64_t*)b & 0x00ff000000ff0000) == (*(uint64_t*)a & 0x00ff000000ff0000)) return 0; if ((*(uint64_t*)b & 0x00ff000000ff0000) == (*(uint64_t*)a & 0x00ff000000ff0000)) return 0;

View file

@ -1,4 +1,4 @@
// Merlok, 2011 // Merlok, 2011, 2017
// people from mifare@nethemba.com, 2010 // people from mifare@nethemba.com, 2010
// //
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // This code is licensed to you under the terms of the GNU GPL, version 2 or,
@ -15,6 +15,11 @@
#include <stdbool.h> #include <stdbool.h>
#include "data.h" #include "data.h"
// defaults
// timeout in units. (ms * 106)/10 or us*0.0106
// 5 == 500us
#define MF_CHKKEYS_DEFTIMEOUT 5
// mfCSetBlock work flags // mfCSetBlock work flags
#define CSETBLOCK_UID 0x01 #define CSETBLOCK_UID 0x01
#define CSETBLOCK_WUPC 0x02 #define CSETBLOCK_WUPC 0x02
@ -24,11 +29,17 @@
#define CSETBLOCK_SINGLE_OPER 0x1F #define CSETBLOCK_SINGLE_OPER 0x1F
#define CSETBLOCK_MAGIC_1B 0x40 #define CSETBLOCK_MAGIC_1B 0x40
typedef struct {
uint64_t Key[2];
int foundKey[2];
} sector_t;
extern char logHexFileName[FILE_PATH_SIZE]; extern char logHexFileName[FILE_PATH_SIZE];
extern int mfDarkside(uint64_t *key); extern int mfDarkside(uint64_t *key);
extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *ResultKeys, bool calibrate); extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *ResultKeys, bool calibrate);
extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key);
extern int mfCheckKeysSec(uint8_t sectorCnt, uint8_t keyType, uint8_t timeout14a, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, sector_t * e_sector);
extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);

View file

@ -38,19 +38,20 @@
#define AT91C_EP_CONTROL 0 #define AT91C_EP_CONTROL 0
#define AT91C_EP_IN_SIZE 0x40
#define AT91C_EP_OUT 1 #define AT91C_EP_OUT 1
#define AT91C_EP_OUT_SIZE 0x40
#define AT91C_EP_IN 2 #define AT91C_EP_IN 2
#define AT91C_EP_NOTIFY 3
#define AT91C_EP_OUT_SIZE 0x40
#define AT91C_EP_IN_SIZE 0x40
static const char devDescriptor[] = { static const char devDescriptor[] = {
/* Device descriptor */ /* Device descriptor */
0x12, // bLength 0x12, // bLength
0x01, // bDescriptorType 0x01, // bDescriptorType
0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0) 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)
0x02, // bDeviceClass: CDC class code 0x02, // bDeviceClass: (Communication Device Class)
0x00, // bDeviceSubclass: CDC class sub code 0x00, // bDeviceSubclass: (unused at this time)
0x00, // bDeviceProtocol: CDC Device protocol 0x00, // bDeviceProtocol: (unused at this time)
0x08, // bMaxPacketSize0 0x08, // bMaxPacketSize0
0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues) 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)
0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument) 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)
@ -74,79 +75,78 @@ static const char cfgDescriptor[] = {
0xC0, // CbmAttributes 0xA0 0xC0, // CbmAttributes 0xA0
0xFA, // CMaxPower 0xFA, // CMaxPower
/* Communication Class Interface Descriptor Requirement */ /* Interface 0 Descriptor: Communication Class Interface */
0x09, // bLength 0x09, // bLength
0x04, // bDescriptorType 0x04, // bDescriptorType
0x00, // bInterfaceNumber 0x00, // bInterfaceNumber
0x00, // bAlternateSetting 0x00, // bAlternateSetting
0x01, // bNumEndpoints 0x01, // bNumEndpoints
0x02, // bInterfaceClass 0x02, // bInterfaceClass: Communication Interface Class
0x02, // bInterfaceSubclass 0x02, // bInterfaceSubclass: Abstract Control Model
0x01, // bInterfaceProtocol 0x01, // bInterfaceProtocol: Common AT Commands, V.25ter
0x00, // iInterface 0x00, // iInterface
/* Header Functional Descriptor */ /* Header Functional Descriptor */
0x05, // bFunction Length 0x05, // bFunction Length
0x24, // bDescriptor type: CS_INTERFACE 0x24, // bDescriptor type: CS_INTERFACE
0x00, // bDescriptor subtype: Header Func Desc 0x00, // bDescriptor subtype: Header Functional Descriptor
0x10, // bcdCDC:1.1 0x10, // bcdCDC:1.1
0x01, 0x01,
/* ACM Functional Descriptor */ /* ACM Functional Descriptor */
0x04, // bFunctionLength 0x04, // bFunctionLength
0x24, // bDescriptor Type: CS_INTERFACE 0x24, // bDescriptor Type: CS_INTERFACE
0x02, // bDescriptor Subtype: ACM Func Desc 0x02, // bDescriptor Subtype: Abstract Control Management Functional Descriptor
0x02, // bmCapabilities 0x02, // bmCapabilities: D1: Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
/* Union Functional Descriptor */ /* Union Functional Descriptor */
0x05, // bFunctionLength 0x05, // bFunctionLength
0x24, // bDescriptorType: CS_INTERFACE 0x24, // bDescriptorType: CS_INTERFACE
0x06, // bDescriptor Subtype: Union Func Desc 0x06, // bDescriptor Subtype: Union Functional Descriptor
0x00, // bMasterInterface: Communication Class Interface 0x00, // bMasterInterface: Communication Class Interface
0x01, // bSlaveInterface0: Data Class Interface 0x01, // bSlaveInterface0: Data Class Interface
/* Call Management Functional Descriptor */ /* Call Management Functional Descriptor */
0x05, // bFunctionLength 0x05, // bFunctionLength
0x24, // bDescriptor Type: CS_INTERFACE 0x24, // bDescriptor Type: CS_INTERFACE
0x01, // bDescriptor Subtype: Call Management Func Desc 0x01, // bDescriptor Subtype: Call Management Functional Descriptor
0x00, // bmCapabilities: D1 + D0 0x00, // bmCapabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself
0x01, // bDataInterface: Data Class Interface 1 0x01, // bDataInterface: Data Class Interface 1
/* Endpoint 1 descriptor */ /* Endpoint 1 descriptor */
0x07, // bLength 0x07, // bLength
0x05, // bDescriptorType 0x05, // bDescriptorType
0x83, // bEndpointAddress, Endpoint 03 - IN 0x83, // bEndpointAddress: Endpoint 03 - IN
0x03, // bmAttributes INT 0x03, // bmAttributes: INT
0x08, // wMaxPacketSize 0x08, // wMaxPacketSize: 8
0x00, 0x00,
0xFF, // bInterval 0xFF, // bInterval
/* Data Class Interface Descriptor Requirement */ /* Interface 1 Descriptor: Data Class Interface */
0x09, // bLength 0x09, // bLength
0x04, // bDescriptorType 0x04, // bDescriptorType
0x01, // bInterfaceNumber 0x01, // bInterfaceNumber
0x00, // bAlternateSetting 0x00, // bAlternateSetting
0x02, // bNumEndpoints 0x02, // bNumEndpoints
0x0A, // bInterfaceClass 0x0A, // bInterfaceClass: Data Interface Class
0x00, // bInterfaceSubclass 0x00, // bInterfaceSubclass: not used
0x00, // bInterfaceProtocol 0x00, // bInterfaceProtocol: No class specific protocol required)
0x00, // iInterface 0x00, // iInterface
/* First alternate setting */
/* Endpoint 1 descriptor */ /* Endpoint 1 descriptor */
0x07, // bLength 0x07, // bLength
0x05, // bDescriptorType 0x05, // bDescriptorType
0x01, // bEndpointAddress, Endpoint 01 - OUT 0x01, // bEndpointAddress: Endpoint 01 - OUT
0x02, // bmAttributes BULK 0x02, // bmAttributes: BULK
AT91C_EP_OUT_SIZE, // wMaxPacketSize AT91C_EP_OUT_SIZE, // wMaxPacketSize
0x00, 0x00,
0x00, // bInterval 0x00, // bInterval
/* Endpoint 2 descriptor */ /* Endpoint 2 descriptor */
0x07, // bLength 0x07, // bLength
0x05, // bDescriptorType 0x05, // bDescriptorType
0x82, // bEndpointAddress, Endpoint 02 - IN 0x82, // bEndpointAddress: Endpoint 02 - IN
0x02, // bmAttributes BULK 0x02, // bmAttributes: BULK
AT91C_EP_IN_SIZE, // wMaxPacketSize AT91C_EP_IN_SIZE, // wMaxPacketSize
0x00, 0x00,
0x00 // bInterval 0x00 // bInterval
@ -262,6 +262,7 @@ AT91S_CDC_LINE_CODING line = {
0, // None Parity 0, // None Parity
8}; // 8 Data bits 8}; // 8 Data bits
void AT91F_CDC_Enumerate(); void AT91F_CDC_Enumerate();
AT91PS_UDP pUdp = AT91C_BASE_UDP; AT91PS_UDP pUdp = AT91C_BASE_UDP;
@ -269,52 +270,55 @@ byte_t btConfiguration = 0;
byte_t btConnection = 0; byte_t btConnection = 0;
byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn usb_disable //* \fn usb_disable
//* \brief This function deactivates the USB device //* \brief This function deactivates the USB device
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
void usb_disable() { void usb_disable() {
// Disconnect the USB device // Disconnect the USB device
AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
// Clear all lingering interrupts // Clear all lingering interrupts
if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) { if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {
pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
} }
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn usb_enable //* \fn usb_enable
//* \brief This function Activates the USB device //* \brief This function Activates the USB device
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
void usb_enable() { void usb_enable() {
// Set the PLL USB Divider // Set the PLL USB Divider
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
// Specific Chip USB Initialisation // Specific Chip USB Initialisation
// Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP; AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
// Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
// Set in PIO mode and Configure in Output // Set in PIO mode and Configure in Output
AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
// Clear for set the Pullup resistor // Clear for set the Pullup resistor
AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU; AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
// Disconnect and reconnect USB controller for 100ms // Disconnect and reconnect USB controller for 100ms
usb_disable(); usb_disable();
// Wait for a short while // Wait for a short while
for (volatile size_t i=0; i<0x100000; i++); for (volatile size_t i=0; i<0x100000; i++);
// Reconnect USB reconnect // Reconnect USB reconnect
AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn usb_check //* \fn usb_check
//* \brief Test if the device is configured and handle enumeration //* \brief Test if the device is configured and handle enumeration
@ -331,8 +335,7 @@ bool usb_check() {
pUdp->UDP_FADDR = AT91C_UDP_FEN; pUdp->UDP_FADDR = AT91C_UDP_FEN;
// Configure endpoint 0 // Configure endpoint 0
pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
} } else if (isr & AT91C_UDP_EPINT0) {
else if (isr & AT91C_UDP_EPINT0) {
pUdp->UDP_ICR = AT91C_UDP_EPINT0; pUdp->UDP_ICR = AT91C_UDP_EPINT0;
AT91F_CDC_Enumerate(); AT91F_CDC_Enumerate();
} }
@ -342,10 +345,11 @@ bool usb_check() {
bool usb_poll() bool usb_poll()
{ {
if (!usb_check()) return false; if (!usb_check()) return false;
return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
} }
/** /**
In github PR #129, some users appears to get a false positive from In github PR #129, some users appears to get a false positive from
usb_poll, which returns true, but the usb_read operation usb_poll, which returns true, but the usb_read operation
@ -356,7 +360,6 @@ bool usb_poll()
**/ **/
bool usb_poll_validate_length() bool usb_poll_validate_length()
{ {
if (!usb_check()) return false; if (!usb_check()) return false;
if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0; return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
@ -393,32 +396,37 @@ uint32_t usb_read(byte_t* data, size_t len) {
return nbBytesRcv; return nbBytesRcv;
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn usb_write //* \fn usb_write
//* \brief Send through endpoint 2 //* \brief Send through endpoint 2
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
uint32_t usb_write(const byte_t* data, const size_t len) { uint32_t usb_write(const byte_t* data, const size_t len) {
size_t length = len; size_t length = len;
uint32_t cpt = 0; uint32_t cpt = 0;
if (!length) return 0; if (!length) return 0;
if (!usb_check()) return 0; if (!usb_check()) return 0;
// Send the first packet // Send the first packet
cpt = MIN(length, AT91C_EP_IN_SIZE-1); cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt; length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++; while (cpt--) {
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
}
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
while (length) { while (length) {
// Fill the second bank // Fill the next bank
cpt = MIN(length, AT91C_EP_IN_SIZE-1); cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt; length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++; while (cpt--) {
// Wait for the first bank to be sent pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
}
// Wait for the previous bank to be sent
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
if (!usb_check()) return length; if (!usb_check()) return length;
} }
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
@ -427,7 +435,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
// Wait for the end of transfer // Wait for the end of transfer
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
if (!usb_check()) return length; if (!usb_check()) return length;
} }
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
@ -435,6 +443,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) {
return length; return length;
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendData //* \fn AT91F_USB_SendData
//* \brief Send Data through the control endpoint //* \brief Send Data through the control endpoint
@ -477,6 +486,7 @@ static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t leng
} }
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendZlp //* \fn AT91F_USB_SendZlp
//* \brief Send zero length packet through the control endpoint //* \brief Send zero length packet through the control endpoint
@ -488,6 +498,7 @@ void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendStall //* \fn AT91F_USB_SendStall
//* \brief Stall the control endpoint //* \brief Stall the control endpoint
@ -499,6 +510,7 @@ void AT91F_USB_SendStall(AT91PS_UDP pUdp) {
while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
} }
//*---------------------------------------------------------------------------- //*----------------------------------------------------------------------------
//* \fn AT91F_CDC_Enumerate //* \fn AT91F_CDC_Enumerate
//* \brief This function is a callback invoked when a SETUP packet is received //* \brief This function is a callback invoked when a SETUP packet is received
@ -510,16 +522,16 @@ void AT91F_CDC_Enumerate() {
if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ) if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) )
return; return;
bmRequestType = pUdp->UDP_FDR[0]; bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
bRequest = pUdp->UDP_FDR[0]; bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
wValue = (pUdp->UDP_FDR[0] & 0xFF); wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wValue |= (pUdp->UDP_FDR[0] << 8); wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
wIndex = (pUdp->UDP_FDR[0] & 0xFF); wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wIndex |= (pUdp->UDP_FDR[0] << 8); wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
wLength = (pUdp->UDP_FDR[0] & 0xFF); wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
wLength |= (pUdp->UDP_FDR[0] << 8); wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
if (bmRequestType & 0x80) { if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR); UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) ); while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) );
} }
@ -553,29 +565,29 @@ void AT91F_CDC_Enumerate() {
btConfiguration = wValue; btConfiguration = wValue;
AT91F_USB_SendZlp(pUdp); AT91F_USB_SendZlp(pUdp);
pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
pUdp->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
pUdp->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
pUdp->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0; pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
break; break;
case STD_GET_CONFIGURATION: case STD_GET_CONFIGURATION:
AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration)); AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
break; break;
case STD_GET_STATUS_ZERO: case STD_GET_STATUS_ZERO:
wStatus = 0; wStatus = 0; // Device is Bus powered, remote wakeup disabled
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
break; break;
case STD_GET_STATUS_INTERFACE: case STD_GET_STATUS_INTERFACE:
wStatus = 0; wStatus = 0; // reserved for future use
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
break; break;
case STD_GET_STATUS_ENDPOINT: case STD_GET_STATUS_ENDPOINT:
wStatus = 0; wStatus = 0;
wIndex &= 0x0F; wIndex &= 0x0F;
if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) { if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
} }
else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) { else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
} }
@ -590,7 +602,7 @@ void AT91F_CDC_Enumerate() {
break; break;
case STD_SET_FEATURE_ENDPOINT: case STD_SET_FEATURE_ENDPOINT:
wIndex &= 0x0F; wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex <= 3)) { if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
pUdp->UDP_CSR[wIndex] = 0; pUdp->UDP_CSR[wIndex] = 0;
AT91F_USB_SendZlp(pUdp); AT91F_USB_SendZlp(pUdp);
} }
@ -605,13 +617,13 @@ void AT91F_CDC_Enumerate() {
break; break;
case STD_CLEAR_FEATURE_ENDPOINT: case STD_CLEAR_FEATURE_ENDPOINT:
wIndex &= 0x0F; wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex <= 3)) { if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
if (wIndex == 1) if (wIndex == AT91C_EP_OUT)
pUdp->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
else if (wIndex == 2) else if (wIndex == AT91C_EP_IN)
pUdp->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
else if (wIndex == 3) else if (wIndex == AT91C_EP_NOTIFY)
pUdp->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN); pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
AT91F_USB_SendZlp(pUdp); AT91F_USB_SendZlp(pUdp);
} }
else else