private void HandleMifareUL(ICardReader reader) { var mifare = new PcscSdk.MifareUltralight.AccessHandler(reader); StatusMessage?.Invoke("Handling as Mifare Ultralight"); byte[] uid = mifare.GetUid(); StatusMessage?.Invoke("UID: " + BitConverter.ToString(uid)); Array.Resize(ref uid, uid.Length + 1); uid[uid.Length - 1] = 0xAA; NewTagUid?.Invoke(uid); byte[] infoData = mifare.Read(0); StatusMessage?.Invoke("CC: " + BitConverter.ToString(infoData.Skip(12).ToArray())); try { byte[] versionData = mifare.GetVersion(); StatusMessage?.Invoke("Mifare Version: " + BitConverter.ToString(versionData)); int capacity = versionData[6] >> 1; int capacityMax = capacity; if ((versionData[6] & 1) == 1) { capacityMax += 1; } capacity = (int)Math.Pow(2, capacity); capacityMax = (int)Math.Pow(2, capacityMax); StatusMessage?.Invoke("Capacity is between " + capacity + " and " + capacityMax + " bytes"); } catch (ApduFailedException e) { StatusMessage?.Invoke("Failed getting Mifare Version: " + e.Message); } byte identMagic = infoData[12]; byte identVersion = infoData[13]; int identCapacity = infoData[14] * 8; int major = identVersion >> 4; int minor = identVersion & 0x0F; if (identMagic != 0xE1 || identVersion < 0x10) { throw new NfcHandlerException("Tag format is unsupported"); } StatusMessage?.Invoke("Found Type 2 Tag version " + major + "." + minor + " with " + identCapacity + " bytes capacity."); if (ndefDataToWrite != null) { WriteNdefToMifareUL(mifare, ndefDataToWrite); ndefDataToWrite = null; } else { byte[] data = DumpMifareUL(mifare); ParseTLVData(data); } }
private void HandleMifareStandard(ICardReader reader) { var mifare = new PcscSdk.MifareStandard.AccessHandler(reader); StatusMessage?.Invoke("Handling as Mifare Standard 1K"); byte[] uid = mifare.GetUid(); StatusMessage?.Invoke("UID: " + BitConverter.ToString(uid)); Array.Resize(ref uid, uid.Length + 1); uid[uid.Length - 1] = 0xBB; NewTagUid?.Invoke(uid); byte gpByte = InitAndGetGPMifareStandard(mifare); bool usesMad = (gpByte & 0x80) != 0; bool multiApp = (gpByte & 0x40) != 0; int madVersion = gpByte & 0x03; StatusMessage?.Invoke("Uses MAD: " + usesMad + "; Multi App: " + multiApp + "; Version: " + madVersion); if (ndefDataToWrite != null) { WriteNdefToMifareStandard(mifare, ndefDataToWrite); ndefDataToWrite = null; } else { if (!usesMad) { throw new NfcHandlerException("No MAD in use"); } if (madVersion != 1) { throw new NfcHandlerException("Unsupported MAD version: " + madVersion + " (Only version 1 is supported)"); } byte[] data = DumpMifareStandard(mifare); ParseTLVData(data); } }
private void HandleHCEClient(ICardReader reader) { StatusMessage?.Invoke("Attemtping to talk to Android HCE device."); var selectCmd = new Iso7816.SelectCommand(FLAGCARRIER_HCE_AID, 0); var res = reader.Transceive(selectCmd); if (res.SW == 0x6a82) { ErrorMessage?.Invoke("Device has no idea who we are."); return; } else if (!res.Succeeded) { ErrorMessage?.Invoke("Failed communicating with device: " + res.ToString()); return; } StatusMessage?.Invoke("Connected to FlagCarrier HCE device!"); byte[] challengeToken = new byte[32]; random.NextBytes(challengeToken, 0, challengeToken.Length); var updateCmd = new Iso7816.UpdateBinaryCommand(challengeToken); res = reader.Transceive(updateCmd); if (res.SW == 0x6A82) { ErrorMessage?.Invoke("HCE Device does not have any data for us."); return; } if (!res.Succeeded) { ErrorMessage?.Invoke("Failed sending challenge token: " + res.ToString()); return; } StatusMessage?.Invoke("Sent challenge token."); byte[] ndefData = new byte[0]; const int len = 250; int offset = 0; do { var readCmd = new Iso7816.ReadBinaryCommand(len, offset); res = reader.Transceive(readCmd); if (!res.Succeeded) { ErrorMessage?.Invoke("Failed reading data at " + offset + ": " + res.ToString()); return; } if (res.ResponseData == null || res.ResponseData.Length == 0) { break; } Array.Resize(ref ndefData, ndefData.Length + res.ResponseData.Length); res.ResponseData.CopyTo(ndefData, offset); offset += res.ResponseData.Length; } while (res.ResponseData.Length == len); StatusMessage?.Invoke("Read " + ndefData.Length + " bytes of ndef data from device."); NdefMessage msg = NdefMessage.FromByteArray(ndefData); NewTagUid?.Invoke(challengeToken); ReceiveNdefMessage?.Invoke(msg); var eraseCmd = new Iso7816.EraseBinaryCommand(); res = reader.Transceive(eraseCmd); if (!res.Succeeded) { ErrorMessage?.Invoke("Failed confirming transaction to device."); } }