CHG: finalized the merge between peter filmoores 14atagfuzz branch (emv). I seriously doubt anything works.

This commit is contained in:
iceman1001 2017-03-01 21:51:23 +01:00
commit 99136c6eef
12 changed files with 678 additions and 248 deletions

View file

@ -1233,9 +1233,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_EMV_READ_RECORD: case CMD_EMV_READ_RECORD:
EMVReadRecord(c->arg[0], c->arg[1], NULL); EMVReadRecord(c->arg[0], c->arg[1], NULL);
break; break;
case CMD_EMV_TRANSACTION:
EMVTransaction();
break;
case CMD_EMV_CLONE: case CMD_EMV_CLONE:
EMVClone(c->arg[0], c->arg[1]); EMVClone(c->arg[0], c->arg[1]);
break; break;

View file

@ -29,6 +29,8 @@ extern "C" {
#include "pcf7931.h" #include "pcf7931.h"
#include "desfire.h" #include "desfire.h"
#include "iso14443b.h" #include "iso14443b.h"
//#include "iso14443a.h"
#include "emvcard.h"
extern int rsamples; // = 0; extern int rsamples; // = 0;
extern int tracing; // = TRUE; extern int tracing; // = TRUE;
@ -118,6 +120,9 @@ void ReaderIso14443a(UsbCommand * c);
//bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); //bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity); void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
void iso14a_set_trigger(bool enable); void iso14a_set_trigger(bool enable);
// also used in emv
bool prepare_allocated_tag_modulation(tag_response_info_t * response_info);
int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
// epa.h // epa.h
void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Collect_Nonce(UsbCommand * c);
@ -220,23 +225,22 @@ bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* d
// util.h // util.h
void HfSnoop(int , int); void HfSnoop(int , int);
//EMV functions emvcmd.h //EMV functions
// emvcmd.h
void EMVTransaction(void); void EMVTransaction(void);
void EMVgetUDOL(void); void EMVgetUDOL(void);
void EMVloadvalue(uint32_t tag, uint8_t* datain); void EMVloadvalue(uint32_t tag, uint8_t* datain);
void EMVdumpcard(void); void EMVdumpcard(void);
/*
//void EMVSelect(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); //void EMVSelect(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
void EMVFuzz_RATS(uint8_t len, uint8_t* RATS); void EMVFuzz_RATS(uint8_t ratslen, uint8_t* RATS);
void EMVReadRecord(uint8_t arg0, uint8_t arg1,emvcard* inputcard); void EMVReadRecord(uint8_t arg0, uint8_t arg1,emvcard* inputcard);
void EMVSelectPPSE(); void EMVSelectPPSE();
void EMVSelectAID(uint8_t *AID, uint8_t AIDlen, emvcard* inputcard); void EMVSelectAID(uint8_t *AID, uint8_t AIDlen, emvcard* inputcard);
void EMVTransaction(); //perform an EMV transaction void EMVTransaction();
void EMVClone(uint8_t maxsfi, uint8_t maxrecord); //clone an EMV card. void EMVClone(uint8_t maxsfi, uint8_t maxrecord);
void EMVSim(); void EMVSim();
void EMVTest(); //test function for emv stuff. void EMVTest();
*/ void SimulateEMVcard();
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -240,6 +240,6 @@ typedef struct {
uint8_t tag_BF0C[222]; //File Control Information (FCI) Issuer Discretionary Data uint8_t tag_BF0C[222]; //File Control Information (FCI) Issuer Discretionary Data
uint8_t tag_DFName[16]; uint8_t tag_DFName[16];
uint8_t tag_DFName_len; uint8_t tag_DFName_len;
} emvtags; } emvcard;
#endif //__EMVCARD_H #endif //__EMVCARD_H

View file

