Пример #1
0
 /// <summary>
 /// Initializes a new <see cref="DataObjectList"/> instance.
 /// </summary>
 /// <param name="dolData">Raw DOL data.</param>
 public DataObjectList(byte[] dolData)
     : this()
 {
     Tlv = new TlvData {
         Value = dolData
     };
 }
Пример #2
0
        private TlvData BuildTlv(TagModel tagModel)
        {
            var tlv = new TlvData {
                Tag = Convert.ToUInt32(tagModel.Tag, 16)
            };

            if (tagModel.Fields == null)
            {
                tlv.Value = tagModel.Tag switch
                {
                    // Language Preference
                    "5F2D" => _data.UnmanagedAttributes[tagModel.Tag]
                    .ToObject <string[]>()
                    .Aggregate(String.Empty, (c, l) => c + l)
                    .FromString(),
                    _ => _data.UnmanagedAttributes[tagModel.Tag]
                    .ToObject <string>()
                    .FromHexa()
                };
            }
            else
            {
                tlv.InnerTlvs = tagModel.Fields.Select(BuildTlv).ToList();
            }

            return(tlv);
        }
Пример #3
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="tlvLogEntry">Raw Log Entry tag</param>
 public LogEntry(TlvData tlvLogEntry)
 {
     if (tlvLogEntry.Length < 2)
     {
         throw new Exception(String.Format("LogEntry: TLV data length < 2, can't parse [{0}]", tlvLogEntry));
     }
     Tlv = tlvLogEntry;
 }
Пример #4
0
            /// <inheritdoc />
            public override string ToString()
            {
                var tlv = new TlvData {
                    Tag = Tag, Length = Length
                };

                return(String.Format("({0:T}/{0:L})", tlv));
            }
Пример #5
0
        /// <summary>
        /// MasterCard cAPDU.
        /// Process the COMPUTE CRYPTOGRAPHIC CHECKSUM phase of a MasterCard transaction.
        /// </summary>
        /// <returns>Last status word.</returns>
        public UInt16 ComputeCryptographicChecksum()
        {
            BeforeComputeCryptographicChecksumEvent.Raise(this, new EmvEventArgs());

            // If UDOL 9F69 is not supplied in records, then use default UDOL = 9F6A04
            byte[] udolDataValue = null;
            var    tlvAll        = new List <TlvData>();

            foreach (var record in _tlvRecords)
            {
                tlvAll.Add(record);
                if (record.HasTag(0x9F69))
                {
                    var udol = new DataObjectList(record.GetTag(0x9F69).Value);
                    tlvAll.AddRange(TlvTerminalData);
                    udolDataValue = udol.BuildData(tlvAll);
                }
            }

            if (udolDataValue == null)
            {
                var tmp        = "";
                var seed       = new Random(10000).Next();
                var rndNumbers = new Random(seed);
                for (var i = 0; i < 8; i++)
                {
                    var rndNumber = rndNumbers.Next(10);
                    tmp += rndNumber.ToString(CultureInfo.InvariantCulture);
                }
                udolDataValue = tmp.FromHexa();
            }

            // Execute COMPUTE CRYPTOGRAPHIC CHECKSUM
            var cAPDU = new CommandAPDU(0x80, 0x2A, 0x8E, 0x80, (uint)udolDataValue.Length, udolDataValue, 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);
            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                _tlvCryptographicChecksum = new TlvData();
                crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                crp.Transmit(_cardChannel);
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _tlvCryptographicChecksum = new TlvData(crp.RApdu.Udr);
            }

            AfterComputeCryptographicChecksumEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Пример #6
0
 /// <summary>
 /// Initializes a new <see cref="EmvApplication"/> instance.
 /// </summary>
 /// <param name="cardChannel"><see cref="ICardChannel">ICardChannel</see> object to use</param>
 /// <param name="tlvFromPSE"><see cref="TlvData">TLVData</see> object coming from PSE records for this application</param>
 public EmvApplication(ICardChannel cardChannel, TlvData tlvFromPSE)
     : this(cardChannel)
 {
     _tlvFromPSE = tlvFromPSE;
     if (_tlvFromPSE.HasTag(0x4F))
     {
         Aid = _tlvFromPSE.GetTag(0x4F).Value.ToHexa();
     }
 }
