Advertisement
Guest User

Untitled

a guest
May 27th, 2019
346
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.15 KB | None | 0 0
  1. //Access Control Reader based on ApplePay (EMV) and Troyka cards
  2.  
  3. #include <OneWire.h>
  4. #include <Adafruit_PN532.h>
  5.  
  6. // If using the breakout with SPI, define the pins for SPI communication.
  7. #define PN532_SCK (52)
  8. #define PN532_MOSI (51)
  9. #define PN532_SS (10)
  10. #define PN532_MISO (50)
  11.  
  12. // Use this line for a breakout with a software SPI connection (recommended):
  13. Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
  14.  
  15.  
  16. //EMV card global vars
  17. static const uint8_t aid_marker[] = {0x4F, 0x07};
  18. static const uint8_t pan_marker[] = {0x5A, 0x08};
  19.  
  20. OneWire myWire(6);
  21.  
  22. void setup(void) {
  23. Serial.begin(115200);
  24. Serial.println("Hello!");
  25.  
  26. nfc.begin();
  27.  
  28. uint32_t versiondata = nfc.getFirmwareVersion();
  29. if (! versiondata) {
  30. Serial.print("Didn't find PN53x board");
  31. while (1); // halt
  32. }
  33. // Got ok data, print it out!
  34. Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  35. Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  36. Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  37.  
  38. // configure board to read RFID tags
  39. nfc.SAMConfig();
  40.  
  41. Serial.println("Waiting for an ISO14443A Card ...");
  42. }
  43.  
  44. // dumb_memmem
  45. static char* dumb_memmem(const char* haystack, int hlen, const char* needle, int nlen) {
  46. // naive implementation
  47. if (nlen > hlen) return 0;
  48. int i;
  49. for (i=0; i<hlen-nlen+1; i++) {
  50. if (memcmp(haystack+i,needle,nlen)==0) {
  51. return (char*)(haystack+i);
  52. }
  53. }
  54. return NULL;
  55. }
  56.  
  57.  
  58. // PAN search
  59. static int pan_search(char *haystack, int hlen, char *outbuff){
  60.  
  61. if (hlen > 20) {
  62. void * searchresult = dumb_memmem(haystack, hlen, pan_marker, 2);
  63. if (searchresult) {
  64. memcpy(outbuff, searchresult + 2, 8);
  65. //Serial.print("Full PAN: ");
  66. //nfc.PrintHex(outbuff, 8);
  67. return 1;
  68. }
  69. return 0;
  70.  
  71. } // end of if
  72. return 0;
  73. } //end of pan_search
  74.  
  75.  
  76.  
  77. // Get Troyka serial from data block
  78. char * gettroykaserial(char * blockdata)
  79. {
  80.  
  81. uint32_t serial_temp;
  82. char troykaserial[11];
  83.  
  84.  
  85. // Parse Troyka 10 digits serial number (not UID) that printed on card
  86. // located from 3 byte up to 4 lower bits of 3 byte
  87. memcpy(&serial_temp, &(blockdata[3]), 4);
  88.  
  89. // Covert MSB to LSB byte order
  90. serial_temp = ((serial_temp>>24)&0xf0) | // move half from byte 3 to byte 0
  91. ((serial_temp<<8)&0xff0000) | // move byte 1 to byte 2
  92. ((serial_temp>>8)&0xff00) | // move byte 2 to byte 1
  93. ((serial_temp<<24)&0xff000000); // byte 0 to byte 3
  94.  
  95. // Shift to half byte to the right
  96. serial_temp = serial_temp >> 4;
  97.  
  98. // Add zero's padding from the left if necessary
  99. sprintf(troykaserial, "%010lu", serial_temp);
  100.  
  101. Serial.print("Troyka Serial: ");
  102. Serial.println(troykaserial);
  103.  
  104. return troykaserial;
  105. }
  106.  
  107.  
  108. void loop(void) {
  109. uint8_t success;
  110. uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
  111. uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
  112.  
  113.  
  114. // Troyka
  115. uint8_t TroykaKeyA[6] = { 0xA7, 0x3F, 0x5D, 0xC1, 0xD3, 0x33 }; // Key А from 8 sector Troyka card
  116. uint8_t KeyTypeA = 0;
  117. uint8_t KeyTypeB = 1;
  118. uint8_t TroykaBlockAddr = 32; // Sector 8, block 0 (block number 32)
  119.  
  120. // EMV card
  121. bool apdusuccess;
  122. uint8_t apdu[255];
  123. uint8_t berBuffer[255];
  124. uint8_t berLength = 255;
  125. uint8_t aid[7];
  126. void *searchresult;
  127. uint8_t pan[8] = {0x00};
  128. uint8_t pan_found = 0;
  129. char temp[3];
  130. char * cardID;
  131.  
  132.  
  133. // Wait for an ISO14443A type cards (Mifare, etc.). When one is found
  134. // 'uid' will be populated with the UID, and uidLength will indicate length
  135. success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  136.  
  137. if (success) {
  138. // Display some basic information about the card
  139. Serial.println("");
  140. Serial.println("");
  141. Serial.println("Found an ISO14443A card");
  142. Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
  143. Serial.print(" UID Value: ");
  144. nfc.PrintHex(uid, uidLength);
  145. Serial.println("");
  146.  
  147. if (uid)
  148. {
  149.  
  150. if (uidLength == 7)
  151. {
  152. // If 7 bytes UID, we probably have a Troyka card
  153. // TODO: check ATS for detect mifare plus instead of UID length
  154. Serial.println("Seems to be a Troyka card (7 byte UID). Lets try authenticate it as Mifare Classic");
  155.  
  156. success = nfc.mifareclassic_AuthenticateBlock(uid+3, uidLength - 3, TroykaBlockAddr, KeyTypeA, TroykaKeyA);
  157.  
  158. if (success)
  159. {
  160. Serial.println("Sector 8 (Blocks 32..35) has been authenticated");
  161. uint8_t data[16];
  162.  
  163. // Try to read content of block 32 (sector 8 block 0)
  164. success = nfc.mifareclassic_ReadDataBlock(TroykaBlockAddr, data);
  165.  
  166. // Extract Troyka serial from block data
  167. cardID = gettroykaserial(data);
  168. Serial.println("-----------------------");
  169. Serial.print("Card ID: ");
  170. Serial.println(cardID);
  171. myWire.write(cardID);
  172. delay(2000);
  173. } // end of if (success)
  174.  
  175. else
  176. {
  177. // If authentication failed, probably it's not mifare card
  178. // tryes to check for EMV card
  179. Serial.println("Failed to authenticate card as Mifare. Try to check for EMV card");
  180.  
  181. delay(2000);
  182. }
  183. } // end of if (uidLength == 7)
  184.  
  185. else if (uidLength == 4)
  186. {
  187. // If 4 bytes UID, we probably have a EMV card
  188. Serial.println("Seems to be a EMV card (4 byte UID). Lets try to read PAN nubmer");
  189.  
  190. // Reading PSE file for AID number
  191. uint8_t apdu[] = {0x00, 0xA4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00};
  192. apdusuccess = nfc.inDataExchange(apdu, sizeof(apdu), berBuffer, &berLength);
  193.  
  194. if (apdusuccess)
  195. {
  196. if (berLength > 10) {
  197. searchresult = dumb_memmem(berBuffer, berLength, aid_marker, 2);
  198. if (searchresult) {
  199. memcpy(&aid, searchresult + 2, 7);
  200. Serial.print("AID: ");
  201. nfc.PrintHex(aid, 7);
  202. }
  203. }
  204.  
  205.  
  206. // Now start application on card (AID)
  207. uint8_t startAID[] = {0x00, 0xa4, 0x04, 0x00, 0x07, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
  208. memcpy(&startAID[5], &aid, 7);
  209. Serial.print("StartAID is: "); nfc.PrintHex(startAID, sizeof(startAID));
  210. berLength = 255;
  211. apdusuccess = nfc.inDataExchange(startAID, sizeof(startAID), berBuffer, &berLength);
  212.  
  213.  
  214. memset(pan, 0x00, 8);
  215. pan_found = 0;
  216. // Looking for PAN
  217. uint8_t apdu1[] = {0x00, 0xb2, 0x01, 0x0c, 0x00};
  218. berLength = 255;
  219. apdusuccess = nfc.inDataExchange(apdu1, sizeof(apdu1), berBuffer, &berLength);
  220. Serial.print("berBuffer1 is: "); nfc.PrintHex(berBuffer, berLength);
  221. pan_found = pan_search(berBuffer, berLength, pan);
  222. if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found");
  223.  
  224. uint8_t apdu2[] = {0x00, 0xb2, 0x02, 0x0c, 0x00};
  225. berLength = 255;
  226. apdusuccess = nfc.inDataExchange(apdu2, sizeof(apdu2), berBuffer, &berLength);
  227. Serial.print("berBuffer3 is: "); nfc.PrintHex(berBuffer, berLength);
  228. if (!pan_found)
  229. pan_found = pan_search(berBuffer, berLength, pan);
  230. if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found");
  231.  
  232. uint8_t apdu3[] = {0x00, 0xb2, 0x01, 0x14, 0x00};
  233. berLength = 255;
  234. apdusuccess = nfc.inDataExchange(apdu3, sizeof(apdu3), berBuffer, &berLength);
  235. Serial.print("berBuffer4 is: "); nfc.PrintHex(berBuffer, berLength);
  236. if (!pan_found)
  237. pan_found = pan_search(berBuffer, berLength, pan);
  238. if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found");
  239.  
  240. uint8_t apdu4[] = {0x00, 0xb2, 0x02, 0x14, 0x00};
  241. uint8_t berLength = 255;
  242. apdusuccess = nfc.inDataExchange(apdu4, sizeof(apdu4), berBuffer, &berLength);
  243. Serial.print("berBuffer5 is: "); nfc.PrintHex(berBuffer, berLength);
  244. if (!pan_found)
  245. pan_found = pan_search(berBuffer, berLength, pan);
  246. if (pan_found) Serial.println("Pan found"); else Serial.println("Pan not found");
  247.  
  248. if (pan_found) {
  249. Serial.println("-----------------------");
  250. Serial.print("Сard ID: ");
  251. for (int i = 3; i < 8; i++) {
  252. sprintf(temp, "%02x", pan[i]);
  253. Serial.print(temp);
  254. }
  255. }
  256. }
  257.  
  258.  
  259. }
  260.  
  261. else
  262. {
  263. Serial.print("Abnormal UID Length: ");
  264. nfc.PrintHex(uid, uidLength);
  265. }
  266.  
  267. } // end of if (uid)
  268.  
  269. else
  270. {
  271. // Failed to read card
  272. Serial.println("Failed to read card. Retry after 2 seconds.");
  273. delay(2000);
  274. }
  275. }
  276. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement