Пример #1
0
        public static void Main(string[] args)
        {
            bool   p_erase        = false;
            bool   p_prepare      = false;
            bool   p_lock         = false;
            bool   p_batch        = false;
            bool   p_continue     = false;
            string p_key          = null;
            int    p_key_type     = 0;
            string p_set_key      = null;
            int    p_set_key_type = 0;
            string p_reader       = null;
            int    p_size         = 0;
            bool   p_list         = false;

            bool nfc_verbose = false;
            bool nfc_silent  = false;

            byte[] blank_buffer = new byte[32];

            byte[] key_buffer = new byte[24];
            int    key_length = 0;

            byte[] set_key_buffer = new byte[24];
            int    set_key_length = 0;

            int    rc;
            UInt32 ndef_size;
            UInt32 cc_size = 32;

            Getopt g = new Getopt("NfcToolDesfire", args, "epwz:k:t:s:r:bclvqh");

            int c;

            while ((c = g.getopt()) != -1)
            {
                switch (c)
                {
                case 'e': p_erase = true; break;

                case 'p': p_prepare = true; break;

                case 'w': p_lock = true; break;

                case 'z': p_size = Int32.Parse(g.Optarg);
                    break;

                case 'k': p_key = g.Optarg;
                    break;

                case 't': p_key_type = Int32.Parse(g.Optarg);
                    break;

                case 's': p_set_key = g.Optarg;
                    break;

                case 'n': p_set_key_type = Int32.Parse(g.Optarg);
                    break;

                case 'r': p_reader = g.Optarg;
                    break;

                case 'l': p_list = true; break;

                case 'b': p_batch = true; break;

                case 'c': p_continue = true; break;

                case 'v': nfc_verbose = true; break;

                case 'q': nfc_silent = true; break;

                case 'h': hello();
                    usage();
                    return;

                case '?': hello();
                    helpmsg("Incorrect parameter(s)", nfc_silent);
                    return;

                default: hello();
                    helpmsg("Invalid command line.", nfc_silent);
                    return;
                }
            }


            if (!nfc_silent)
            {
                hello();
            }

            if (p_list)
            {
                string reader_list = "";
                for (int i = 0; i < SCARD.Readers.Length - 1; i++)
                {
                    reader_list += "Reader " + i + "=" + SCARD.Readers[i] + "  -  ";
                }
                reader_list += "Reader " + (SCARD.Readers.Length - 1) + "=" + SCARD.Readers[SCARD.Readers.Length - 1];
                Console.WriteLine(reader_list);
                return;
            }

            /* Check the minimum mandatory parameters */
            if ((!p_erase) && (!p_prepare) && (!p_lock))
            {
                helpmsg("No mode specified, nothing to do!", nfc_silent);
                return;
            }

            if ((p_erase || p_prepare) && (p_lock))
            {
                helpmsg("Multiple modes specified, choose one!", nfc_silent);
                return;
            }

            /* Retrieve the key(s) */
            if (p_erase || p_prepare)
            {
                if (p_key == null)
                {
                    if (nfc_verbose)
                    {
                        Console.WriteLine("Key not specified, using default");
                    }

                    key_buffer = new byte[24];
                    for (int i = 0; i < key_buffer.Length; i++)
                    {
                        key_buffer[i] = 0;
                    }

                    key_length = 8;
                }
                else
                {
                    CardBuffer key = new CardBuffer(p_key);
                    key_buffer = new byte[24];
                    Array.ConstrainedCopy(key.GetBytes(), 0, key_buffer, 0, key.GetBytes().Length);
                    key_length = key.GetBytes().Length;
                }

                if ((key_length != 8) && (key_length != 16) && (key_length != 24))
                {
                    helpmsg("Key: invalid parameter", nfc_silent);
                    return;
                }

                if (key_length == 8)
                {
                    Array.ConstrainedCopy(key_buffer, 0, key_buffer, 8, 8);
                    Array.ConstrainedCopy(key_buffer, 0, key_buffer, 16, 8);
                }
                else
                if (key_length == 16)
                {
                    Array.ConstrainedCopy(key_buffer, 0, key_buffer, 16, 8);
                }

                if (p_key_type == 0)
                {
                    if (key_length == 8)
                    {
                        if (!nfc_silent)
                        {
                            Console.WriteLine("Type of key not specified, assuming DES");
                        }
                        p_key_type = KEY_DES_OR_3DES;
                    }
                    else
                    if (key_length == 16)
                    {
                        if (!nfc_silent)
                        {
                            Console.WriteLine("Type of key not specified, assuming TripleDES");
                        }
                        p_key_type = KEY_DES_OR_3DES;
                    }
                    else
                    if (key_length == 24)
                    {
                        if (!nfc_silent)
                        {
                            Console.WriteLine("Type of key not specified, assuming TripleDES with 3 keys");
                        }
                        p_key_type = KEY_DES_OR_3DES_ISO;
                    }
                    else
                    {
                        helpmsg("You must specify the type of the key!", nfc_silent);
                        return;
                    }
                }


                if (p_set_key != null)
                {
                    CardBuffer set_key = new CardBuffer(p_set_key);
                    set_key_buffer = new byte[24];
                    Array.ConstrainedCopy(set_key.GetBytes(), 0, set_key_buffer, 0, set_key.GetBytes().Length);
                    set_key_length = set_key.GetBytes().Length;


                    if ((set_key_length != 8) && (set_key_length != 16) && (set_key_length != 24))
                    {
                        helpmsg("New key: invalid parameter", nfc_silent);
                        return;
                    }

                    if (set_key_length == 8)
                    {
                        Array.ConstrainedCopy(set_key_buffer, 0, set_key_buffer, 8, 8);
                        Array.ConstrainedCopy(set_key_buffer, 0, set_key_buffer, 16, 8);
                    }
                    else
                    if (set_key_length == 16)
                    {
                        Array.ConstrainedCopy(set_key_buffer, 0, set_key_buffer, 16, 8);
                    }

                    if (p_set_key_type == 0)
                    {
                        if (set_key_length == 8)
                        {
                            if (!nfc_silent)
                            {
                                Console.WriteLine("Type of new key not specified, assuming DES");
                            }
                            p_set_key_type = KEY_DES_OR_3DES;
                        }
                        else
                        if (set_key_length == 16)
                        {
                            if (!nfc_silent)
                            {
                                Console.WriteLine("Type of new key not specified, assuming TripleDES");
                            }
                            p_set_key_type = KEY_DES_OR_3DES;
                        }
                        else
                        if (set_key_length == 24)
                        {
                            if (!nfc_silent)
                            {
                                Console.WriteLine("Type of new key not specified, assuming TripleDES with 3 keys");
                            }
                            p_set_key_type = KEY_DES_OR_3DES_ISO;
                        }
                        else
                        {
                            helpmsg("You must specify the type of the new key!", nfc_silent);
                            return;
                        }
                    }
                }
            }

            if (p_reader == null)
            {
                helpmsg("No Reader selected!", nfc_silent);
                return;
            }


            string ReaderName;

            /* Verify the reader */
            try
            {
                ReaderName = SCARD.Readers[Int32.Parse(p_reader)];
            }
            catch
            {
                Console.WriteLine("Reader not found!");
                return;
            }
            if (p_reader == null)
            {
                Console.WriteLine("Reader not found!");
                return;
            }

            if (!nfc_silent)
            {
                Console.WriteLine("Looking for Desfire EV1 card on reader " + ReaderName);
            }


batch_begin:

            /* Connect to the card */
            SCardChannel scard = new SCardChannel(ReaderName);

            if (scard == null)
            {
                Console.WriteLine("Failed to connect to the target card.");
                if (p_batch && p_continue)
                {
                    goto batch_begin;
                }
                goto failed;
            }

            if (!scard.Connect())
            {
                Console.WriteLine("Failed to connect to the target card.");
                if (p_batch && p_continue)
                {
                    goto batch_begin;
                }
                goto failed;
            }

            /* Open the Desfire DLL */
            rc = SCARD_DESFIRE.AttachLibrary(scard.hCard);
            if (rc != SCARD.S_SUCCESS)
            {
                Console.WriteLine("Failed to instantiate the PC/SC Desfire DLL.");
                goto failed;
            }

            rc = SCARD_DESFIRE.IsoWrapping(scard.hCard, DF_ISO_WRAPPING_CARD);
            if (rc != SCARD.S_SUCCESS)
            {
                Console.WriteLine("Failed to select the ISO 7816 wrapping mode.");
                goto failed;
            }

            byte[] version_info = new byte[30];

            rc = SCARD_DESFIRE.GetVersion(scard.hCard, version_info);
            if (rc != SCARD.S_SUCCESS)
            {
                Console.WriteLine("Desfire 'get version' command failed.");
                if (p_batch && p_continue)
                {
                    goto batch_end;
                }
                goto failed;
            }

            if (!nfc_silent)
            {
                Console.WriteLine("Found a Desfire card\n");
            }

            if (nfc_verbose)
            {
                Console.WriteLine("Hardware: Vendor=" + version_info[0]
                                  + ", Type=" + version_info[1]
                                  + ", SubType=" + version_info[2]
                                  + ", v" + version_info[3] + "." + version_info[4]);

                Console.WriteLine("Software: Vendor=" + version_info[7]
                                  + ", Type=" + version_info[8]
                                  + ", SubType=" + version_info[9]
                                  + ", v" + version_info[10] + "." + version_info[11]);
            }


            if ((version_info[0] != 0x04) || (version_info[7] != 0x04))
            {
                Console.WriteLine("Manufacturer is not NXP\n");
                if (p_batch && p_continue)
                {
                    goto batch_end;
                }
                goto failed;
            }

            if ((version_info[1] != 0x01) || (version_info[8] != 0x01))
            {
                Console.WriteLine("Type is not Desfire\n");
                if (p_batch && p_continue)
                {
                    goto batch_end;
                }
                goto failed;
            }

            if (version_info[10] < 1)
            {
                Console.WriteLine("Software version is below EV1\n");
                if (p_batch && p_continue)
                {
                    goto batch_end;
                }
                goto failed;
            }

            if (p_erase || p_prepare)
            {
                if (nfc_verbose)
                {
                    Console.WriteLine("Authenticating...");
                }

                switch (p_key_type)
                {
                case KEY_DES_OR_3DES: rc = SCARD_DESFIRE.Authenticate(scard.hCard, 0, key_buffer); break;

                case KEY_DES_OR_3DES_ISO: rc = SCARD_DESFIRE.AuthenticateIso24(scard.hCard, 0, key_buffer); break;

                case KEY_AES_ISO: rc = SCARD_DESFIRE.AuthenticateAes(scard.hCard, 0, key_buffer); break;

                default: rc = -1; break;
                }
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Authentication failed");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }
                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (set_key_length > 0)
                {
                    if (nfc_verbose)
                    {
                        Console.WriteLine("Setting the new key...");
                    }

                    if ((p_key_type == KEY_DES_OR_3DES) && (p_set_key_type == KEY_DES_OR_3DES))
                    {
                        rc = SCARD_DESFIRE.ChangeKey(scard.hCard, 0, set_key_buffer, null);
                    }
                    else
                    if ((p_key_type == KEY_DES_OR_3DES) && (p_set_key_type == KEY_DES_OR_3DES_ISO))
                    {
                        rc = SCARD_DESFIRE.AuthenticateIso24(scard.hCard, 0, key_buffer);
                        if (rc == SCARD.S_SUCCESS)
                        {
                            rc = SCARD_DESFIRE.ChangeKey24(scard.hCard, 0, set_key_buffer, null);
                        }
                    }
                    else
                    if ((p_key_type == KEY_DES_OR_3DES) && (p_set_key_type == KEY_AES_ISO))
                    {
                        rc = SCARD_DESFIRE.ChangeKeyAes(scard.hCard, DF_APPLSETTING2_AES | 0, 0, set_key_buffer, null);
                    }
                    else
                    if ((p_key_type == KEY_DES_OR_3DES_ISO) && (p_set_key_type == KEY_DES_OR_3DES))
                    {
                        rc = SCARD_DESFIRE.ChangeKeyAes(scard.hCard, DF_APPLSETTING2_AES | 0, 0, blank_buffer, null);
                        if (rc == SCARD.S_SUCCESS)
                        {
                            rc = SCARD_DESFIRE.AuthenticateAes(scard.hCard, 0, blank_buffer);
                        }
                        if (rc == SCARD.S_SUCCESS)
                        {
                            rc = SCARD_DESFIRE.ChangeKey(scard.hCard, 0, set_key_buffer, null);
                        }
                    }
                    else
                    if ((p_key_type == KEY_DES_OR_3DES_ISO) && (p_set_key_type == KEY_DES_OR_3DES_ISO))
                    {
                        rc = SCARD_DESFIRE.ChangeKey24(scard.hCard, 0, set_key_buffer, null);
                    }
                    else
                    if ((p_key_type == KEY_DES_OR_3DES_ISO) && (p_set_key_type == KEY_AES_ISO))
                    {
                        rc = SCARD_DESFIRE.ChangeKeyAes(scard.hCard, DF_APPLSETTING2_AES | 0, 0, set_key_buffer, null);
                    }
                    else
                    if ((p_key_type == KEY_AES_ISO) && (p_set_key_type == KEY_DES_OR_3DES))
                    {
                        rc = SCARD_DESFIRE.ChangeKey(scard.hCard, 0, set_key_buffer, null);
                    }
                    else
                    if ((p_key_type == KEY_AES_ISO) && (p_set_key_type == KEY_DES_OR_3DES_ISO))
                    {
                        rc = SCARD_DESFIRE.ChangeKey24(scard.hCard, 0, set_key_buffer, null);
                    }
                    else
                    if ((p_key_type == KEY_AES_ISO) && (p_set_key_type == KEY_AES_ISO))
                    {
                        rc = SCARD_DESFIRE.ChangeKeyAes(scard.hCard, DF_APPLSETTING2_AES | 0, 0, set_key_buffer, null);
                    }

                    if (rc != SCARD.S_SUCCESS)
                    {
                        Console.WriteLine("Change key failed");
                        if (!nfc_silent)
                        {
                            Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                        }
                        if (p_batch && p_continue)
                        {
                            goto batch_end;
                        }
                        goto failed;
                    }

                    switch (p_set_key_type)
                    {
                    case KEY_DES_OR_3DES: rc = SCARD_DESFIRE.Authenticate(scard.hCard, 0, set_key_buffer); break;

                    case KEY_DES_OR_3DES_ISO: rc = SCARD_DESFIRE.AuthenticateIso24(scard.hCard, 0, set_key_buffer); break;

                    case KEY_AES_ISO: rc = SCARD_DESFIRE.AuthenticateAes(scard.hCard, 0, set_key_buffer); break;

                    default: rc = -1; break;
                    }
                    if (rc != SCARD.S_SUCCESS)
                    {
                        Console.WriteLine("Authentication with new key failed");
                        if (!nfc_silent)
                        {
                            Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                        }
                        if (p_batch && p_continue)
                        {
                            goto batch_end;
                        }
                        goto failed;
                    }
                }
            }


            if (p_erase)
            {
                if (nfc_verbose)
                {
                    Console.WriteLine("Formating the card...");
                }

                rc = SCARD_DESFIRE.FormatPICC(scard.hCard);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Format PICC failed\n");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }
                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (p_set_key != null)
                {
                    if (nfc_verbose)
                    {
                        Console.WriteLine("Changing the key...");
                    }
                }

                if (!nfc_silent)
                {
                    Console.WriteLine("Card erase done...");
                }
            }


            if (p_prepare)
            {
                byte[] nfc_aid           = new byte[7];
                byte[] NFC_NDEF_7816_AID = new byte[7] {
                    0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01
                };
                nfc_aid = NFC_NDEF_7816_AID;
                byte[] cc_buffer = new byte[15];

                if (nfc_verbose)
                {
                    Console.WriteLine("Creating the NFC NDEF application...");
                }

                rc = SCARD_DESFIRE.CreateIsoApplication(scard.hCard,
                                                        NFC_NDEF_DESFIRE_DF_ID,
                                                        0xFF,
                                                        DF_APPLSETTING2_ISO_EF_IDS | 0,
                                                        NFC_NDEF_7816_DF_ID,
                                                        nfc_aid,
                                                        (byte)nfc_aid.Length);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Create application failed");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }

                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (nfc_verbose)
                {
                    Console.WriteLine("Entering the NFC NDEF directory...");
                }

                rc = SCARD_DESFIRE.SelectApplication(scard.hCard, NFC_NDEF_DESFIRE_DF_ID);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Select application failed");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }
                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (nfc_verbose)
                {
                    Console.WriteLine("Creating the NFC CC file...");
                }

                rc = SCARD_DESFIRE.CreateIsoStdDataFile(scard.hCard,
                                                        NFC_NDEF_DESFIRE_CC_EF_ID,
                                                        NFC_NDEF_7816_CC_EF_ID,
                                                        0,
                                                        0xEEEE,
                                                        cc_size);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Create CC file failed");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }

                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                ndef_size = 0;
                rc        = SCARD_DESFIRE.GetFreeMemory(scard.hCard, ref ndef_size);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Get free memory failed");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }
                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (p_size != 0)
                {
                    if (ndef_size < p_size)
                    {
                        Console.WriteLine("NDEF size=" + p_size + ", bigger than available space on card (" + ndef_size + ")\n", p_size, ndef_size);
                        if (!nfc_silent)
                        {
                            Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                        }
                        if (p_batch && p_continue)
                        {
                            goto batch_end;
                        }
                        goto failed;
                    }
                    ndef_size = (UInt32)p_size;
                }

                if (nfc_verbose)
                {
                    Console.WriteLine("Creating the NFC NDEF file...");
                }

                rc = SCARD_DESFIRE.CreateIsoStdDataFile(scard.hCard,
                                                        NFC_NDEF_DESFIRE_DATA_EF_ID,
                                                        NFC_NDEF_7816_DATA_EF_ID,
                                                        0,
                                                        0xEEEE,
                                                        ndef_size);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Create NDEF file failed: " + NFC_NDEF_DESFIRE_DATA_EF_ID + "-"
                                      + NFC_NDEF_7816_DATA_EF_ID + "-" + ndef_size);
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }
                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (nfc_verbose)
                {
                    Console.WriteLine("Populating the NFC CC file...\n");
                }

                cc_buffer[0]  = 0x00;
                cc_buffer[1]  = 0x0F;
                cc_buffer[2]  = NFC_NDEF_VERSION_2;
                cc_buffer[3]  = 0x00;
                cc_buffer[4]  = 0x3B;
                cc_buffer[5]  = 0x00;
                cc_buffer[6]  = 0x34;
                cc_buffer[7]  = NDEF_FILE_CONTROL_TAG;
                cc_buffer[8]  = 0x06;
                cc_buffer[9]  = (byte)(NFC_NDEF_7816_DATA_EF_ID >> 8);
                cc_buffer[10] = (byte)(NFC_NDEF_7816_DATA_EF_ID & 0x00FF);
                cc_buffer[11] = (byte)(ndef_size >> 8);
                cc_buffer[12] = (byte)(ndef_size & 0x00FF);
                cc_buffer[13] = 0x00;
                cc_buffer[14] = 0x00;

                rc = SCARD_DESFIRE.WriteData2(scard.hCard,
                                              NFC_NDEF_DESFIRE_CC_EF_ID,
                                              0,
                                              (UInt32)cc_buffer.Length,
                                              cc_buffer);
                if (rc != SCARD.S_SUCCESS)
                {
                    Console.WriteLine("Populate CC file failed\n");
                    if (!nfc_silent)
                    {
                        Console.WriteLine(SCARD_DESFIRE.GetErrorMessage(rc));
                    }
                    if (p_batch && p_continue)
                    {
                        goto batch_end;
                    }
                    goto failed;
                }

                if (!nfc_silent)
                {
                    Console.WriteLine("Card prepare done...\n");
                }
            }