Пример #7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="tagId"></param>
 /// <param name="tlv"></param>
 /// <param name="tagsManager"></param>
 private static void WriteTlv(UInt32 tagId, TlvData tlv, TlvDictionary tagsManager)
 {
     Console.WriteLine("  >> Contains tag {0:X2}: {1} [ {2} ]", tagId, tlv.HasTag(tagId), tlv.GetTag(tagId));
     if (tlv.HasTag(tagId) && (tagsManager.CreateInstance(tlv.GetTag(tagId)) != null))
     {
         Console.ForegroundColor = ConsoleColor.Blue;
         Console.WriteLine("     >> {0:N}: {0}", tagsManager.CreateInstance(tlv.GetTag(tagId)));
         Console.ForegroundColor = ConsoleColor.Gray;
     }
 }
Пример #8
0
            /// <inheritdoc />
            public string ToString(string format, IFormatProvider formatProvider)
            {
                if (!String.IsNullOrEmpty(format))
                {
                    var tlv = new TlvData {
                        Tag = Tag, Length = Length
                    };
                    return(tlv.ToString(format, formatProvider));
                }

                return(ToString());
            }
Пример #9
0
        /// <summary>
        /// Enumerates DO.
        /// </summary>
        /// <returns><see cref="DataObjectList.DataObjectDefinition"/> instances.</returns>
        public IEnumerable <DataObjectDefinition> GetDataObjectDefinitions()
        {
            UInt32 offset    = 0;
            var    tlvParser = new TlvData();

            while (offset < Tlv.Value.Length)
            {
                offset = tlvParser.ParseT(Tlv.Value, offset);
                offset = tlvParser.ParseL(Tlv.Value, offset);
                yield return(new DataObjectDefinition(tlvParser.Tag, tlvParser.Length));
            }
        }
Пример #10
0
        /// <summary>
        /// Process the INTERNAL AUTHENTICATION of an EMV transaction.
        /// </summary>
        /// <param name="unpredictableNumber">Unpredictable number.</param>
        /// <returns>Last status word.</returns>
        public UInt16 InternalAuthenticate(byte[] unpredictableNumber)
        {
            BeforeInternalAuthenticateEvent.Raise(this, new EmvEventArgs());

            _tlvInternalAuthenticateUnpredictableNumber = new TlvData(0x9F37, 0x04, unpredictableNumber);

            // Build DDOL data
            byte[] ddolDataValue;
            if (Ddol != null)
            {
                // Use DDOL to build data
                var tlvAll = new List <TlvData>
                {
                    TlvFci,
                    TlvProcessingOptions,
                    _tlvInternalAuthenticateUnpredictableNumber
                };
                tlvAll.AddRange(TlvRecords);
                tlvAll.AddRange(TlvTerminalData);
                ddolDataValue = Ddol.BuildData(tlvAll);
            }
            else
            {
                ddolDataValue = new byte[0];
            }

            // Execute GET PROCESSING OPTIONS
            var cAPDU = new CommandAPDU(0x00, 0x88, 0x00, 0x00, (uint)ddolDataValue.Length, ddolDataValue, 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);
            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                _tlvSignedDynamicApplicationResponse = new TlvData();
                crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                crp.Transmit(_cardChannel);
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _tlvSignedDynamicApplicationResponse = new TlvData(crp.RApdu.Udr);
            }

            AfterInternalAuthenticateEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Пример #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tagId"></param>
        /// <param name="tlv"></param>
        /// <param name="tagsManager"></param>
        private void WriteTlv(UInt32 tagId, TlvData tlv, TlvDictionary tagsManager)
        {
            gui.guiDetailedLogs.AppendText(String.Format("  >> TLV {0:X2}: [ {1} ]\n", tagId, tlv.GetTag(tagId)));

            if (!tlv.HasTag(tagId) || (tagsManager.CreateInstance(tlv.GetTag(tagId)) == null))
            {
                return;
            }

            gui.guiDetailedLogs.SelectionColor = highlightColor;
            gui.guiDetailedLogs.AppendText(String.Format("     >> {0:N}: {0}\n", tagsManager.CreateInstance(tlv.GetTag(tagId))));
            gui.guiDetailedLogs.SelectionColor = standardColor;
        }