@ -10,10 +10,37 @@
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
#include "emvcmd.h" #include "emvcmd.h"
static emvtags currentcard; //use to hold emv tags for the reader/card during communications static emvcard currentcard; //use to hold emv tags for the reader/card during communications
// The FPGA will report its internal sending delay in void EMVTest()
//uint16_t FpgaSendQueueDelay; {
uint8_t rats[0x0b] = {0x0b,0x78,0x80,0x81,0x02,0x4b,0x4f,0x4e,0x41, 0x14, 0x11};
EMVFuzz_RATS(0xb, rats);
//grab card
//EMVClone(1,1);
/*
uint8_t tagvalbuffer[256];
uint8_t tagvallen;
uint8_t template6F[] = {0x6F,0x00};
uint8_t templateA5[] = {0xA5,0x00};
uint8_t tag1[] = {0x50,0x00,0x00};
uint8_t tag2[] = {0x87,0x00,0x00};
uint8_t tag3[] = {0x9f,0x38,0x00};
uint8_t tag4[] = {0x5F,0x2D,0x00};
uint8_t tag5[] = {0x9F,0x11,0x00};
uint8_t tag6[] = {0x9F,0x12,0x00};
uint8_t tag7[] = {0x84, 0x00};
uint8_t tag8[] = {0xA5, 0x00};
emv_generatetemplate(templateA5,&currentcard,tagvalbuffer,&tagvallen, 6, tag1, tag2, tag3, tag4, tag5, tag6);
memcpy(currentcard.tag_A5, tagvalbuffer+2, tagvallen-2);
currentcard.tag_A5_len = tagvallen-2;
emv_generatetemplate(template6F,&currentcard,currentcard.tag_6F ,&currentcard.tag_6F_len, 2, tag7, tag8);
Dbprintf("TAG A5=");
Dbhexdump(currentcard.tag_A5_len,currentcard.tag_A5 , false);
*/
//EMVSim();
}
//load individual tag into current card //load individual tag into current card
@ -23,21 +50,25 @@ void EMVloadvalue(uint32_t tag, uint8_t *datain){
emv_settag(tag, datain, &currentcard); emv_settag(tag, datain, &currentcard);
} }
void EMVReadRecord(uint8_t arg0, uint8_t arg1,emvtags *currentcard) void EMVReadRecord(uint8_t arg0, uint8_t arg1,emvcard *currentcard)
{ {
uint8_t record = arg0; uint8_t record = arg0;
uint8_t sfi = arg1 & 0x0F; // convert arg1 to number uint8_t sfi = arg1 & 0x0F; // convert arg1 to number
uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t *resp = BigBuf_malloc(256);
// variables // variables
tlvtag inputtag; // create the tag structure tlvtag inputtag; // create the tag structure
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
// perform read // perform read
// write the result to the provided card // write the result to the provided card
if(!emv_readrecord(record,sfi,receivedAnswer)) { while(true) {
if(!emv_readrecord(record, sfi, resp)) {
if(MF_DBGLEVEL >= 1) Dbprintf("readrecord failed"); if(MF_DBGLEVEL >= 1) Dbprintf("readrecord failed");
} }
if(*(receivedAnswer+1) == 0x70){ if(*(resp+1) == 0x70){
decode_ber_tlv_item(receivedAnswer+1, &inputtag); decode_ber_tlv_item(resp+1, &inputtag);
emv_decode_field(inputtag.value, inputtag.valuelength, currentcard); emv_decode_field(inputtag.value, inputtag.valuelength, currentcard);
} }
else else
@ -45,46 +76,79 @@ void EMVReadRecord(uint8_t arg0, uint8_t arg1,emvtags *currentcard)
if(MF_DBGLEVEL >= 1) if(MF_DBGLEVEL >= 1)
Dbprintf("Record not found SFI=%i RECORD=%i", sfi, record); Dbprintf("Record not found SFI=%i RECORD=%i", sfi, record);
} }
return; LED_B_ON();
LED_B_OFF();
break;
}
LEDsoff();
} }
void EMVSelectAID(uint8_t *AID, uint8_t AIDlen, emvtags* inputcard) void EMVSelectAID(uint8_t *AID, uint8_t AIDlen, emvcard* inputcard)
{ {
uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t* resp = BigBuf_malloc(256);
// variables // variables
tlvtag inputtag; // create the tag structure tlvtag inputtag; // create the tag structure
// perform select LED_A_ON();
if(!emv_select(AID, AIDlen, receivedAnswer)){ LED_B_OFF();
if(MF_DBGLEVEL == 1) Dbprintf("AID Select failed"); LED_C_OFF();
return;
} while(true) {
// write the result to the provided card
if(*(receivedAnswer+1) == 0x6F){ if(!emv_select(AID, AIDlen, resp)){
// decode the 6F template if(MF_DBGLEVEL == 1) DbpString("AID Select failed");
decode_ber_tlv_item(receivedAnswer+1, &inputtag); break;
// store 84 and A5 tags }
emv_decode_field(inputtag.value, inputtag.valuelength, &currentcard);
// decode the A5 tag // write the result to the provided card
if(currentcard.tag_A5_len > 0) if(*(resp+1) == 0x6F){
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard); // decode the 6F template
decode_ber_tlv_item(resp+1, &inputtag);
// store 84 and A5 tags
emv_decode_field(inputtag.value, inputtag.valuelength, &currentcard);
// decode the A5 tag
if(currentcard.tag_A5_len > 0)
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard);
// copy this result to the DFName // copy this result to the DFName
if(currentcard.tag_84_len == 0) if(currentcard.tag_84_len == 0)
memcpy(currentcard.tag_DFName, currentcard.tag_84, currentcard.tag_84_len); memcpy(currentcard.tag_DFName, currentcard.tag_84, currentcard.tag_84_len);
// decode the BF0C result, assuming 1 directory entry for now // decode the BF0C result, assuming 1 directory entry for now
if(currentcard.tag_BF0C_len !=0){ if(currentcard.tag_BF0C_len !=0){
emv_decode_field(currentcard.tag_BF0C, currentcard.tag_BF0C_len, &currentcard);} emv_decode_field(currentcard.tag_BF0C, currentcard.tag_BF0C_len, &currentcard);}
// retrieve the AID, use the AID to decide what transaction flow to use
if(currentcard.tag_61_len !=0){ // retrieve the AID, use the AID to decide what transaction flow to use
emv_decode_field(currentcard.tag_61, currentcard.tag_61_len, &currentcard);} if(currentcard.tag_61_len !=0)
emv_decode_field(currentcard.tag_61, currentcard.tag_61_len, &currentcard);
}
LED_B_ON();
LED_B_OFF();
break;
}
if(MF_DBGLEVEL >= 2) DbpString("SELECT AID COMPLETED");
LEDsoff();
}
void EMVSelectPPSE()
{
while(true) {
if(!emv_selectPPSE()) {
if(MF_DBGLEVEL >= 1) DbpString("PPSE failed");
break;
}
LED_B_ON();
LED_B_OFF();
break;
} }
if(MF_DBGLEVEL >= 2) if(MF_DBGLEVEL >= 2) DbpString("SELECT PPSE COMPLETED");
DbpString("SELECT AID COMPLETED"); LEDsoff();
} }
int EMVGetProcessingOptions(uint8_t *PDOL, uint8_t PDOLlen, emvtags* inputcard) int EMVGetProcessingOptions(uint8_t *PDOL, uint8_t PDOLlen, emvcard* inputcard)
{ {
uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswer[MAX_FRAME_SIZE];
@ -116,7 +180,7 @@ int EMVGetProcessingOptions(uint8_t *PDOL, uint8_t PDOLlen, emvtags* inputcard)
return 1; return 1;
} }
int EMVGetChallenge(emvtags* inputcard) int EMVGetChallenge(emvcard* inputcard)
{ {
uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswer[MAX_FRAME_SIZE];
// variables // variables
@ -129,7 +193,7 @@ int EMVGetChallenge(emvtags* inputcard)
return 0; return 0;
} }
int EMVGenerateAC(uint8_t refcontrol, emvtags* inputcard) int EMVGenerateAC(uint8_t refcontrol, emvcard* inputcard)
{ {
uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t cdolcommand[MAX_FRAME_SIZE]; uint8_t cdolcommand[MAX_FRAME_SIZE];
@ -162,37 +226,49 @@ int EMVGenerateAC(uint8_t refcontrol, emvtags* inputcard)
//takes in TTQ, amount authorised, unpredicable number and transaction currency code //takes in TTQ, amount authorised, unpredicable number and transaction currency code
int EMV_PaywaveTransaction() int EMV_PaywaveTransaction()
{ {
uint8_t cardMode = 0; uint8_t *resp = BigBuf_malloc(256);
// determine mode of transaction from TTQ tlvtag temptag;
if((currentcard.tag_9F66[0] & 0x40) == 0x40) { //get the current block counter
cardMode = VISA_EMV; //select the AID (Mastercard
EMVSelectAID(currentcard.tag_4F,currentcard.tag_4F_len, &currentcard);
if(resp[1] == 0x6F){ //decode template
decode_ber_tlv_item(&resp[1], &temptag);
//decode 84 and A5 tags
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
//decode the A5 tag
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard);
//decode the BF0C result, assuming 1 directory entry for now
//retrieve the AID
} }
else if((currentcard.tag_9F66[0] & 0x20) == 0x20) {
cardMode = VISA_FDDA;
}
else if((currentcard.tag_9F66[0] & 0x80) == 0x80) {
if((currentcard.tag_9F66[1] & 0x80) == 0x80) { //CVN17
cardMode = VISA_CVN17;
} else {
cardMode = VISA_DCVV;
}
}
EMVSelectAID(currentcard.tag_4F,currentcard.tag_4F_len, &currentcard); // perform second AID command
// get PDOL // get PDOL
uint8_t pdolcommand[20]; //20 byte buffer for pdol data uint8_t pdolcommand[20]; //20 byte buffer for pdol data
uint8_t pdolcommandlen = 0; uint8_t pdolcommandlen = 0;
if(currentcard.tag_9F38_len > 0) { if(currentcard.tag_9F38_len > 0) {
emv_generateDOL(currentcard.tag_9F38, currentcard.tag_9F38_len, &currentcard, pdolcommand, &pdolcommandlen); emv_generateDOL(currentcard.tag_9F38, currentcard.tag_9F38_len, &currentcard, pdolcommand, &pdolcommandlen);
} else {
pdolcommandlen = 0;
} }
Dbhexdump(pdolcommandlen, pdolcommand,false);
if(!EMVGetProcessingOptions(pdolcommand,pdolcommandlen, &currentcard)) { if(!EMVGetProcessingOptions(pdolcommand, pdolcommandlen, &currentcard)) {
if(MF_DBGLEVEL >= 1) Dbprintf("PDOL failed"); if(MF_DBGLEVEL >= 1) Dbprintf("PDOL failed");
return 1; return 1;
} }
if(resp[1] == 0x80) //format 1 data field returned
{
memcpy(currentcard.tag_82, &resp[3],2); //copy AIP
currentcard.tag_94_len = resp[2]-2; //AFL len
memcpy(currentcard.tag_94, &resp[5], currentcard.tag_94_len); //copy AFL
}
else if(resp[1] == 0x77) //format 2 data field returned
{
decode_ber_tlv_item(&resp[1], &temptag);
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
}
else
{
//throw an error
}
Dbprintf("AFL="); Dbprintf("AFL=");
Dbhexdump(currentcard.tag_94_len, currentcard.tag_94,false); Dbhexdump(currentcard.tag_94_len, currentcard.tag_94,false);
Dbprintf("AIP="); Dbprintf("AIP=");
@ -200,63 +276,106 @@ int EMV_PaywaveTransaction()
emv_decodeAIP(currentcard.tag_82); emv_decodeAIP(currentcard.tag_82);
// //
// decode the AFL list and read records // decode the AFL list and read records
uint8_t i = 0;
uint8_t sfi = 0; //record, sfi
uint8_t recordstart = 0; EMVReadRecord(1,1,&currentcard);
uint8_t recordend = 0; Dbhexdump(200, resp, false);
if(currentcard.tag_94_len > 0){ EMVReadRecord(2,1,&currentcard);
while( i < currentcard.tag_94_len){ Dbhexdump(200, resp,false);
sfi = (currentcard.tag_94[i++] & 0xF8) >> 3; EMVReadRecord( 1,2, &currentcard);
recordstart = currentcard.tag_94[i++]; Dbhexdump(200, resp,false);
recordend = currentcard.tag_94[i++]; EMVReadRecord(2,2,&currentcard);
for(int j=recordstart; j<(recordend+1); j++){ Dbhexdump(200, resp,false);
// read records EMVReadRecord( 3,2, &currentcard);
EMVReadRecord(j,sfi, &currentcard); Dbhexdump(200, resp,false);
// while(responsebuffer[0] == 0xF2) { EMVReadRecord( 4,2, &currentcard);
// EMVReadRecord(j,sfi, &currentcard); Dbhexdump(200, resp,false);
// } EMVReadRecord( 1,3, &currentcard);
} Dbhexdump(200, resp,false);
i++; EMVReadRecord(2,3,&currentcard);
} Dbhexdump(200, resp,false);
EMVReadRecord(4,2,&currentcard);
EMVReadRecord( 1,3, &currentcard);
Dbhexdump(200, resp,false);
//DDA supported, so read more records
if((currentcard.tag_82[0] & AIP_CDA_SUPPORTED) == AIP_CDA_SUPPORTED){
EMVReadRecord( 1,4, &currentcard);
EMVReadRecord( 2,4, &currentcard);
} }
else {
EMVReadRecord(1,1,&currentcard);
EMVReadRecord(1,2,&currentcard);
EMVReadRecord(1,3,&currentcard);
EMVReadRecord(2,1,&currentcard);
EMVReadRecord(2,2,&currentcard);
EMVReadRecord(2,3,&currentcard);
EMVReadRecord(3,1,&currentcard);
EMVReadRecord(3,3,&currentcard);
EMVReadRecord(4,2,&currentcard);
}
// EMVGetChallenge(&currentcard);
// memcpy(currentcard.tag_9F4C,&responsebuffer[1],8); // ICC UN
EMVGenerateAC(0x81,&currentcard);
Dbprintf("CARDMODE=%i",cardMode);
emv_decodeCVM(currentcard.tag_8E, currentcard.tag_8E_len);
/* get ICC dynamic data */
//if((currentcard.tag_82[0] & AIP_CDA_SUPPORTED) == AIP_CDA_SUPPORTED)
{
//DDA supported, so perform GENERATE AC
uint8_t cdolcommand[40]; //20 byte buffer for pdol data
uint8_t cdolcommandlen;
//generate the iCC UN
EMVGetChallenge(&currentcard);
memcpy(currentcard.tag_9F37,&resp[1],8); // ICC UN
memcpy(currentcard.tag_9F4C,&resp[1],8); // ICC UN
if(currentcard.tag_8C_len > 0) {
emv_generateDOL(currentcard.tag_8C, currentcard.tag_8C_len, &currentcard, cdolcommand, &cdolcommandlen);
} else {
cdolcommandlen = 0;
}
Dbhexdump(currentcard.tag_8C_len, currentcard.tag_8C,false);
Dbhexdump(cdolcommandlen, cdolcommand,false);
EMVGenerateAC(0x41, &currentcard);
Dbhexdump(100, resp,false);
}
return 0; return 0;
} }
int EMV_PaypassTransaction() int EMV_PaypassTransaction()
{ {
// uint8_t *responsebuffer = emv_get_bigbufptr(); uint8_t *resp = BigBuf_malloc(256);
// tlvtag temptag; //buffer for decoded tags tlvtag temptag; //buffer for decoded tags
// get the current block counter // get the current block counter
// select the AID (Mastercard // select the AID (Mastercard
EMVSelectAID(currentcard.tag_4F,currentcard.tag_4F_len, &currentcard); EMVSelectAID(currentcard.tag_4F,currentcard.tag_4F_len, &currentcard);
if(resp[1] == 0x6F){ //decode template
decode_ber_tlv_item(&resp[1], &temptag);
//decode 84 and A5 tags
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
//decode the A5 tag
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard);
//decode the BF0C result, assuming 1 directory entry for now
//retrieve the AID
}
// get PDOL // get PDOL
uint8_t pdolcommand[20]; // 20 byte buffer for pdol data uint8_t pdolcommand[20]; // 20 byte buffer for pdol data
uint8_t pdolcommandlen = 0; uint8_t pdolcommandlen = 0;
if(currentcard.tag_9F38_len > 0) { if(currentcard.tag_9F38_len > 0) {
emv_generateDOL(currentcard.tag_9F38, currentcard.tag_9F38_len, &currentcard, pdolcommand, &pdolcommandlen); emv_generateDOL(currentcard.tag_9F38, currentcard.tag_9F38_len, &currentcard, pdolcommand, &pdolcommandlen);
} else {
pdolcommandlen = 0;
} }
if(EMVGetProcessingOptions(pdolcommand,pdolcommandlen, &currentcard)) { if(EMVGetProcessingOptions(pdolcommand,pdolcommandlen, &currentcard)) {
if(MF_DBGLEVEL >= 1) Dbprintf("PDOL failed"); if(MF_DBGLEVEL >= 1) Dbprintf("PDOL failed");
return 1; return 1;
} }
if(resp[1] == 0x80) //format 1 data field returned
{
memcpy(currentcard.tag_82, &resp[3],2); //copy AIP
currentcard.tag_94_len = resp[2]-2; //AFL len
memcpy(currentcard.tag_94, &resp[5],currentcard.tag_94_len); //copy AFL
}
else if(resp[1] == 0x77) //format 2 data field returned
{
decode_ber_tlv_item(&resp[1], &temptag);
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
}
else
{
//throw an error
}
Dbprintf("AFL="); Dbprintf("AFL=");
Dbhexdump(currentcard.tag_94_len, currentcard.tag_94,false); Dbhexdump(currentcard.tag_94_len, currentcard.tag_94,false);
Dbprintf("AIP="); Dbprintf("AIP=");
@ -264,57 +383,69 @@ int EMV_PaypassTransaction()
emv_decodeAIP(currentcard.tag_82); emv_decodeAIP(currentcard.tag_82);
// decode the AFL list and read records // decode the AFL list and read records
uint8_t i = 0;
uint8_t sfi = 0; //record, sfi
uint8_t recordstart = 0; EMVReadRecord( 1,1, &currentcard);
uint8_t recordend = 0; EMVReadRecord( 1,2, &currentcard);
EMVReadRecord( 1,3, &currentcard);
while( i< currentcard.tag_94_len){ EMVReadRecord( 2,3, &currentcard);
sfi = (currentcard.tag_94[i++] & 0xF8) >> 3;
recordstart = currentcard.tag_94[i++]; //DDA supported, so read more records
recordend = currentcard.tag_94[i++]; if((currentcard.tag_82[0] & AIP_CDA_SUPPORTED) == AIP_CDA_SUPPORTED){
for(int j=recordstart; j<(recordend+1); j++){ EMVReadRecord( 1,4, &currentcard);
// read records EMVReadRecord( 2,4, &currentcard);
EMVReadRecord(j,sfi, &currentcard);
// while(responsebuffer[0] == 0xF2) {
// EMVReadRecord(j,sfi, &currentcard);
// }
}
i++;
} }
/* get ICC dynamic data */ /* get ICC dynamic data */
if((currentcard.tag_82[0] & AIP_CDA_SUPPORTED) == AIP_CDA_SUPPORTED) if((currentcard.tag_82[0] & AIP_CDA_SUPPORTED) == AIP_CDA_SUPPORTED)
{ {
// DDA supported, so perform GENERATE AC // DDA supported, so perform GENERATE AC
uint8_t cdolcommand[40]; //20 byte buffer for pdol data
uint8_t cdolcommandlen;
// generate the iCC UN // generate the iCC UN
EMVGetChallenge(&currentcard); EMVGetChallenge(&currentcard);
//memcpy(currentcard.tag_9F4C,&responsebuffer[1],8); // ICC UN memcpy(currentcard.tag_9F4C, &resp[1],8); // ICC UN
EMVGenerateAC(0x80,&currentcard);
if(currentcard.tag_8C_len > 0) {
emv_generateDOL(currentcard.tag_8C, currentcard.tag_8C_len, &currentcard, cdolcommand, &cdolcommandlen);
} else {
cdolcommandlen = 0;
}
EMVGenerateAC(0x80, &currentcard);
if(resp[1] == 0x77) //format 2 data field returned
{
decode_ber_tlv_item(&resp[1], &temptag);
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
}
// generate AC2 // generate AC2
// if(currentcard.tag_8D_len > 0) { if(currentcard.tag_8D_len > 0) {
// emv_generateDOL(currentcard.tag_8D, currentcard.tag_8D_len, &currentcard, cdolcommand, &cdolcommandlen); } emv_generateDOL(currentcard.tag_8D, currentcard.tag_8D_len, &currentcard, cdolcommand, &cdolcommandlen); }
// else{ else{
// //cdolcommand = NULL; //cdol val is null //cdolcommand = NULL; //cdol val is null
// cdolcommandlen = 0; cdolcommandlen = 0;
// } }
// emv_generateAC(0x80, cdolcommand,cdolcommandlen, &currentcard);
EMVGenerateAC(0x80, &currentcard);
// if(responsebuffer[1] == 0x77) //format 2 data field returned if(resp[1] == 0x77) //format 2 data field returned
// { {
// decode_ber_tlv_item(&responsebuffer[1], &temptag); decode_ber_tlv_item(&resp[1], &temptag);
// emv_decode_field(temptag.value, temptag.valuelength, &currentcard); emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
// } }
} }
// generate cryptographic checksum // generate cryptographic checksum
// uint8_t udol[4] = {0x00,0x00,0x00,0x00}; uint8_t udol[4] = {0x00,0x00,0x00,0x00};
// emv_computecryptogram(udol, sizeof(udol));
// if(responsebuffer[1] == 0x77) //format 2 data field returned emv_computecryptogram(udol, sizeof(udol), resp);
// {
// decode_ber_tlv_item(&responsebuffer[1], &temptag); if(resp[1] == 0x77) //format 2 data field returned
// emv_decode_field(temptag.value, temptag.valuelength, &currentcard); {
// } decode_ber_tlv_item(&resp[1], &temptag);
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
}
return 0; return 0;
} }
@ -329,6 +460,30 @@ void EMVTransaction()
clear_trace(); clear_trace();
set_tracing(TRUE); set_tracing(TRUE);
uint8_t *resp = BigBuf_malloc(256);
//variables
tlvtag temptag; //used to buffer decoded tag valuesd
//initialize the emv card structure
//extern emvcard currentcard;
memset(&currentcard, 0x00, sizeof(currentcard)); //set all to zeros
memcpy(currentcard.tag_9F66,"\xD7\x20\xC0\x00",4);
memcpy(currentcard.tag_9F02,"\x00\x00\x00\x00\x00\x20",6); //20 dollars
memcpy(currentcard.tag_9F37, "\x01\x02\x03\x04", 4); //UN
memcpy(currentcard.tag_5F2A, "\x00\x36",2); //currency code
//CDOL stuff
memcpy(currentcard.tag_9F03,"\x00\x00\x00\x00\x00\x00",6);
memcpy(currentcard.tag_9F1A,"\x00\x36",2); //country code
memcpy(currentcard.tag_95,"\x00\x00\x00\x00\x00",5); //TVR
memcpy(currentcard.tag_9A,"\x14\x04\x01",3); //date
memcpy(currentcard.tag_9C,"\x00",1); //processingcode;
memcpy(currentcard.tag_9F45, "\x00\x00", 2); //Data Authentication Code
memset(currentcard.tag_9F4C,0x00,8); // ICC UN
memcpy(currentcard.tag_9F35,"\x12",1);
memcpy(currentcard.tag_9F34,"\x3F\x00\x00", 3); //CVM
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
@ -340,10 +495,21 @@ void EMVTransaction()
if(MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); if(MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break; break;
} }
//selectPPSE EMVSelectPPSE();
EMVSelectAID((uint8_t *)DF_PSE, 14, &currentcard); //hard coded len
//get response //get response
if (resp[1] == 0x6F){ //decode template
decode_ber_tlv_item(&resp[1], &temptag);
//decode 84 and A5 tags
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
//decode the A5 tag
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard);
//decode the BF0C result, assuming 1 directory entry for now
if(currentcard.tag_BF0C_len !=0){
emv_decode_field(currentcard.tag_BF0C, currentcard.tag_BF0C_len, &currentcard);}
//retrieve the AID, use the AID to decide what transaction flow to use
if(currentcard.tag_61_len !=0){
emv_decode_field(currentcard.tag_61, currentcard.tag_61_len, &currentcard);}
}
if (!memcmp(currentcard.tag_4F, AID_MASTERCARD, sizeof(AID_MASTERCARD))){ if (!memcmp(currentcard.tag_4F, AID_MASTERCARD, sizeof(AID_MASTERCARD))){
Dbprintf("Mastercard Paypass Card Detected"); Dbprintf("Mastercard Paypass Card Detected");
EMV_PaypassTransaction(); EMV_PaypassTransaction();
@ -353,6 +519,10 @@ void EMVTransaction()
EMV_PaywaveTransaction(); EMV_PaywaveTransaction();
} }
//TODO: add other card schemes like AMEX, JCB, China Unionpay etc //TODO: add other card schemes like AMEX, JCB, China Unionpay etc
LED_B_ON();
//output the sensitive data
cmd_send(CMD_ACK, 0, 0,0,resp,100);
LED_B_OFF();
break; break;
} }
if (MF_DBGLEVEL >= 2) DbpString("EMV TRANSACTION FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("EMV TRANSACTION FINISHED");
@ -364,6 +534,117 @@ void EMVTransaction()
void EMVdumpcard(void){ void EMVdumpcard(void){
dumpCard(&currentcard); dumpCard(&currentcard);
} }
//EMV clone a card - read up to the max SFI and max records for that SFI
void EMVClone(uint8_t maxsfi, uint8_t maxrecord)
{
//params
uint8_t uid[10];
uint32_t cuid;
uint8_t *resp = BigBuf_malloc(256);
iso14a_card_select_t hi14a_card; //card select values
//variables
tlvtag temptag; //used to buffer decoded tag valuesd
memset(&currentcard, 0x00, sizeof(currentcard)); //set all to zeros
//memcpy(currentcard.tag_9F66,"\x20\x00\x00\x00",4);
memcpy(currentcard.tag_9F66,"\xD7\x20\xC0\x00",4);
//memcpy(currentcard.tag_9F66,"\xC0\x00\x00\x00",2);
memcpy(currentcard.tag_9F02,"\x00\x00\x00\x00\x00\x20",6); //20 dollars
memcpy(currentcard.tag_9F37, "\x01\x02\x03\x04", 4); //UN
memcpy(currentcard.tag_5F2A, "\x00\x36",2); //currency code
//CDOL stuff
//memcpy(currentcard.tag_9F02,"\x00\x00\x00\x00\x00\x20",6);
memcpy(currentcard.tag_9F03,"\x00\x00\x00\x00\x00\x00",6);
memcpy(currentcard.tag_9F1A,"\x00\x36",2); //country code
memcpy(currentcard.tag_95,"\x00\x00\x00\x00\x00",5); //TVR
//memcpy(currentcard.tag_5F2A,"\x00\x36",2);
memcpy(currentcard.tag_9A,"\x14\x04x01",3); //date
memcpy(currentcard.tag_9C,"\x00",1); //processingcode;
memcpy(currentcard.tag_9F45, "\x00\x00", 2); //Data Authentication Code
memset(currentcard.tag_9F4C,0x00,8); // ICC UN
memcpy(currentcard.tag_9F35,"\x12",1);
memcpy(currentcard.tag_9F34,"\x3F\x00\x00", 3); //CVM
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
while(true) {
if(!iso14443a_select_card(uid, &hi14a_card, &cuid, true, 0)) {
if(MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break;
}
//copy UID and ATQA SAK and ATS values
memcpy(currentcard.UID, hi14a_card.uid, hi14a_card.uidlen);
currentcard.UID_len = hi14a_card.uidlen;
memcpy(currentcard.ATQA, hi14a_card.atqa, 2);
currentcard.SAK = (uint8_t)hi14a_card.sak;
memcpy(currentcard.ATS, hi14a_card.ats, hi14a_card.ats_len);
currentcard.ATS_len = hi14a_card.ats_len;
if(MF_DBGLEVEL >= 1){
Dbprintf("UID=");
Dbhexdump(currentcard.UID_len, currentcard.UID, false);
Dbprintf("ATQA=");
Dbhexdump(2, currentcard.ATQA,false);
Dbprintf("SAK=");
Dbhexdump(1, &currentcard.SAK,false);
Dbprintf("ATS=");
Dbhexdump(currentcard.ATS_len, currentcard.ATS,false);
}
EMVSelectPPSE();
//get response
if(resp[1] == 0x6F){ //decode template
decode_ber_tlv_item(&resp[1], &temptag);
//decode 84 and A5 tags
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
//decode the A5 tag
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard);
//decode the BF0C result, assuming 1 directory entry for now
if(currentcard.tag_BF0C_len !=0){
emv_decode_field(currentcard.tag_BF0C, currentcard.tag_BF0C_len, &currentcard);}
//retrieve the AID, use the AID to decide what transaction flow to use
if(currentcard.tag_61_len !=0){
emv_decode_field(currentcard.tag_61, currentcard.tag_61_len, &currentcard);}
}
//perform AID selection
EMVSelectAID(currentcard.tag_4F,currentcard.tag_4F_len, &currentcard);
if(resp[1] == 0x6F){ //decode template
decode_ber_tlv_item(&resp[1], &temptag);
//decode 84 and A5 tags
emv_decode_field(temptag.value, temptag.valuelength, &currentcard);
//decode the A5 tag
emv_decode_field(currentcard.tag_A5, currentcard.tag_A5_len, &currentcard);
//decode the BF0C result, assuming 1 directory entry for now
}
//decode the AFL list and read records
//scan all card records
Dbprintf("Reading %u SFIs and %u records...", maxsfi, maxrecord);
for(uint8_t sfi = 1; sfi < maxsfi; sfi++){ //all possible SFI values
for(uint8_t record = 1; record < maxrecord; record++){
EMVReadRecord(record,sfi, &currentcard);
if(resp[1] == 0x70){
Dbprintf("Record Found! SFI=%u RECORD=%u", sfi, record);
}
}
}
Dbprintf("Reading finished");
LED_B_ON();
//output the sensitive data
cmd_send(CMD_ACK, 0, 0,0,resp,100);
LED_B_OFF();
break;
}
if(MF_DBGLEVEL >= 2) DbpString("EMV TRANSACTION FINISHED");
//finish up
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
//SIMULATOR CODE //SIMULATOR CODE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -474,8 +755,8 @@ void SimulateEMVcard()
// Allocate 512 bytes for the dynamic modulation, created when the reader queries for it // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it
// Such a response is less time critical, so we can prepare them on the fly // Such a response is less time critical, so we can prepare them on the fly
#define DYNAMIC_RESPONSE_BUFFER_SIZE 256 //max frame size #define DYNAMIC_RESPONSE_BUFFER_SIZE 64
#define DYNAMIC_MODULATION_BUFFER_SIZE 2 + 9*DYNAMIC_RESPONSE_BUFFER_SIZE //(start and stop bit, 8 bit packet with 1 bit parity #define DYNAMIC_MODULATION_BUFFER_SIZE 512
//uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE]; //uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE];
//uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE]; //uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE];
@ -698,25 +979,26 @@ void SimulateEMVcard()
if (p_response != NULL) { if (p_response != NULL) {
EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n, receivedCmd[0] == 0x52); EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n, receivedCmd[0] == 0x52);
// do the tracing for the previous reader request and this tag answer: // do the tracing for the previous reader request and this tag answer:
uint8_t par[MAX_PARITY_SIZE] = {0x00};
GetParity(p_response->response, p_response->response_n, par);
EmLogTrace(Uart.output, // EmLogTrace(Uart.output,
Uart.len, // Uart.len,
Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, // Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG,
Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, // Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG,
Uart.parity, // Uart.parity,
p_response->response, // p_response->response,
p_response->response_n, // p_response->response_n,
LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, // LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG,
(LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, // (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG,
par); // par);
}
if (!tracing) {
Dbprintf("Trace Full. Simulation stopped.");
break;
} }
// if (!tracing) {
// Dbprintf("Trace Full. Simulation stopped.");
// break;
// }
} }
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd); Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
@ -725,3 +1007,108 @@ void SimulateEMVcard()
*/ */
} }
//-----------------------------------------------------------------------------
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
void EMVFuzz_RATS(uint8_t ratslen, uint8_t* RATS)
{
int len;
uint8_t sak = 0x28;
//copy input rats into a buffer
uint8_t ratscmd[ratslen+2];
memcpy(ratscmd, RATS, ratslen);
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
uint8_t atqa[2] = {0x04, 0x00};
// The second response contains the (mandatory) first 24 bits of the UID
uint8_t uid0[5] = {0x12,0x34,0x56,0x78,0x9A};
// Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID.
uid0[4] = uid0[0] ^ uid0[1] ^ uid0[2] ^ uid0[3];
// Prepare the mandatory SAK (for 4 and 7 byte UID)
uint8_t sakresponse[3];
sakresponse[0] = sak;
ComputeCrc14443(CRC_14443_A, sakresponse, 1, &sakresponse[1], &sakresponse[2]);
// Prepare the optional second SAK (for 7 byte UID), drop the cascade bit
uint8_t ACK1[] = {0xa3,0x6f,0xc6}; //ACK packets
uint8_t ACK2[] = {0xa2,0x00,0x00};
AppendCrc14443a(ACK2, 1);
AppendCrc14443a(ratscmd, sizeof(ratscmd)-2);
//handle the PPS selection
uint8_t PPSR[3] = {0xD0,0x00,0x00};
AppendCrc14443a(PPSR, 1);
//#define TAG_RESPONSE_COUNT 9
tag_response_info_t responses[7] = {
{ .response = atqa, .response_n = sizeof(atqa) }, // Answer to request - respond with card type
{ .response = uid0, .response_n = sizeof(uid0) }, // Anticollision cascade1 - respond with uid
{ .response = sakresponse, .response_n = sizeof(sakresponse) }, // Acknowledge select - cascade 1
{ .response = ratscmd, .response_n = sizeof(ratscmd) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = ACK1, .response_n = sizeof(ACK1) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = ACK2, .response_n = sizeof(ACK2) }, // dummy ATS (pseudo-ATR), answer to RATS
{ .response = PPSR, .response_n = sizeof(PPSR) }, // dummy ATS (pseudo-ATR), answer to RATS
};
// Reset the offset pointer of the free buffer
//reset_free_buffer();
// Prepare the responses of the anticollision phase
// there will be not enough time to do this at the moment the reader sends it REQA
for (size_t i=0; i<7; i++) {
prepare_allocated_tag_modulation(&responses[i]);
}
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
// To control where we are in the protocol
int order;
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
tag_response_info_t* p_response;
LED_C_ON();
// Clean receive command buffer
for(;;){
if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)){
break;
}
p_response = NULL;
if ((receivedCmd[0] == 0x26) || (receivedCmd[0] == 0x52)) { // Received a REQUEST
p_response = &responses[0]; order = 1;
}
if (receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) { // Received request for UID (cascade 1)
p_response = &responses[1]; order = 2; //send the UID
}
if (receivedCmd[1] == 0x70 && receivedCmd[0] == 0x93) { // Received a SELECT (cascade 1)
p_response = &responses[2]; order = 3; //send the SAK
}
if (receivedCmd[0] == 0xD0) { // Received a PPS request
p_response = &responses[6]; order = 70;
}
if (receivedCmd[0] == 0xE0) { // Received a RATS request
p_response = &responses[3]; order = 70;
EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n, (receivedCmd[0] == 0x52) || (receivedCmd[0] == 0x26));
break;
}
if (p_response != NULL){
EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n, (receivedCmd[0] == 0x52) || (receivedCmd[0] == 0x26));
} else {
break;
}
}
if (order && (MF_DBGLEVEL >= 2)) DbpString("just using order vars");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_C_OFF();
return;
}

