예제 #1
0
        private void ParseTLVData(byte[] data)
        {
            using (MemoryStream stream = new MemoryStream(data))
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    while (stream.Position < stream.Length)
                    {
                        byte   tag    = reader.ReadByte();
                        int    length = 0;
                        byte[] val    = null;
                        if (tag != 0x00 && tag != 0xFE)
                        {
                            length = reader.ReadByte();
                            if (length >= 0xFF)
                            {
                                byte[] lengthBytes = reader.ReadBytes(2);
                                if (BitConverter.IsLittleEndian)
                                {
                                    Array.Reverse(lengthBytes);
                                }
                                length = BitConverter.ToUInt16(lengthBytes, 0);
                            }
                            val = length > 0 ? reader.ReadBytes(length) : null;
                        }

                        switch (tag)
                        {
                        case 0x00:
                            StatusMessage?.Invoke("Skipping NULL TLV");
                            break;

                        case 0x01:
                            StatusMessage?.Invoke("Skipping Lock Control TLV");
                            break;

                        case 0x02:
                            StatusMessage?.Invoke("Skipping Memory Control TLV");
                            break;

                        case 0xFE:
                            StatusMessage?.Invoke("Reached terminator TLV");
                            return;

                        case 0x03:
                            if (val != null)
                            {
                                StatusMessage?.Invoke("Found NDEF TLV (" + length + " bytes)");
                                NdefMessage msg = NdefMessage.FromByteArray(val);
                                ReceiveNdefMessage?.Invoke(msg);
                            }
                            else
                            {
                                StatusMessage?.Invoke("Found empty NDEF TLV");
                            }
                            break;

                        default:
                            StatusMessage?.Invoke("Skipping unknown TLV " + BitConverter.ToString(new byte[] { tag }));
                            break;
                        }
                    }
                }
        }
예제 #2
0
        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.");
            }
        }