Пример #12
0
        /// <summary>
        /// Process the GET PROCESSING OPTIONS phase of an EMV transaction.
        /// </summary>
        /// <returns>Last status word.</returns>
        public UInt16 GetProcessingOptions()
        {
            BeforeGetProcessingOptionsEvent.Raise(this, new EmvEventArgs());

            // If PDOL 9F38 is not supplied in FCI, then used 8300 as UDC; if supplied: build the PDOL in tag 83 L V
            byte[] pdolDataValue;
            if (TlvFci.HasTag(0x9F38))
            {
                // Use PDOL to build tag 83 value
                var pdol   = new DataObjectList(TlvFci.GetTag(0x9F38).Value);
                var tlvAll = new List <TlvData> {
                    TlvFci
                };
                tlvAll.AddRange(TlvTerminalData);
                pdolDataValue = pdol.BuildData(tlvAll);
            }
            else
            {
                pdolDataValue = new byte[0];
            }
            // Build tag 83 with computed value
            var tlvPdolData = new TlvData(0x83, (uint)pdolDataValue.Length, pdolDataValue);

            // Execute GET PROCESSING OPTIONS
            var cAPDU = new CommandAPDU(0x80, 0xA8, 0x00, 0x00, tlvPdolData.Length + 2, tlvPdolData.ToByteArray(), 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);

            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                _tlvProcessingOptions = new TlvData();

                crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                crp.Transmit(_cardChannel);
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _tlvProcessingOptions = new TlvData(crp.RApdu.Udr);
            }

            AfterGetProcessingOptionsEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Пример #13
0
        private void buttonXmlToTlv_Click(object sender, EventArgs e)
        {
            TlvData tlv = null;

            var isDone = TryAndOutput(() =>
            {
                var serializer = new XmlSerializer(typeof(TlvData));
                tlv            = (TlvData)serializer.Deserialize(new StringReader(textSource.Text));
            });

            if (!isDone)
            {
                return;
            }

            ConvertAndOutput(() => tlv.ToByteArray().ToHexa());
        }
Пример #14
0
        /// <summary>
        /// Builds DGI to be used with STORE DATA command for given records having the same index.
        /// </summary>
        /// <param name="sfi"></param>
        /// <param name="index"></param>
        /// <param name="records"></param>
        /// <returns></returns>
        public string BuildDgi(byte sfi, byte index, IEnumerable <PseRecord> records)
        {
            var tlv70 = new TlvData(0x70, new List <TlvData>());

            foreach (var record in records)
            {
                var tlvs = new List <TlvData> {
                    new TlvData {
                        Tag = 0x4F, Value = record.AdfName.FromHexa()
                    },
                    new TlvData {
                        Tag = 0x50, Value = record.ApplicationLabel.FromString()
                    }
                };

                if (!String.IsNullOrWhiteSpace(record.PreferredName))
                {
                    tlvs.Add(new TlvData {
                        Tag = 0x9F12, Value = record.PreferredName.FromString()
                    });
                }

                if (record.PriorityIndicator.HasValue)
                {
                    tlvs.Add(new TlvData {
                        Tag = 0x87, Value = record.PriorityIndicator.Value.ToByteArray()
                    });
                }

                if (!String.IsNullOrWhiteSpace(record.DiscretionaryData))
                {
                    tlvs.Add(new TlvData {
                        Tag = 0x73, Value = record.DiscretionaryData.FromHexa()
                    });
                }

                var tlv61 = new TlvData(0x61, tlvs);
                tlv70.InnerTlvs.Add(tlv61);
            }

            var dgiLength = TlvDataHelper.ToBerEncodedL((uint)tlv70.Length / 2);

            return($"{sfi:X2}{index:X2}{dgiLength.ToHexa('\0')}{tlv70.ToByteArray().ToHexa()}");
        }
Пример #15
0
        /// <summary>
        /// Parses an array of Bytes as a sequence of value, using the format defined by the <see cref="DataObjectList"/>.
        /// </summary>
        /// <param name="data">Array of Bytes to be parsed.</param>
        /// <returns>The list of <see cref="TlvData"/> objects obtained after parsing.</returns>
        public List <TlvData> ParseRawData(byte[] data)
        {
            var tlvDataList = new List <TlvData>();

            var offset = 0;

            foreach (var dod in GetDataObjectDefinitions())
            {
                var tlvData = new TlvData {
                    Tag = dod.Tag, Length = dod.Length, Value = new byte[dod.Length]
                };
                Array.Copy(data, offset, tlvData.Value, 0, (int)dod.Length);
                tlvDataList.Add(tlvData);

                offset += (int)dod.Length;
            }

            return(tlvDataList);
        }
Пример #16
0
        /// <summary>
        /// Reads the file pointed by the SFI found in the FCI of the application.
        /// </summary>
        /// <returns>Last status word.</returns>
        public UInt16 ReadDataFile(AflEntry file)
        {
            for (var recordNumber = file.FirstRecord; recordNumber <= file.LastRecord; recordNumber++)
            {
                CommandAPDU cAPDU = new EMVReadRecordCommand(recordNumber, file.Sfi, 0);
                var         crp   = new CommandResponsePair(cAPDU);
                crp.Transmit(_cardChannel);

                if (crp.RApdu.StatusWord == 0x9000)
                {
                    var tlv = new TlvData(crp.RApdu.Udr);

                    if (tlv.Tag != 0x70)
                    {
                        throw new Exception(String.Format("EMVApplication.readData(): record is not TLV-coded with tag 70 [{0}]", tlv));
                    }

                    // Store data in list
                    _tlvRecords.Add(tlv);

                    // If used for offline, store it in dedicated list
                    if (recordNumber - file.FirstRecord < file.OfflineNumberOfRecords)
                    {
                        // For files with SFI in the range 1 to 10, the record tag ('70') and the record length are excluded from the offline data authentication process.
                        if (file.Sfi <= 10)
                        {
                            foreach (var tlvData in tlv.InnerTlvs)
                            {
                                _tlvOfflineRecords.Add(tlvData);
                            }
                        }
                        //For files with SFI in the range 11 to 30, the record tag ('70') and the record length are not excluded from the offline data authentication process.
                        else
                        {
                            _tlvOfflineRecords.Add(tlv);
                        }
                    }
                }
                _lastStatusWord = crp.RApdu.StatusWord;
            }
            return(_lastStatusWord);
        }
Пример #17
0
        private static TreeNode ConvertTlvDataToTreeNode(TlvData tlv, TlvDictionary tlvManager)
        {
            TreeNode tlvNode;

            if (tlvManager != null && tlvManager.Get(String.Format("{0:T}", tlv)) != null)
            {
                var tlvObject = tlvManager.CreateInstance(tlv);
                tlvObject.Tlv = tlv;
                tlvNode       = new TreeNode(String.Format("{0:N}: {0}", tlvObject));
            }
            else
            {
                tlvNode = new TreeNode(String.Format("T:{0:T} L:{0:L} V:{0:Vh}", tlv));
            }
            foreach (var subTLV in tlv.InnerTlvs)
            {
                tlvNode.Nodes.Add(ConvertTlvDataToTreeNode(subTLV, tlvManager));
            }
            return(tlvNode);
        }