View file

@ -18,7 +18,6 @@
#include "string.h" #include "string.h"
#include "iso14443crc.h" #include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "mifare.h"
#include "emvcmd.h" #include "emvcmd.h"
#include "emvutil.h" #include "emvutil.h"
#include "emvdataels.h" #include "emvdataels.h"
@ -31,4 +30,5 @@
#define MASTERCARD_MSR 0 #define MASTERCARD_MSR 0
#define MASTERCARD_MCHIP 1 #define MASTERCARD_MCHIP 1
#endif #endif

View file

@ -16,7 +16,7 @@
//util functions //util functions
//print detected tag name over the serial link //print detected tag name over the serial link
int emv_printtag(uint8_t* selected_tag, emvtags* inputcard, uint8_t* outputstring, uint8_t* outputlen) int emv_printtag(uint8_t* selected_tag, emvcard* inputcard, uint8_t* outputstring, uint8_t* outputlen)
{ {
//search tag list and print the match //search tag list and print the match
//get the value of the tag //get the value of the tag
@ -36,8 +36,8 @@ int emv_printtag(uint8_t* selected_tag, emvtags* inputcard, uint8_t* outputstrin
return 0; return 0;
} }
//returns the value of the emv tag in the supplied emvtags structure //returns the value of the emv tag in the supplied emvcard structure
int emv_lookuptag(uint8_t* tag, emvtags *currentcard, uint8_t* outputval, uint8_t* outputvallen) int emv_lookuptag(uint8_t* tag, emvcard *currentcard, uint8_t* outputval, uint8_t* outputvallen)
{ {
//loop through tag and return the appropriate value //loop through tag and return the appropriate value
uint8_t returnedtag[255]; uint8_t returnedtag[255];
@ -367,7 +367,7 @@ exitfunction: //goto label to exit search quickly once found
} }
//function to //function to
int emv_settag(uint32_t tag, uint8_t *datain, emvtags *currentcard){ int emv_settag(uint32_t tag, uint8_t *datain, emvcard *currentcard){
char binarydata[255] = {0}; char binarydata[255] = {0};
/* /*
@ -807,13 +807,13 @@ int emv_settag(uint32_t tag, uint8_t *datain, emvtags *currentcard){
} }
/* generates an emv template based off tag values supplied */ /* generates an emv template based off tag values supplied */
int emv_generatetemplate(uint8_t* templateval,emvtags* currentcard, uint8_t* returnedval, uint8_t* returnedlen,uint8_t numtags, ...) int emv_generatetemplate(uint8_t* templateval,emvcard* currentcard, uint8_t* returnedval, uint8_t* returnedlen,uint8_t numtags, ...)
{ {
va_list arguments; va_list arguments;
uint8_t* currenttag; //value of the current tag uint8_t* currenttag; //value of the current tag
uint8_t tagval[255]; //buffer to hold the extracted tag value uint8_t tagval[256]; //buffer to hold the extracted tag value
uint8_t taglen = 0; //extracted tag length uint8_t taglen = 0; //extracted tag length
uint8_t bufferval[255]; uint8_t bufferval[256];
uint8_t counter = 0; uint8_t counter = 0;
uint32_t encodedlen = 0; uint32_t encodedlen = 0;
va_start(arguments, numtags); va_start(arguments, numtags);
@ -830,7 +830,7 @@ int emv_generatetemplate(uint8_t* templateval,emvtags* currentcard, uint8_t* ret
} }
//generate a valid pdol list //generate a valid pdol list
int emv_generateDOL(uint8_t* DOL, uint8_t DOLlen,emvtags* currentcard,uint8_t* DOLoutput, uint8_t* DOLoutputlen) int emv_generateDOL(uint8_t* DOL, uint8_t DOLlen,emvcard* currentcard,uint8_t* DOLoutput, uint8_t* DOLoutputlen)
{ {
if(!DOL || !currentcard || !DOLoutput) // null pointer checks if(!DOL || !currentcard || !DOLoutput) // null pointer checks
return 1; return 1;
@ -866,7 +866,7 @@ int emv_generateDOL(uint8_t* DOL, uint8_t DOLlen,emvtags* currentcard,uint8_t* D
//decode the tag inputted and fill in the supplied structure. clean up the cleanup_passpass function //decode the tag inputted and fill in the supplied structure. clean up the cleanup_passpass function
int emv_emvtags_decode_tag(tlvtag* inputtag, emvtags* currentcard) int emv_emvtags_decode_tag(tlvtag* inputtag, emvcard* currentcard)
{ {
if(!inputtag || !currentcard) { if(!inputtag || !currentcard) {
return 1; return 1;
@ -1324,7 +1324,7 @@ else
return 0; return 0;
} }
int emv_decode_field(uint8_t* inputfield,uint16_t inputlength, emvtags *result) int emv_decode_field(uint8_t* inputfield,uint16_t inputlength, emvcard *result)
{ {
uint16_t lengthcounter=0; uint16_t lengthcounter=0;
tlvtag newtag; tlvtag newtag;
@ -1337,7 +1337,7 @@ int emv_decode_field(uint8_t* inputfield,uint16_t inputlength, emvtags *result)
{ {
//decode the tlv tag //decode the tlv tag
decode_ber_tlv_item((inputfield+lengthcounter),&newtag); decode_ber_tlv_item((inputfield+lengthcounter),&newtag);
//write the emvtags strucutre //write the emvcard strucutre
emv_emvtags_decode_tag(&newtag,result); emv_emvtags_decode_tag(&newtag,result);
//move to next value and decode //move to next value and decode
lengthcounter += newtag.fieldlength-1; lengthcounter += newtag.fieldlength-1;
@ -1503,18 +1503,85 @@ int emv_decodeCVM(uint8_t* CVM, uint8_t CVMlen)
} }
return 0; return 0;
} }
//simulate a emvcard card
//input is a structure containing values to simulate
//clones an EMV card
void emvsnoop() {
//states
int cardSTATE = EMVEMUL_NOFIELD;
int vHf = 0;
int res;
uint16_t len = 0;
uint8_t* receivedCmd = BigBuf_malloc(MAX_MIFARE_FRAME_SIZE);
uint8_t par[MAX_MIFARE_PARITY_SIZE] = {0x00};
uint8_t rATQA[] = {0x04,0x00};
uint8_t rUIDBCC[] = {0x8F,0x2F,0x27,0xE1, 0x66};
uint8_t rSAK[] = {0x28, 0xB4, 0xFC};
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
bool finished = FALSE;
while (!BUTTON_PRESS() && !finished){
WDT_HIT();
//find reader field
if(cardSTATE == EMVEMUL_NOFIELD){
vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
if(vHf > EMV_MINFIELDV){
cardSTATE_TO_IDLE();
LED_A_ON();
}
}
if(cardSTATE == EMVEMUL_NOFIELD) continue;
//get data
res = EmGetCmd(receivedCmd, &len, par);
if(res == 2) { //field is off
cardSTATE = EMVEMUL_NOFIELD;
LEDsoff();
continue;
}
else if(res==1){
break; // button press
}
if(len==1 && ((receivedCmd[0] == 0x26 && cardSTATE != EMVEMUL_HALTED) || receivedCmd[0] == 0x52)){
EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
cardSTATE = EMVEMUL_SELECT1;
continue;
}
switch(cardSTATE){
case EMVEMUL_NOFIELD:
case EMVEMUL_HALTED:
case EMVEMUL_IDLE:{
break;
}
case EMVEMUL_SELECT1:{
//select all
if(len==2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC, sizeof(rUIDBCC));
break;
}
if(len==2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC, 4) == 0)) {
EmSendCmd(rSAK, sizeof(rSAK));
break;
}
}
}
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
//ICEMAN: move to client //ICEMAN: move to client
//dump the current card to the console //dump the current card to the console
void dumpCard(emvtags* currentcard){ void dumpCard(emvcard* currentcard){
DUMP(currentcard->ATQA); DUMP(currentcard->ATQA);
Dbhexdump(sizeof(currentcard->ATQA), currentcard->ATQA, false); Dbhexdump(sizeof(currentcard->ATQA), currentcard->ATQA, false);
DUMP(currentcard->UID); DUMP(currentcard->UID);
Dbhexdump(currentcard->UID_len, currentcard->UID, false); Dbhexdump(currentcard->UID_len, currentcard->UID, false);
DUMP(currentcard->SAK1); DUMP(currentcard->SAK);
Dbhexdump(1, &currentcard->SAK1, false); Dbhexdump(1, &currentcard->SAK, false);
DUMP(currentcard->SAK2);
Dbhexdump(1, &currentcard->SAK2, false);
DUMP(currentcard->ATS); DUMP(currentcard->ATS);
Dbhexdump(currentcard->ATS_len, currentcard->ATS, false); Dbhexdump(currentcard->ATS_len, currentcard->ATS, false);
DUMP(currentcard->tag_4F); DUMP(currentcard->tag_4F);

View file

@ -48,8 +48,7 @@
int emv_select(uint8_t* AID, uint8_t AID_len, void* data); int emv_select(uint8_t* AID, uint8_t AID_len, void* data);
int emv_selectPPSE(); int emv_selectPPSE();
int emv_readrecord(uint8_t recordnumber, uint8_t sfi, void* data); int emv_readrecord(uint8_t recordnumber, uint8_t sfi, void* data);
int emv_getprocessingoptions(uint8_t* pdol, uint8_t pdol_len, void* data int emv_getprocessingoptions(uint8_t* pdol, uint8_t pdol_len, void* data);
);
int emv_computecryptogram(uint8_t* UDOL, uint8_t UDOL_len, void *data); int emv_computecryptogram(uint8_t* UDOL, uint8_t UDOL_len, void *data);
//return 8 8byte ICC random number. //return 8 8byte ICC random number.
int emv_getchallenge(void *data); int emv_getchallenge(void *data);
@ -59,18 +58,21 @@ int emv_decodeAFL(uint8_t* AFL, uint8_t AFLlen);
int emv_decodeAIP(uint8_t* AIP); int emv_decodeAIP(uint8_t* AIP);
int emv_decodeCVM(uint8_t* CVM, uint8_t CVMlen); int emv_decodeCVM(uint8_t* CVM, uint8_t CVMlen);
//emulator
void EMVsim();
//utils //utils
int emv_printtag(uint8_t* selected_tag,emvtags* inputcard, uint8_t* outputstring, uint8_t* outputlen); int emv_printtag(uint8_t* selected_tag, emvcard* inputcard, uint8_t* outputstring, uint8_t* outputlen);
int emv_decode_field(uint8_t* inputfield,uint16_t inputlength, emvtags *result); int emv_decode_field(uint8_t* inputfield,uint16_t inputlength, emvcard *result);
int emv_emvtags_decode_tag(tlvtag* inputtag, emvtags* currentcard); int emv_emvtags_decode_tag(tlvtag* inputtag, emvcard* currentcard);
//look up a tag in the current structure //look up a tag in the current structure
int emv_lookuptag(uint8_t* tag, emvtags* currentcard, uint8_t* outputval, uint8_t* outputvallen); int emv_lookuptag(uint8_t* tag, emvcard* currentcard, uint8_t* outputval, uint8_t* outputvallen);
//set a tag from external impurt //set a tag from external impurt
int emv_settag(uint32_t tag, uint8_t *datain, emvtags *currentcard) ; int emv_settag(uint32_t tag, uint8_t *datain, emvcard *currentcard) ;
void dumpCard(emvtags* currentcard); void dumpCard(emvcard* currentcard);
//generate a valid PDOL list from the returned card value, used in get processing options //generate a valid PDOL list from the returned card value, used in get processing options
int emv_generateDOL(uint8_t* DOL, uint8_t DOLlen,emvtags* currentcard, uint8_t* DOLoutput, uint8_t* DOLoutputlen); int emv_generateDOL(uint8_t* DOL, uint8_t DOLlen,emvcard* currentcard, uint8_t* DOLoutput, uint8_t* DOLoutputlen);
int emv_generatetemplate(uint8_t* templateval,emvtags* currentcard, uint8_t* returnedval, uint8_t* returnedlen, uint8_t numtags, ...); int emv_generatetemplate(uint8_t* templateval,emvcard* currentcard, uint8_t* returnedval, uint8_t* returnedlen, uint8_t numtags, ...);
#endif #endif

View file

@ -759,7 +759,7 @@ static void Code4bitAnswerAsTag(uint8_t cmd) {
// Stop when button is pressed // Stop when button is pressed
// Or return TRUE when command is captured // Or return TRUE when command is captured
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) { int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) {
// Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
// only, since we are receiving, not transmitting). // only, since we are receiving, not transmitting).
// Signal field is off with the appropriate LED // Signal field is off with the appropriate LED
@ -1361,40 +1361,6 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) {
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
LED_A_OFF(); LED_A_OFF();
/*
if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) {
for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
if (ar_nr_collected[i] == 2) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
ar_nr_resp[i].cuid, //UID
ar_nr_resp[i].nonce, //NT
ar_nr_resp[i].nr, //NR1
ar_nr_resp[i].ar, //AR1
ar_nr_resp[i].nr2, //NR2
ar_nr_resp[i].ar2 //AR2
);
}
}
for ( uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT*2; i++) {
if (ar_nr_collected[i] == 2) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
ar_nr_resp[i].cuid, //UID
ar_nr_resp[i].nonce, //NT
ar_nr_resp[i].nr, //NR1
ar_nr_resp[i].ar, //AR1
ar_nr_resp[i].nonce2,//NT2
ar_nr_resp[i].nr2, //NR2
ar_nr_resp[i].ar2 //AR2
);
}
}
}
*/
if (MF_DBGLEVEL >= 4){ if (MF_DBGLEVEL >= 4){
Dbprintf("-[ Wake ups after halt [%d]", happened); Dbprintf("-[ Wake ups after halt [%d]", happened);
Dbprintf("-[ Messages after halt [%d]", happened2); Dbprintf("-[ Messages after halt [%d]", happened2);
@ -1567,7 +1533,7 @@ void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *p
// Stop when button is pressed (return 1) or field was gone (return 2) // Stop when button is pressed (return 1) or field was gone (return 2)
// Or return 0 when command is captured // Or return 0 when command is captured
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) {
*len = 0; *len = 0;
uint32_t timer = 0, vtime = 0; uint32_t timer = 0, vtime = 0;

View file

@ -82,13 +82,6 @@ typedef struct {
uint8_t *parity; uint8_t *parity;
} tUart; } tUart;
typedef struct {
uint8_t* response;
size_t response_n;
uint8_t* modulation;
size_t modulation_n;
uint32_t ProxToAirDuration;
} tag_response_info_t;
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
extern void AppendCrc14443a(uint8_t *data, int len); extern void AppendCrc14443a(uint8_t *data, int len);
@ -109,6 +102,7 @@ int EmSend4bit(uint8_t resp);
int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par); int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par);
int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded); int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded);
extern int EmSendCmd(uint8_t *resp, uint16_t respLen); extern int EmSendCmd(uint8_t *resp, uint16_t respLen);
extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity);
int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);

View file

@ -23,10 +23,8 @@ extern "C" {
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "iso14443crc.h" #include "iso14443crc.h"
#include "mifare.h" #include "mifare.h"
#include "protocols.h" #include "protocols.h"
//#include "mifareutil.h"
extern void AppendCrc14443b(uint8_t *data, int len); extern void AppendCrc14443b(uint8_t *data, int len);
void SendRawCommand14443B_Ex(UsbCommand *c); void SendRawCommand14443B_Ex(UsbCommand *c);

View file

@ -12,6 +12,10 @@
#ifndef __COMMON_H #ifndef __COMMON_H
#define __COMMON_H #define __COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -20,7 +24,7 @@ typedef unsigned char byte_t;
// debug // debug
// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode // 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode
#define MF_DBG_NONE 0 #define MF_DBG_NONE 0
#define MF_DBG_ERROR 1 #define MF_DBG_ERROR 1
#define MF_DBG_ALL 2 #define MF_DBG_ALL 2
#define MF_DBG_EXTENDED 4 #define MF_DBG_EXTENDED 4
@ -29,7 +33,6 @@ extern int MF_DBGLEVEL;
// reader voltage field detector // reader voltage field detector
#define MF_MINFIELDV 4000 #define MF_MINFIELDV 4000
#ifndef MIN #ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b)) # define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif #endif
@ -42,4 +45,10 @@ extern int MF_DBGLEVEL;
# define ABS(a) ( ((a)<0) ? -(a) : (a) ) # define ABS(a) ( ((a)<0) ? -(a) : (a) )
#endif #endif
#define RAMFUNC __attribute((long_call, section(".ramfunc"))) #define RAMFUNC __attribute((long_call, section(".ramfunc")))
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -37,7 +37,13 @@ typedef enum ISO14A_COMMAND {
ISO14A_TOPAZMODE = (1 << 8) ISO14A_TOPAZMODE = (1 << 8)
} iso14a_command_t; } iso14a_command_t;
typedef struct {
uint8_t* response;
size_t response_n;
uint8_t* modulation;
size_t modulation_n;
uint32_t ProxToAirDuration;
} tag_response_info_t;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ISO 14443B // ISO 14443B
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------