//////////////////////////////////////////////// //MifareTest Card explorer V.1.00 //Programma realizzato da Francesco Germinara //www.germinara.it 2005 FREEWARE //info@germinara.it //http://www.germinara.it //programmatore PINEROLO TORINO ITALIA //Data realizzazione: 19/luglio/2005 //////////////////////////////////////////////// // // Thanks to Stoyan Yordanov for the help and the technical support. //////////////////////////////////////////////////////////////////////// // MIFARETestView.h : interface of the CMIFARETestView class // #include "StdAfx.h" #include ".\cfgmifareobj.h" //Standard constructor for CFGMifareCard object CFGMifareCard::CFGMifareCard(){ ClearData(); } //Clear data structure void CFGMifareCard::ClearData(){ strCardType="Unknow"; nMethodType=UNKNOW_METHOD; strCardUID=""; memset(&cardInfo,0x00,sizeof(CARD_DATA)); SetKeyA(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF); //Default Key A value SetKeyB(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF); //Default Key B value } //Return UID as string object CString CFGMifareCard::Uid(){ return strCardUID; } //Set Key A value void CFGMifareCard::SetKeyA(unsigned char byte0,unsigned char byte1,unsigned char byte2,unsigned char byte3,unsigned char byte4,unsigned char byte5){ KeyA[0]=byte0; KeyA[1]=byte1; KeyA[2]=byte2; KeyA[3]=byte3; KeyA[4]=byte4; KeyA[5]=byte5; } //set KeyA as CString void CFGMifareCard::SetKeyA(CString byte0,CString byte1,CString byte2,CString byte3,CString byte4,CString byte5){ KeyA[0]=atoh(byte0); KeyA[1]=atoh(byte1); KeyA[2]=atoh(byte2); KeyA[3]=atoh(byte3); KeyA[4]=atoh(byte4); KeyA[5]=atoh(byte5); } //set KeyA as CString void CFGMifareCard::SetKeyB(CString byte0,CString byte1,CString byte2,CString byte3,CString byte4,CString byte5){ KeyB[0]=atoh(byte0); KeyB[1]=atoh(byte1); KeyB[2]=atoh(byte2); KeyB[3]=atoh(byte3); KeyB[4]=atoh(byte4); KeyB[5]=atoh(byte5); } //Set Key B value void CFGMifareCard::SetKeyB(unsigned char byte0,unsigned char byte1,unsigned char byte2,unsigned char byte3,unsigned char byte4,unsigned char byte5){ KeyB[0]=byte0; KeyB[1]=byte1; KeyB[2]=byte2; KeyB[3]=byte3; KeyB[4]=byte4; KeyB[5]=byte5; } //get KeyA void CFGMifareCard::GetKeyA(unsigned char &byte0,unsigned char &byte1,unsigned char &byte2,unsigned char &byte3,unsigned char &byte4,unsigned char &byte5){ byte0=KeyA[0]; byte1=KeyA[1]; byte2=KeyA[2]; byte3=KeyA[3]; byte4=KeyA[4]; byte5=KeyA[5]; } //get KeyB void CFGMifareCard::GetKeyB(unsigned char &byte0,unsigned char &byte1,unsigned char &byte2,unsigned char &byte3,unsigned char &byte4,unsigned char &byte5){ byte0=KeyB[0]; byte1=KeyB[1]; byte2=KeyB[2]; byte3=KeyB[3]; byte4=KeyB[4]; byte5=KeyB[5]; } //Return Key A value void CFGMifareCard::GetKeyA(unsigned char key[6]){ memcpy(key,KeyA,6); } //Return Key B value void CFGMifareCard::GetKeyB(unsigned char key[6]){ memcpy(key,KeyB,6); } //Return Key A value as string object CString CFGMifareCard::GetKeyA(){ CString strResult,strTmp; int nIndex=0; strResult=""; for(nIndex=0; nIndex< 6; nIndex++){ strTmp.Format("%0.2X",KeyA[nIndex]); strResult+=strTmp; } return strResult; } //Return Key B value as string object //Return Key A value as string object CString CFGMifareCard::GetKeyB(){ CString strResult,strTmp; int nIndex=0; strResult=""; for(nIndex=0; nIndex< 6; nIndex++){ strTmp.Format("%0.2X",KeyB[nIndex]); strResult+=strTmp; } return strResult; } //Set UID as string object void CFGMifareCard::SetUid(CString CardUID){ strCardUID=CardUID; } //Get the Card Info structure CARD_DATA * CFGMifareCard::GetCardInfo(){ return &cardInfo; } CFGMifareCard::~CFGMifareCard(){ } //Operator Overload bool CFGMifareCard::operator==(CFGMifareCard & obj) { int sts=memcmp((void*)&this->cardInfo.ChipID,(void*)&obj.cardInfo.ChipID,SINGLE_UID_BYTES); if(sts==0) return true; else return false; } CString CFGMifareCard::CardType(){ //Get the Card Type Description return strCardType; } void CFGMifareCard::SetCardType(CString str){ //Set Card Type Description strCardType=str; } //Standard constructor for CFGMifareObj object CFGMifareObj::CFGMifareObj(void) { hSess=NULL; //Session handle nIDGemini2kReader=X501; bIsDebug=TRUE; msgErr=""; nDelayWaitCard=100; nCardsInRF=0; saGemini2kReader.Add(("X501")); //The readers that I have saGemini2kReader.Add("X701"); saMifareCardTypes.Add("MIFARE ultralight"); saMifareCardTypes.Add("MIFARE Standard 1K"); saMifareCardTypes.Add("MIFARE Standard 4K"); saMifareCardTypes.Add("MIFARE DESFire"); //I don't know if the reader can read this type of card //saMifareCardType.Add("MIFARE ProX"); //saMifareCardType.Add("MIFARE SmartMX"); } void CFGMifareObj::SetReaderToUse(int nIndex){ if(nIndex == 0) nIDGemini2kReader=X501; if(nIndex == 1) nIDGemini2kReader=X701; } //For internal Use only void CFGMifareObj::SetDebugMode(bool bSts){ bIsDebug=bSts; } //Set the delay time for loop check of card presence in RF field void CFGMifareObj::SetDelayForWaitCard(int nMilliSec){ nDelayWaitCard=nMilliSec; } //Get the delay time for loop check of card presence in RF field int CFGMifareObj::DelayForWaitCard(){ return nDelayWaitCard; } CFGMifareObj::~CFGMifareObj(void) { ClearData(); saGemini2kReader.RemoveAll(); saMifareCardTypes.RemoveAll(); } //Helper function to display error message if present and if bIsDebug==TRUE void CFGMifareObj::DisplayMsgErr(){ if(bIsDebug) AfxMessageBox(msgErr.TrimRight()); } //Try to open a session and connect to the USB reader bool CFGMifareObj::ConnectToReader(){ //Clean Up old data card ClearData(); SendMessage(AfxGetMainWnd()->m_hWnd,WM_USER+1,(WPARAM)this,nCardsInRF); bool sts=false; int err=0; if(hSess == NULL){ hSess=CreateSession(0); //Create the communication session if(!hSess) msgErr.Format("CFGMifareObj::ConnectToReader -> Error: Can not get session."); else{//Ok, now try to connect the reader on USB_0 err= ConnectReader(hSess,USB_INTERFACE,"USB_0",nIDGemini2kReader); if(err){//Error, release connection msgErr.Format("CFGMifareObj::ConnectToReader ->Cannot connect the reader %s",GetErrorText(err)); ReleaseSession(hSess,0); hSess=NULL; }else{ msgErr.Format("CFGMifareObj::ConnectToReader ->Reader %X connected on USB_0.",nIDGemini2kReader); sts=true; //All work fine } } }else{ msgErr.Format("CFGMifareObj::ConnectToReader ->Reader %X already connected on USB_0.",nIDGemini2kReader); sts=true; //Connection alredy exist. } return sts; } //Disconnect to the USB reader and release session void CFGMifareObj::DisconnectToReader(){ msgErr.Format("CFGMifareObj::DisconnectToReader ->Reader %X disconnected on USB_0.",nIDGemini2kReader); DisconnectReader(hSess); ReleaseSession(hSess,0); hSess=NULL; } //Select Idle Card and register it int CFGMifareObj::SelectAidleCard(){ int sts=0; BOOL cardAlreadyRegistered=FALSE; ChipIDSize = (unsigned char)(sizeof(ChipID)); sts=SelectIdleCard(hSess,ChipID,&ChipIDSize,ATQ,&ATS); if(sts==0){ paCard = new CFGMifareCard(); paCard->ClearData(); FillCFGMifareCardInfo(); cardAlreadyRegistered=SearchCard(paCard); if(!cardAlreadyRegistered){ paCards.Add(paCard); nCardsInRF++; SendMessage(AfxGetMainWnd()->m_hWnd,WM_USER+1,(WPARAM)this,nCardsInRF); }else{ delete paCard; } } return sts; } //Fill Card Info void CFGMifareObj::FillCFGMifareCardInfo(){ CString strTmp; strTmp="Card ID: "; CString strCardUID; strCardUID=""; for(unsigned char i = 0; i < ChipIDSize;i++){ msgErr.Format("%0.2X", ChipID[i]); strCardUID+=msgErr; strTmp+=msgErr; } paCard->SetUid(strCardUID); msgErr.Format("ATQ is %0X%02 %0X%02\n",ATQ[0],ATQ[1]); strTmp+=msgErr; switch(((ATQ[1] << 8)|ATQ[0])) { case 0x0044: strTmp+="Assuming MIFARE ultralight\n"; paCard->GetCardInfo()->BlocksCount = 4; paCard->GetCardInfo()->SectorsCount = 1; paCard->GetCardInfo()->Method = ULTRA_LIGTH_METHOD; paCard->SetCardType("Mifare Ultralight"); break; case 0x004: strTmp+="Assuming MIFARE 1K\n"; paCard->GetCardInfo()->BlocksCount = 64; paCard->GetCardInfo()->SectorsCount = 16; paCard->GetCardInfo()->Method = MIFARE_1K_METHOD; memcpy(paCard->GetCardInfo()->ChipID.Mif_UID,ChipID,SINGLE_UID_BYTES); paCard->SetCardType("Mifare 1K"); break; case 0x0002: strTmp+="Assuming MIFARE 4K\n"; paCard->GetCardInfo()->BlocksCount = 256; paCard->GetCardInfo()->SectorsCount = 40; paCard->GetCardInfo()->Method = MIFARE_4K_METHOD; memcpy(paCard->GetCardInfo()->ChipID.Mif_UID,ChipID,SINGLE_UID_BYTES); paCard->SetCardType("Mifare 4K"); break; case 0x0344: strTmp+="Assuming MIFARE DESFire\n"; paCard->SetCardType("Mifare DESFire"); break; paCard->GetCardInfo()->Method = MIFARE_DES_FIRE_METHOD; default: strTmp+="Assuming non MIFARE\n"; paCard->SetCardType("Non Mifare Card"); break; } msgErr.Format("SAK is %0X%02\n",ATS); strTmp+=msgErr; if(((ATS >> 5) & 1)) { strTmp+="T=CL supported\n"; paCard->GetCardInfo()->Method = T_CL_METHOD; } else strTmp+="T=CL NOT supported\n"; msgErr=strTmp; } //Halt communication with the card void CFGMifareObj::HaltTheCard(){ HaltCard(hSess); } //Return Number of registered card int CFGMifareObj::NumberOfRegisteredCards(){ return nCardsInRF; } //Check if a card was already registered. BOOL CFGMifareObj::SearchCard(CFGMifareCard *pSelectedCard){ int nIndex=0; for(nIndex=0; nIndex < paCards.GetCount(); nIndex++){ if(*pSelectedCard == *(CFGMifareCard *)paCards.GetAt(nIndex)){ return TRUE; } } return FALSE; } //Fill a Tree with card INFO void CFGMifareObj::FillTree(CTreeCtrl& aTree){ HTREEITEM hTRoot,hTItem; int nIndex=0; CString cardInfo; for(nIndex=0; nIndex < paCards.GetCount(); nIndex++){ paCard = (CFGMifareCard *)paCards.GetAt(nIndex); cardInfo.Format("%s - %s",paCard->CardType(),paCard->Uid()); hTRoot = AddOneItem(aTree,(HTREEITEM)NULL,cardInfo, (HTREEITEM)TVI_ROOT, 0,paCard); cardInfo.Format("T=CL is %s Supported",paCard->GetCardInfo()->HasPart4 ? "" : "not"); hTItem=aTree.InsertItem(cardInfo, 1, 1, hTRoot); cardInfo.Format("Block Count %d",paCard->GetCardInfo()->BlocksCount); hTItem=aTree.InsertItem(cardInfo, 1, 1, hTRoot); cardInfo.Format("Sector Count %d",paCard->GetCardInfo()->SectorsCount); hTItem=aTree.InsertItem(cardInfo, 1, 1, hTRoot); aTree.Expand(hTRoot,TVE_EXPAND); CString strMethod; switch(paCard->GetCardInfo()->Method){ case UNKNOW_METHOD: strMethod="Unknow"; break; case ULTRA_LIGTH_METHOD: strMethod="Ultra light"; break; case MIFARE_1K_METHOD: strMethod="Mifare 1K"; break; case MIFARE_4K_METHOD: strMethod="Mifare 4k"; break; case MIFARE_DES_FIRE_METHOD: strMethod="Mifare DesFire"; break; case T_CL_METHOD: strMethod="T=CL"; break; } cardInfo.Format("Method Type %s",strMethod); hTItem=aTree.InsertItem(cardInfo, 1, 1, hTRoot); cardInfo.Format("Key A %s",paCard->GetKeyA()); hTItem=aTree.InsertItem(cardInfo, 1, 1, hTRoot); cardInfo.Format("Key B %s",paCard->GetKeyB()); hTItem=aTree.InsertItem(cardInfo, 1, 1, hTRoot); } } //Add a element to CTreeCtrl HTREEITEM CFGMifareObj::AddOneItem(CTreeCtrl& aTree,HTREEITEM hParent, CString szText, HTREEITEM hInsAfter, int iImage,CFGMifareCard *aCard){ HTREEITEM hItem; TV_ITEM tvI; TV_INSERTSTRUCT tvIns; char str[501]; strcpy(str,szText); tvI.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvI.pszText = str; tvI.cchTextMax = szText.GetLength(); tvI.iImage = iImage; tvI.iSelectedImage = iImage; tvI.lParam = (LPARAM)aCard; tvIns.item = tvI; tvIns.hInsertAfter = hInsAfter; tvIns.hParent = hParent; hItem = aTree.InsertItem(&tvIns); return (hItem); } //Clear all data card void CFGMifareObj::ClearData(){ int nIndex=0; for(nIndex=0; nIndex='0' && strValue.GetAt(0) <='9') hexValue+=(strValue.GetAt(0) - '0') * 16; if(strValue.GetAt(0) >='A' && strValue.GetAt(0) <='F') hexValue+=((strValue.GetAt(0) - 'A')+10) * 16; if(strValue.GetAt(1) >='0' && strValue.GetAt(1) <='9') hexValue+=strValue.GetAt(1) - '0'; if(strValue.GetAt(1) >='A' && strValue.GetAt(1) <='F') hexValue+=(strValue.GetAt(1) - 'A')+10; return (unsigned char) hexValue; } //Read a single Block int CFGMifareObj::ReadBlock(CFGMifareCard *pSelectedCard,int nBlock,int usingKey,unsigned char *BlockData){ int sts=0; if(nBlock >= pSelectedCard->GetCardInfo()->BlocksCount){ msgErr.Format("CFGMifareObj::ReadBlock -> Error: Invalid block number! Max Blocks: %d - Block request to read: %d",pSelectedCard->GetCardInfo()->BlocksCount,nBlock); DisplayMsgErr(); return -1; } if(usingKey != USE_KEY_A && usingKey != USE_KEY_B){ msgErr.Format("CFGMifareObj::ReadBlock -> Error: Invalid Key! Must be USE_KEY_A or USE_KEY_B"); DisplayMsgErr(); return -1; } memset(BlockData,0x00,MIF_BLOCK_SIZE); //Empty data in the buffer MIF_KEY accessKey; accessKey.KeyType=usingKey; if(usingKey == USE_KEY_A){ memcpy(accessKey.KeyValue,pSelectedCard->KeyA,MIF_KEY_VALUE_LEN); }else{ memcpy(accessKey.KeyValue,pSelectedCard->KeyB,MIF_KEY_VALUE_LEN); } sts = MifC_ReadBlockAuth(hSess,&accessKey,&pSelectedCard->cardInfo.ChipID,(unsigned char)nBlock,BlockData); return sts; } //Select a Card int CFGMifareObj::SelectACard(CFGMifareCard *pSelectedCard){ int sts=0x00; int nMaxTimeOut=20; for(;;){ ChipIDSize = (unsigned char)(sizeof(ChipID)); sts=SelectIdleCard(hSess,ChipID,&ChipIDSize,ATQ,&ATS); if(sts == 0x00 && pSelectedCard->cardInfo.ChipID.Mif_UID[0] == ChipID[0] && pSelectedCard->cardInfo.ChipID.Mif_UID[1] == ChipID[1] && pSelectedCard->cardInfo.ChipID.Mif_UID[2] == ChipID[2] && pSelectedCard->cardInfo.ChipID.Mif_UID[3] == ChipID[3]) return 0x00; else{ nMaxTimeOut --; if(!nMaxTimeOut) break; } } return sts; //No Card } //Remove specified card from internal list void CFGMifareObj::RemoveCard(CFGMifareCard *pSelectedCard){ int nIndex=0; for(nIndex=0; nIndex < paCards.GetCount(); nIndex++){ if(*pSelectedCard == *(CFGMifareCard *)paCards.GetAt(nIndex)){ //Ok, found paCards.RemoveAt(nIndex); nCardsInRF--; return; } } return; } int STDCALL_METHOD MifC_WriteBlock( SESSION_HANDLE hSession, unsigned char BlockNumber, unsigned char *pData//must point to 16 bytes ); //Write a single Block int CFGMifareObj::WriteBlock(CFGMifareCard *pSelectedCard,int nBlock,int usingKey,unsigned char *BlockData){ int sts=0; if(nBlock >= pSelectedCard->GetCardInfo()->BlocksCount){ msgErr.Format("CFGMifareObj::ReadBlock -> Error: Invalid block number! Max Blocks: %d - Block request to read: %d",pSelectedCard->GetCardInfo()->BlocksCount,nBlock); DisplayMsgErr(); return -1; } if(usingKey != USE_KEY_A && usingKey != USE_KEY_B){ msgErr.Format("CFGMifareObj::ReadBlock -> Error: Invalid Key! Must be USE_KEY_A or USE_KEY_B"); DisplayMsgErr(); return -1; } MIF_KEY accessKey; accessKey.KeyType=usingKey; if(usingKey == USE_KEY_A){ memcpy(accessKey.KeyValue,pSelectedCard->KeyA,MIF_KEY_VALUE_LEN); }else{ memcpy(accessKey.KeyValue,pSelectedCard->KeyB,MIF_KEY_VALUE_LEN); } sts = MifC_WriteBlockAuth(hSess,&accessKey,&pSelectedCard->cardInfo.ChipID,(unsigned char)nBlock,BlockData); return sts; } //Erase a single Block int CFGMifareObj::EraseBlock(CFGMifareCard *pSelectedCard,int nBlock,int usingKey){ unsigned char BlockData[MIF_BLOCK_SIZE]; memset(BlockData,0x00,MIF_BLOCK_SIZE); //Empty data in the buffer return WriteBlock(pSelectedCard,nBlock,usingKey,BlockData); //Write Nul Data } //Read a single sector int CFGMifareObj::ReadSector(CFGMifareCard *pSelectedCard,int nSector,int usingKey,unsigned char *SecData,int* bytesRead){ //Mifare 4k is 32 sector with 4 block each of 16 bytes // 8 sector with 16 block each og 16 bytes unsigned char SecDataLen; //Set the correct data sector lenght if( nSector < 32) SecDataLen=48; else SecDataLen = 240; int sts=0; if(nSector >= pSelectedCard->GetCardInfo()->SectorsCount){ msgErr.Format("CFGMifareObj::ReadSector -> Error: Invalid sector number! Max Sectors: %d - Sector request to read: %d",pSelectedCard->GetCardInfo()->SectorsCount,nSector); DisplayMsgErr(); return -1; } if(usingKey != USE_KEY_A && usingKey != USE_KEY_B){ msgErr.Format("CFGMifareObj::ReadSector -> Error: Invalid Key! Must be USE_KEY_A or USE_KEY_B"); DisplayMsgErr(); return -1; } memset(SecData,0x00,SecDataLen); //Empty data in the buffer MIF_KEY accessKey; accessKey.KeyType=usingKey; if(usingKey == USE_KEY_A){ memcpy(accessKey.KeyValue,pSelectedCard->KeyA,MIF_KEY_VALUE_LEN); }else{ memcpy(accessKey.KeyValue,pSelectedCard->KeyB,MIF_KEY_VALUE_LEN); } sts = MifC_ReadSectorDataAuth(hSess,&accessKey,&pSelectedCard->cardInfo.ChipID,SecData,SecDataLen,nSector); *bytesRead=SecDataLen; return sts; } //Write a single sector int CFGMifareObj::WriteSector(CFGMifareCard *pSelectedCard,int nSector,int usingKey,unsigned char *SecData){ //Mifare 4k is 32 sector with 4 block each of 16 bytes // 8 sector with 16 block each og 16 bytes unsigned char SecDataLen; //Set the correct data sector lenght if( nSector < 32) SecDataLen=48; else SecDataLen = 240; int sts=0; if(nSector >= pSelectedCard->GetCardInfo()->SectorsCount){ msgErr.Format("CFGMifareObj::WriteSector -> Error: Invalid sector number! Max Sectors: %d - Sector request to read: %d",pSelectedCard->GetCardInfo()->SectorsCount,nSector); DisplayMsgErr(); return -1; } if(usingKey != USE_KEY_A && usingKey != USE_KEY_B){ msgErr.Format("CFGMifareObj::WriteSector -> Error: Invalid Key! Must be USE_KEY_A or USE_KEY_B"); DisplayMsgErr(); return -1; } MIF_KEY accessKey; accessKey.KeyType=usingKey; if(usingKey == USE_KEY_A){ memcpy(accessKey.KeyValue,pSelectedCard->KeyA,MIF_KEY_VALUE_LEN); }else{ memcpy(accessKey.KeyValue,pSelectedCard->KeyB,MIF_KEY_VALUE_LEN); } sts = MifC_WriteSectorDataAuth(hSess,&accessKey,&pSelectedCard->cardInfo.ChipID,SecData,SecDataLen,nSector); return sts; } //Erase a single Block int CFGMifareObj::EraseSector(CFGMifareCard *pSelectedCard,int nSector,int usingKey){ unsigned char aSecData[255]; memset(aSecData,0x00,255); //Empty data in the buffer return WriteSector(pSelectedCard,nSector,usingKey,aSecData); //Write Nul Data } //Read all data on the card int CFGMifareObj::ReadAllSector(CFGMifareCard *pSelectedCard,CByteArray& dataOnCard,int usingKey,CProgressCtrl *aPrgBar){ dataOnCard.RemoveAll(); CByteArray tmpArray; int sts=0; int nSectorToRead=pSelectedCard->GetCardInfo()->SectorsCount; int nSector=0; unsigned char aSecData[255]; int bytesRead=0; for(nSector=0; nSectorStepIt(); if(!sts){ for(int nByte=0; nByteStepIt(); }else break; } return sts; } //Write all data on the card int CFGMifareObj::WriteAllSector(CFGMifareCard *pSelectedCard,CByteArray& dataToWrite,int usingKey,CProgressCtrl *aPrgBar){ int sts=0; int nSectorToRead=pSelectedCard->GetCardInfo()->SectorsCount; int nSector=0; unsigned char aSecData[255]; int bytesRead=0; unsigned char SecDataLen; int posBuffer=0; for(nSector=0; nSectorStepIt(); if(sts) break; } return sts; } //Read a ACL int CFGMifareObj::ReadACL(CFGMifareCard *pSelectedCard,int nSector,int usingKey,unsigned char *pACL,MIF_KEY& theKeyB){ //Is the pACL=4 BYTES ACL MIF_KEY theKeyA; int sts=0; if(nSector >= pSelectedCard->GetCardInfo()->SectorsCount){ msgErr.Format("CFGMifareObj::ReadSector -> Error: Invalid sector number! Max Sectors: %d - Sector request to read: %d",pSelectedCard->GetCardInfo()->SectorsCount,nSector); DisplayMsgErr(); return -1; } if(usingKey != USE_KEY_A && usingKey != USE_KEY_B){ msgErr.Format("CFGMifareObj::ReadSector -> Error: Invalid Key! Must be USE_KEY_A or USE_KEY_B"); DisplayMsgErr(); return -1; } memset(pACL,0x00,4); //Empty data in the buffer MIF_KEY accessKey; accessKey.KeyType=usingKey; if(usingKey == USE_KEY_A){ memcpy(accessKey.KeyValue,pSelectedCard->KeyA,MIF_KEY_VALUE_LEN); }else{ memcpy(accessKey.KeyValue,pSelectedCard->KeyB,MIF_KEY_VALUE_LEN); } sts=MifC_GetSectorTrailerAuth2(hSess,&accessKey,&pSelectedCard->cardInfo.ChipID,nSector,pACL,&theKeyA,&theKeyB); return sts; } //Write a ACL int CFGMifareObj::WriteACL(CFGMifareCard *pSelectedCard,int nSector,MIF_KEY& theWriteKey,unsigned char *pACL,MIF_KEY& theKeyA,MIF_KEY& theKeyB){ int sts=0; if(nSector >= pSelectedCard->GetCardInfo()->SectorsCount){ msgErr.Format("CFGMifareObj::ReadSector -> Error: Invalid sector number! Max Sectors: %d - Sector request to read: %d",pSelectedCard->GetCardInfo()->SectorsCount,nSector); DisplayMsgErr(); return -1; } sts=MifC_WriteSectorTrailerAuth(hSess,nSector,&theWriteKey,&pSelectedCard->cardInfo.ChipID,pACL,&theKeyA,&theKeyB); return sts; }