Example #1
0
        private byte[] DumpMifareStandard(PcscSdk.MifareStandard.AccessHandler mifare)
        {
            byte[] madData = new byte[32];
            mifare.Read(1, PcscSdk.MifareStandard.GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 0).CopyTo(madData, 0);
            mifare.Read(2, PcscSdk.MifareStandard.GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 0).CopyTo(madData, 16);

            byte crc     = madData[0];
            byte calcCrc = PcscSdk.MifareStandard.CRC8.Calc(madData.Skip(1).ToArray());

            if (crc != calcCrc)
            {
                throw new NfcHandlerException("MAD CRC mismatch. 0x" + BitConverter.ToString(new[] { crc }) + " != 0x" + BitConverter.ToString(new[] { calcCrc }));
            }

            StatusMessage?.Invoke("CRC 0x" + BitConverter.ToString(new[] { crc }) + " OK");

            using (MemoryStream mem = new MemoryStream())
            {
                for (int sec = 1; sec < 16; sec++)
                {
                    if (madData[sec * 2] != 0x03 || madData[sec * 2 + 1] != 0xE1)
                    {
                        continue;
                    }
                    for (int block = sec * 4; block < sec * 4 + 3; block++)
                    {
                        mem.Write(mifare.Read((ushort)block, PcscSdk.MifareStandard.GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 1), 0, 16);
                    }
                }

                return(mem.ToArray());
            }
        }
Example #2
0
        private byte InitAndGetGPMifareStandard(PcscSdk.MifareStandard.AccessHandler mifare)
        {
            mifare.LoadKey(new byte[] { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, 0);
            StatusMessage?.Invoke("Loaded public MAD key in slot 0.");

            mifare.LoadKey(new byte[] { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }, 1);
            StatusMessage?.Invoke("Loaded public NDEF key in slot 1.");

            byte[] infoData;
            try
            {
                infoData = mifare.Read(3, GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 0);
            }
            catch (Exception)
            {
                StatusMessage?.Invoke("Failed reading with default key.");

                mifare.LoadKey(PcscSdk.MifareStandard.DefaultKeys.FactoryDefault, 0);
                StatusMessage?.Invoke("Loaded factory default key in slot 0.");

                infoData = mifare.Read(3, GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 0);
                StatusMessage?.Invoke("Card uses factory default key!");
            }
            byte gpByte = infoData[9];

            StatusMessage?.Invoke("General purpose byte: " + BitConverter.ToString(new[] { gpByte }));

            return(gpByte);
        }
Example #3
0
        private void WriteNdefToMifareStandard(PcscSdk.MifareStandard.AccessHandler mifare, byte[] ndefData)
        {
            InitializeMifareStandard(mifare);

            const int capacity = 15 * 3 * 16;

            byte[] wrappedData = GenerateTLVData(ndefData);

            if (wrappedData.Length > capacity)
            {
                throw new NfcHandlerException("Data size of " + wrappedData.Length + " bytes exceeds capacity of " + capacity + " bytes!");
            }

            int data_length = wrappedData.Length;

            Array.Resize(ref wrappedData, (data_length / 16) * 16 + 16);

            byte writeBlock = 3;

            for (byte pos = 0; pos < wrappedData.Length; pos += 16)
            {
                if (++writeBlock % 4 == 3)
                {
                    writeBlock++;
                }
                mifare.Write(writeBlock, wrappedData.Skip(pos).Take(16).ToArray(), GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 1);
            }

            StatusMessage?.Invoke("Written " + data_length + " bytes of data. Ndef message length is " + ndefData.Length + " bytes.");
        }
Example #4
0
        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);
            }
        }
Example #5
0
        private void InitializeMifareStandard(PcscSdk.MifareStandard.AccessHandler mifare)
        {
            byte[] mad1 = mifare.Read(1, PcscSdk.MifareStandard.GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 0);
            byte[] mad2 = mifare.Read(2, PcscSdk.MifareStandard.GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 0);

            // One of my readers only has two key slots, another one does not allow overwriting them, but has at least 3. So here we go...
            // Also, the Microsoft IFD emulation(?) reports 0x0000 in response, but it still seems to have worked.
            byte factoryKeySlot = 0;

            try
            {
                mifare.LoadKey(PcscSdk.MifareStandard.DefaultKeys.FactoryDefault, 0);
                StatusMessage?.Invoke("Loaded factory default key in slot 0.");
            }
            catch (ApduFailedException e)
            {
                if (e.Response.SW == 0x0000 && e.Response.ResponseData.Length == 0 && mifare.CardReader.Name.Contains("Microsoft IFD"))
                {
                    StatusMessage?.Invoke("Loaded factory default key in slot 0. (MS Quirk)");
                }
                else
                {
                    StatusMessage?.Invoke("Could not re-load to slot 0, trying slot 2: " + e.Message);
                    mifare.LoadKey(PcscSdk.MifareStandard.DefaultKeys.FactoryDefault, 2);
                    StatusMessage?.Invoke("Loaded factory default key in slot 2.");
                    factoryKeySlot = 2;
                }
            }

            if (!mad1.SequenceEqual(ndefMadData[1]) || !mad2.SequenceEqual(ndefMadData[2]))
            {
                StatusMessage?.Invoke("Writing NDEF MAD block.");

                for (byte block = 1; block < 4; block++)
                {
                    StatusMessage?.Invoke("Writing MAD block " + block);
                    try
                    {
                        mifare.Write(block, ndefMadData[block], GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, factoryKeySlot);
                    }
                    catch (Exception)
                    {
                        mifare.Write(block, ndefMadData[block], GeneralAuthenticate.GeneralAuthenticateKeyType.PicoTagPassKeyB, factoryKeySlot);
                    }
                }
            }

            for (int sector = 1; sector < 16; sector++)
            {
                byte block = (byte)(sector * 4 + 3);
                try
                {
                    for (int i = 1; i < 4; i++)
                    {
                        var authRes = mifare.CardReader.Transceive(new PcscSdk.MifareStandard.GeneralAuthenticate((byte)(block - i), 1, GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA));
                        if (!authRes.Succeeded)
                        {
                            StatusMessage?.Invoke("NDEF read authentication failed, trying trailer rewrite.");
                            throw new Exception();
                        }
                    }

                    byte[] sectorIdent = mifare.Read(block, GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, 1);
                    if (!sectorIdent.SequenceEqual(ndefComparator))
                    {
                        throw new Exception();
                    }
                }
                catch (Exception)
                {
                    StatusMessage?.Invoke("Writing NDEF trailer into sector " + sector);
                    try
                    {
                        mifare.Write(block, ndefSectorIdent, GeneralAuthenticate.GeneralAuthenticateKeyType.MifareKeyA, factoryKeySlot);
                    }
                    catch (Exception)
                    {
                        mifare.Write(block, ndefSectorIdent, GeneralAuthenticate.GeneralAuthenticateKeyType.PicoTagPassKeyB, factoryKeySlot);
                    }
                }
            }

            StatusMessage?.Invoke("Tag is NDEF formated");
        }