Exemple #1
0
        private void ReadCard(object o)
        {
            UseHourglass(true);
            string selectedReader = o as string;

            UpdateStatusLabel("Reading card...");

            TreeView treeView = new TreeView();
            TreeNode cardNode = new TreeNode("Card");

            cardNode.ImageIndex         = 0;
            cardNode.SelectedImageIndex = 0;
            treeView.Nodes.Add(cardNode);

            // Tree nodes
            TreeNode      pseNode                = null;
            TreeNode      fciNode                = null;
            ASN1          fci                    = null;
            List <byte[]> pseIdentifiers         = new List <byte[]>();
            List <byte[]> applicationIdentifiers = new List <byte[]>();
            ASCIIEncoding encoding               = new ASCIIEncoding();
            APDUCommand   apdu                   = null;
            APDUResponse  response               = null;
            bool          pseFound               = false;

            if (!skipPSEToolStripMenuItem.Checked)
            {
                pseIdentifiers.Add(encoding.GetBytes("1PAY.SYS.DDF01"));
                pseIdentifiers.Add(encoding.GetBytes("2PAY.SYS.DDF01"));
            }

            try
            {
                // Now lets process all Payment System Environments
                if (pseIdentifiers.Count > 0)
                {
                    cardReader.Connect(selectedReader);

                    foreach (byte[] pse in pseIdentifiers)
                    {
                        apdu     = new APDUCommand(0x00, 0xA4, 0x04, 0x00, pse, (byte)pse.Length);
                        response = cardReader.Transmit(apdu);

                        // Get response nescesary
                        if (response.SW1 == 0x61)
                        {
                            apdu     = new APDUCommand(0x00, 0xC0, 0x00, 0x00, null, response.SW2);
                            response = cardReader.Transmit(apdu);
                        }

                        // PSE application read found ok
                        if (response.SW1 == 0x90)
                        {
                            pseFound = true;

                            pseNode                    = new TreeNode(String.Format("Application {0}", encoding.GetString(pse)));
                            pseNode.ImageIndex         = 1;
                            pseNode.SelectedImageIndex = 1;
                            pseNode.Tag                = pse;
                            cardNode.Nodes.Add(pseNode);

                            fciNode                    = new TreeNode("File Control Information");
                            fciNode.ImageIndex         = 3;
                            fciNode.SelectedImageIndex = 3;
                            fciNode.Tag                = "fci";
                            pseNode.Nodes.Add(fciNode);

                            fci = new ASN1(response.Data);
                            AddRecordNodes(fci, fciNode);

                            byte sfi          = new ASN1(response.Data).Find(0x88).Value[0];
                            byte recordNumber = 0x01;
                            byte p2           = (byte)((sfi << 3) | 4);

                            TreeNode efDirNode = new TreeNode(String.Format("EF Directory - {0:X2}", sfi));
                            efDirNode.ImageIndex         = 2;
                            efDirNode.SelectedImageIndex = 2;
                            efDirNode.Tag = sfi;
                            pseNode.Nodes.Add(efDirNode);


                            while (response.SW1 != 0x6A && response.SW2 != 0x83)
                            {
                                apdu     = new APDUCommand(0x00, 0xB2, recordNumber, p2, null, 0x00);
                                response = cardReader.Transmit(apdu);

                                // Retry with correct length
                                if (response.SW1 == 0x6C)
                                {
                                    apdu     = new APDUCommand(0x00, 0xB2, recordNumber, p2, null, response.SW2);
                                    response = cardReader.Transmit(apdu);
                                }

                                if (response.SW1 == 0x61)
                                {
                                    apdu     = new APDUCommand(0x00, 0xC0, 0x00, 0x00, null, response.SW2);
                                    response = cardReader.Transmit(apdu);
                                }

                                if (response.Data != null)
                                {
                                    TreeNode recordNode = new TreeNode(String.Format("Record - {0:X2}", recordNumber));
                                    recordNode.ImageIndex         = 4;
                                    recordNode.SelectedImageIndex = 4;
                                    recordNode.Tag = recordNumber;
                                    efDirNode.Nodes.Add(recordNode);

                                    ASN1 aef = new ASN1(response.Data);
                                    AddRecordNodes(aef, recordNode);

                                    foreach (ASN1 appTemplate in aef)
                                    {
                                        // Check we really have an Application Template
                                        if (appTemplate.Tag[0] == 0x61)
                                        {
                                            applicationIdentifiers.Add(appTemplate.Find(0x4f).Value);
                                        }
                                    }
                                }

                                recordNumber++;
                            }
                        }

                        if (pseFound)
                        {
                            break;
                        }
                    }

                    cardReader.Disconnect();
                }

                // We couldn't read the AID's from the PSE, so we'll just try querying all ADI's we know about
                if (!pseFound)
                {
                    // From http://www.darkc0de.com/others/ChAP.py
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000003"));         // VISA
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000031010"));     // VISA Debit/Credit
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000003101001"));   // VISA Credit
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000003101002"));   // VISA Debit
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000032010"));     // VISA Electron
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000033010"));     // VISA Interlink
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000038010"));     // VISA Plus
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000003999910"));   // VISA ATM

                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000041010"));     // Mastercard
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000048010"));     // Cirrus
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000043060"));     // Maestro
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000050001"));     // Maestro UK
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A00000002401"));       // Self Service
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000025"));         // American Express
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000025010104"));   // American Express
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A000000025010701"));   // ExpressPay
                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000291010"));     // Link

                    applicationIdentifiers.Add(Helpers.HexStringToBytes("B012345678"));         // Maestro TEST

                    applicationIdentifiers.Add(Helpers.HexStringToBytes("A0000000651010"));     // JCB
                }

                // Now lets process all of the AID's we found
                if (applicationIdentifiers.Count > 0)
                {
                    foreach (byte[] AID in applicationIdentifiers)
                    {
                        List <ApplicationFileLocator> applicationFileLocators = new List <ApplicationFileLocator>();
                        StringBuilder sb = new StringBuilder();

                        cardReader.Connect(selectedReader);

                        // Select AID
                        apdu     = new APDUCommand(0x00, 0xA4, 0x04, 0x00, AID, (byte)AID.Length);
                        response = cardReader.Transmit(apdu);

                        // Get response nescesary
                        if (response.SW1 == 0x61)
                        {
                            apdu     = new APDUCommand(0x00, 0xC0, 0x00, 0x00, null, response.SW2);
                            response = cardReader.Transmit(apdu);
                        }

                        // Application not found
                        if (response.SW1 == 0x6A && response.SW2 == 0x82)
                        {
                            continue;
                        }

                        if (response.SW1 == 0x90)
                        {
                            foreach (byte b in AID)
                            {
                                sb.AppendFormat("{0:X2}", b);
                            }

                            TreeNode applicationNode = new TreeNode(String.Format("Application {0}", sb.ToString()));
                            applicationNode.ImageIndex         = 1;
                            applicationNode.SelectedImageIndex = 1;
                            applicationNode.Tag = AID;
                            cardNode.Nodes.Add(applicationNode);

                            fciNode                    = new TreeNode("File Control Information");
                            fciNode.ImageIndex         = 3;
                            fciNode.SelectedImageIndex = 3;
                            fciNode.Tag                = "fci";
                            applicationNode.Nodes.Add(fciNode);

                            fci = new ASN1(response.Data);
                            AddRecordNodes(fci, fciNode);

                            // Get processing options (with empty PDOL)
                            apdu     = new APDUCommand(0x80, 0xA8, 0x00, 0x00, new byte[] { 0x83, 0x00 }, 0x02);
                            response = cardReader.Transmit(apdu);

                            // Get response nescesary
                            if (response.SW1 == 0x61)
                            {
                                apdu     = new APDUCommand(0x00, 0xC0, 0x00, 0x00, null, response.SW2);
                                response = cardReader.Transmit(apdu);
                            }

                            if (response.SW1 == 0x90)
                            {
                                ASN1 template = new ASN1(response.Data);
                                ASN1 aip      = null;
                                ASN1 afl      = null;

                                // Primative response (Template Format 1)
                                if (template.Tag[0] == 0x80)
                                {
                                    byte[] tempAIP = new byte[2];
                                    Buffer.BlockCopy(template.Value, 0, tempAIP, 0, 2);
                                    aip = new ASN1(0x82, tempAIP);

                                    byte[] tempAFL = new byte[template.Length - 2];
                                    Buffer.BlockCopy(template.Value, 2, tempAFL, 0, template.Length - 2);
                                    afl = new ASN1(0x94, tempAFL);
                                }

                                // constructed data object response (Template Format 2)
                                if (template.Tag[0] == 0x77)
                                {
                                    aip = template.Find(0x82);
                                    afl = template.Find(0x94);
                                }

                                // Chop up AFL's
                                for (int i = 0; i < afl.Length; i += 4)
                                {
                                    byte[] AFL = new byte[4];
                                    Buffer.BlockCopy(afl.Value, i, AFL, 0, 4);

                                    ApplicationFileLocator fileLocator = new ApplicationFileLocator(AFL);
                                    applicationFileLocators.Add(fileLocator);
                                }

                                TreeNode aipaflNode = new TreeNode("Application Interchange Profile - Application File Locator");
                                aipaflNode.ImageIndex         = 3;
                                aipaflNode.SelectedImageIndex = 3;
                                aipaflNode.Tag = "aip";
                                applicationNode.Nodes.Add(aipaflNode);

                                ASN1 aipafl = new ASN1(response.Data);
                                AddRecordNodes(aipafl, aipaflNode);

                                foreach (ApplicationFileLocator file in applicationFileLocators)
                                {
                                    int r  = file.FirstRecord;// +afl.OfflineRecords;     // We'll read SDA records too
                                    int lr = file.LastRecord;

                                    byte p2 = (byte)((file.SFI << 3) | 4);

                                    TreeNode efNode = new TreeNode(String.Format("Elementary File - {0:X2}", file.SFI));
                                    efNode.ImageIndex         = 2;
                                    efNode.SelectedImageIndex = 2;
                                    efNode.Tag = file.SFI;
                                    applicationNode.Nodes.Add(efNode);

                                    while (r <= lr)
                                    {
                                        apdu     = new APDUCommand(0x00, 0xB2, (byte)r, p2, null, 0x00);
                                        response = cardReader.Transmit(apdu);

                                        // Retry with correct length
                                        if (response.SW1 == 0x6C)
                                        {
                                            apdu     = new APDUCommand(0x00, 0xB2, (byte)r, p2, null, response.SW2);
                                            response = cardReader.Transmit(apdu);
                                        }

                                        TreeNode recordNode = new TreeNode(String.Format(" Record - {0:X2}", r));

                                        if (r <= file.OfflineRecords)
                                        {
                                            recordNode.ImageIndex         = 5;
                                            recordNode.SelectedImageIndex = 5;
                                        }
                                        else
                                        {
                                            recordNode.ImageIndex         = 4;
                                            recordNode.SelectedImageIndex = 4;
                                        }

                                        recordNode.Tag = r;
                                        efNode.Nodes.Add(recordNode);

                                        ASN1 record = new ASN1(response.Data);
                                        AddRecordNodes(record, recordNode);

                                        r++;
                                    }
                                }

                                //IEnumerable<XElement> tags = tagsDocument.Descendants().Where(el => el.Name == "Tag");
                                //foreach (XElement element in tags)
                                //{
                                //    string tag = element.Attribute("Tag").Value;

                                //    // Only try GET_DATA on two byte tags
                                //    if (tag.Length == 4)
                                //    {
                                //        byte p1 = byte.Parse(tag.Substring(0, 2), NumberStyles.HexNumber);
                                //        byte p2 = byte.Parse(tag.Substring(2, 2), NumberStyles.HexNumber);

                                //        apdu = new APDUCommand(0x80, 0xCA, p1, p2, null, 0);
                                //        response = cardReader.Transmit(apdu);

                                //        if (response.SW1 == 0x90)
                                //        {
                                //            Debug.WriteLine(response.ToString());
                                //        }
                                //    }
                                //}

                                apdu     = new APDUCommand(0x80, 0xCA, 0x9f, 0x13, null, 0);
                                response = cardReader.Transmit(apdu);
                                Debug.WriteLine(response.ToString());
                                apdu     = new APDUCommand(0x80, 0xCA, 0x9f, 0x17, null, 0);
                                response = cardReader.Transmit(apdu);
                                Debug.WriteLine(response.ToString());
                                apdu     = new APDUCommand(0x80, 0xCA, 0x9f, 0x36, null, 0);
                                response = cardReader.Transmit(apdu);
                                Debug.WriteLine(response.ToString());
                            }
                            else
                            {
                                // Unexpected status word
                                UpdateStatusLabel(String.Format("Unexpected response from GET PROCESSING OPTIONS command: 0x{0:X2}{1:X2}", response.SW1, response.SW2));
                            }
                        }
                        else
                        {
                            // Unexpected status word
                            UpdateStatusLabel(String.Format("Unexpected response from SELECT command: 0x{0:X2}{1:X2}", response.SW1, response.SW2));
                        }

                        cardReader.Disconnect();
                    }
                }

                treeViewData.Invoke(new UpdateTreeViewDelegate(UpdateTreeView), new object[] { treeView });
            }
            catch (PCSCException ex)
            {
                UpdateStatusLabel(ex.Message);
                return;
            }
            finally
            {
                UseHourglass(false);
                UpdateStatusLabel("Ready");
            }
        }