Пример #18
0
        /// <summary>
        /// Selects the DF by its DF Name or AID.
        /// </summary>
        /// <returns>Last status word</returns>
        public UInt16 Select()
        {
            BeforeSelectEvent.Raise(this, new EmvEventArgs());

            // Execute the SELECT
            var crp = new CommandResponsePair(new EMVSelectByNameCommand(_adfName, 0));

            crp.Transmit(_cardChannel);
            _lastStatusWord = crp.RApdu.StatusWord;

            // Finally, store FCI
            if (crp.RApdu.StatusWord == 0x9000)
            {
                TlvFci = new TlvData(crp.RApdu.Udr);
            }

            AfterSelectEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Пример #19
0
        /// <summary>
        /// Process a GET DATA to retrieve one EMV information.
        /// </summary>
        /// <param name="tag">
        ///     <list type="bullet">
        ///         <item><c>0x9F36</c> for ATC</item>
        ///         <item><c>0x9F13</c> for Last Online ATC Register</item>
        ///         <item><c>0x9F17</c> for PIN Try Counter</item>
        ///         <item><c>0x9F4F</c> for Log Format</item>
        ///     </list>
        /// </param>
        /// <param name="tlv"></param>
        /// <returns>Last status word.</returns>
        protected UInt16 GetData(UInt32 tag, ref TlvData tlv)
        {
            // Execute GET DATA instruction
            var cAPDU = new GetDataCommand(tag, 0)
            {
                Cla = 0x80
            };
            var crp = new CommandResponsePair(cAPDU);

            if (crp.Transmit(_cardChannel) != ErrorCode.Success)
            {
                return(_lastStatusWord);
            }

            _lastStatusWord = crp.RApdu.StatusWord;

            // Finally store rAPDU
            if (crp.RApdu.StatusWord == 0x9000)
            {
                tlv = new TlvData(crp.RApdu.Udr);
            }

            return(_lastStatusWord);
        }
Пример #20
0
 /// <summary>
 /// Initializes a new <see cref="CertificationAuthorityPublicKeyIndex"/> instance.
 /// </summary>
 /// <param name="tlvCaPublicKeyIndex">TLVData defining the Certification Authority Public Key Index tag.</param>
 public CertificationAuthorityPublicKeyIndex(TlvData tlvCaPublicKeyIndex)
 {
     Tlv = tlvCaPublicKeyIndex;
 }
Пример #21
0
 /// <summary>
 /// Creates a new <see cref="EmvDefinitionFile"/> instance.
 /// </summary>
 /// <param name="cardChannel"><see cref="ICardChannel">ICardChannel</see> object to use</param>
 public EmvDefinitionFile(ICardChannel cardChannel)
 {
     _cardChannel = new CardChannelIso7816(new CardChannelTerminalTransportLayer(cardChannel));
     TlvFci       = null;
 }
Пример #22
0
 /// <summary>
 /// Initializes a new <see cref="ShortFileIdentifier"/> instance.
 /// </summary>
 /// <param name="tlvSfi">TLVData defining the SFI tag</param>
 public ShortFileIdentifier(TlvData tlvSfi)
 {
     Tlv = tlvSfi;
 }
Пример #23
0
 /// <summary>
 /// Initializes a new <see cref="CryptogramInformationData"/> instance.
 /// </summary>
 /// <param name="tlvCid">TLV CID data.</param>
 public CryptogramInformationData(TlvData tlvCid)
     : this()
 {
     Tlv = tlvCid;
 }
Пример #24
0
 /// <summary>
 /// Initializes a new <see cref="CryptogramInformationData"/> instance.
 /// </summary>
 public CryptogramInformationData()
 {
     Tlv = new TlvData();
 }
Пример #25
0
 /// <summary>
 /// Initializes a new <see cref="TerminalVerificationResult"/> instance.
 /// </summary>
 /// <param name="tlvTvr">TLV TVR data.</param>
 public TerminalVerificationResult(TlvData tlvTvr)
     : this()
 {
     Tlv = tlvTvr;
 }
Пример #26
0
 /// <summary>
 /// Initializes a new <see cref="TerminalVerificationResult"/> instance.
 /// </summary>
 public TerminalVerificationResult()
 {
     Tlv = new TlvData();
 }
Пример #27
0
        /// <summary>
        /// Initializes a new <see cref="ApplicationIdentifier"/> instance.
        /// </summary>
        /// <param name="sAid">string AID.</param>
        public ApplicationIdentifier(string sAid)
        {
            var value = sAid.FromHexa();

            Tlv = new TlvData(0x4F, (UInt32)value.Length, value);
        }
Пример #28
0
 /// <summary>
 /// Initializes a new <see cref="ApplicationIdentifier"/> instance.
 /// Constructor
 /// </summary>
 /// <param name="tlvAid">TLVData containing AID.</param>
 public ApplicationIdentifier(TlvData tlvAid)
 {
     Tlv = tlvAid;
 }
Пример #29
0
 /// <summary>
 /// Initializes a new <see cref="ApplicationIdentifier"/> instance.
 /// </summary>
 public ApplicationIdentifier()
 {
     Tlv = new TlvData {
         Tag = 0x4F
     };
 }
Пример #30
0
 /// <summary>
 /// Initializes a new <see cref="ApplicationFileLocator"/> instance.
 /// </summary>
 public ApplicationFileLocator()
 {
     Tlv = new TlvData {
         Tag = 0x94
     };
 }