batch_end:
            SCARD_DESFIRE.DetachLibrary(scard.hCard);
            scard.Disconnect();
            return;

            /* Error */
failed:
            if (scard.hCard != null)
            {
                SCARD_DESFIRE.DetachLibrary(scard.hCard);
            }
            scard.Disconnect();
            return;
        }
Пример #2
0
        /// <summary>
        /// Callback used when the reader's status change
        /// As this method is called from a thread, you can't directly modify the user interface
        /// </summary>
        /// <param name="readerState"></param>
        /// <param name="cardAtr"></param>
        private void readerStatusChanged(uint readerState, CardBuffer cardAtr)
        {
            // When you are in a thread you can't directly modify the user interface
            if (InvokeRequired)
            {
                this.BeginInvoke(new readerStatusChangedInvoker(readerStatusChanged), readerState, cardAtr);
                return;
            }
            lblStatus.Text           = "";
            txtHardwareVendor.Text   = "";
            txtSoftwareVendor.Text   = "";
            txtApplicationsList.Text = "";

            if (cardAtr == null)
            {
                return;
            }

            channel = new SCardChannel(reader);
            //channel.ShareMode = SCARD.SHARE_EXCLUSIVE;

            if (!channel.Connect())
            {
                lblStatus.Text = "Error, can't connect to the card";
                return;
            }

            int rc = SCARD_DESFIRE.AttachLibrary(channel.hCard);

            if (rc != SCARD.S_SUCCESS)
            {
                lblStatus.Text = "Error, failed to instantiate the PC/SC Desfire DLL";
                return;
            }

            rc = SCARD_DESFIRE.IsoWrapping(channel.hCard, DF_ISO_WRAPPING_CARD);
            if (rc != SCARD.S_SUCCESS)
            {
                lblStatus.Text = "Error, failed to select the ISO 7816 wrapping mode";
                return;
            }

            // ***********************
            // * Get card's versions *
            // ***********************
            byte[] versionInfo = new byte[30];

            rc = SCARD_DESFIRE.GetVersion(channel.hCard, versionInfo);
            if (rc != SCARD.S_SUCCESS)
            {
                lblStatus.Text = "Error, Desfire 'GetVersion' command failed - error: " + rc;
                return;
            }

            lblStatus.Text = "Desfire 'GetVersion' command ok";

            txtHardwareVendor.Text = "Vendor Id: " + versionInfo[0] + CR + "Type: " + versionInfo[1] + CR + "SubType: " + versionInfo[2] + CR + "Version: " + versionInfo[3] + "." + versionInfo[4];
            txtSoftwareVendor.Text = "Vendor Id: " + versionInfo[7] + CR + "Type: " + versionInfo[8] + CR + "SubType: " + versionInfo[9] + CR + "Version: " + versionInfo[10] + "." + versionInfo[11];
            if ((versionInfo[0] != 0x04) || (versionInfo[7] != 0x04))
            {
                txtSoftwareVendor.Text += CR + "Manufacturer is not NXP";
            }

            if ((versionInfo[1] != 0x01) || (versionInfo[8] != 0x01))
            {
                txtSoftwareVendor.Text += CR + "Type is not Desfire";
            }

            if (versionInfo[10] < 1)
            {
                txtSoftwareVendor.Text += CR + "Software version is below EV1";
            }

            // *************************
            // * Get applications list *
            // *************************
            UInt32[] aidsList = new UInt32[28];
            byte     aidCount = 0;

            rc = SCARD_DESFIRE.GetApplicationIDs(channel.hCard, (byte)28, aidsList, ref aidCount);
            if (rc != SCARD.S_SUCCESS)
            {
                lblStatus.Text = "Error, Desfire 'GetApplicationIDs' command failed - error: " + rc;
                return;
            }
            txtApplicationsList.Text = "Applications'count: " + aidCount + CR;
            if (aidCount == 0)
            {
                return;
            }

            for (byte i = 0; i < aidCount; i++)
            {
                txtApplicationsList.Text += "AID: " + "0x" + aidsList[i].ToString("X6") + CR;
            }

            rc = SCARD_DESFIRE.DetachLibrary(channel.hCard);
        }