static private void init(byte[] base_key)
        {
            byte bMSB;
            byte block_size   = 0;
            byte rb_xor_value = 0;

            /*BYTE abSavedInitVktr[16];
             * DWORD t, i;*/
            int i = 0;

            /*KEY_ISO_AES*/
            rb_xor_value = 0x87;
            block_size   = 16;

            cmac_subkey_0 = AESEncrypt(base_key, init_vector, cmac_subkey_0);
            LogManager.DoLogOperation(string.Format("K0={0}", BinConvert.ToHex(cmac_subkey_0)));
            Array.Copy(cmac_subkey_0, 0, cmac_subkey_1, 0, cmac_subkey_0.Length);
            // If the MSBit of the generated cipher == 1 -> K1 = (cipher << 1) ^ Rb ...
            // store MSB:
            bMSB = cmac_subkey_1[0];

            // Shift the complete cipher for 1 bit ==> K1:
            for (i = 0; i < (int)(block_size - 1); i++)
            {
                cmac_subkey_1[i] <<= 1;
                // add the carry over bit:
                cmac_subkey_1[i] |= (byte)(((cmac_subkey_1[i + 1] & 0x80) == 0x80 ? 0x01 : 0x00));
            }
            cmac_subkey_1[block_size - 1] <<= 1;
            if ((bMSB & 0x80) == 0x80)
            {
                // XOR with Rb:
                cmac_subkey_1[block_size - 1] ^= rb_xor_value;
            }

            // store MSB:
            bMSB = cmac_subkey_1[0];

            // Shift K1 ==> K2:
            for (i = 0; i < (int)(block_size - 1); i++)
            {
                cmac_subkey_2[i]  = (byte)(cmac_subkey_1[i] << 1);
                cmac_subkey_2[i] |= (byte)(((cmac_subkey_1[i + 1] & 0x80) == 0x80 ? 0x01 : 0x00));
            }
            cmac_subkey_2[block_size - 1] = (byte)(cmac_subkey_1[block_size - 1] << 1);

            if ((bMSB & 0x80) == 0x80)
            {
                // XOR with Rb:
                cmac_subkey_2[block_size - 1] ^= rb_xor_value;
            }
        }
        static public int EjectCard()
        {
            if (m_hCard.Connected == false)
            {
                LogManager.DoLogOperation("[ERROR] can't disconnect from the card");
                return(ERROR_INSERT_CARD);
            }
            m_hCard.DisconnectReset();
            //m_hCard.Dispose();

            LogManager.DoLogOperation("[INFO] Disconnected from the card");

            return(ERROR_NO_ERROR);
        }
        static public int InsertCard()
        {
            m_hCard = new SCardChannel(m_ReaderList[_reader_id]);

            if (m_hCard == null)
            {
                return(ERROR_INSERT_CARD);
            }

            if (!m_hCard.ConnectExclusive())
            {
                LogManager.DoLogOperation("[ERROR] can't connect to the card");
                //m_hCard.Dispose();
                return(ERROR_INSERT_CARD);
            }
            LogManager.DoLogOperation("[INFO] Connected to the card");


            return(ERROR_NO_ERROR);
        }
        private static bool Transmit(byte[] command, out byte[] response)
        {
            CAPDU capdu = new CAPDU(command);
            RAPDU rapdu = m_hCard.Transmit(capdu);

            response = null;
            if (rapdu == null)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] fails to transmit"));
                return(false);
            }
            response = new byte[rapdu.Length];
            Array.Copy(rapdu.Bytes, 0, response, 0, rapdu.Length);
            if (rapdu.SW != 0x9000)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] failed " + SCARD.CardStatusWordsToString(rapdu.SW) + "(" + SCARD.CardStatusWordsToString(rapdu.SW) + ")"));
                return(false);
            }


            return(true);
        }
        static int Main(string[] args)
        {
            LogManager.InstantiateLogManager();
            _aes_master_key = "";
            //_aes_new_master_key = "";
            _aes_base_key = "";
            _aes_owner_divert_root_key = "";
            _iso_enable = false;
            Logger.ReadArgs(args);

            //Logger.ConsoleLevel = Logger.Level.Info;
            Console.Title = string.Format("{0} {1} v.{2}", Application.CompanyName, Application.ProductName, Application.ProductVersion);

            if (args.Length > 0)
            {
                if (!ParseArgs(args))
                {
                    LogManager.DoLogOperation("[ERROR] Fails to parse argument !!!");

                    Console.WriteLine("Hit any key to exit.");
                    Console.ReadKey();
                    return(ERROR_PARSE_ERROR);
                }
            }
            else
            {
                goto done;
            }


done:

            m_ReaderList = new List <string>();
            int i = 0;

            if (SCARD.Readers == null)
            {
                return(ERROR_READER_ERROR);
            }
            for (i = 0; i < SCARD.Readers.Length - 1; i++)
            {
                m_ReaderList.Add(SCARD.Readers[i]);
            }

            if (SCARD.Readers.Length == 0)
            {
                LogManager.DoLogOperation("[ERROR] No PCSC reader available !!!");
                return(ERROR_READER_ERROR);
            }
            m_ReaderList.Add(SCARD.Readers[SCARD.Readers.Length - 1]);

            #region format
            if ((_actions_to_do & ActionToDo.actFormat) != 0)
            {
                LogManager.DoLogOperation("[INFO] Formatting Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_aes_master_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --master-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);
                    if (m_Desfire.Format())
                    {
                        LogManager.DoLogOperation("[INFO] DUEINFO Done ...");
                    }

                    EjectCard();
                }
            }
            #endregion

            #region new
            if ((_actions_to_do & ActionToDo.actNew) != 0)
            {
                LogManager.DoLogOperation("[INFO] Creating new DUEINFO Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_aes_base_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set DUEINFO base key for diversification. Add --dueinfo-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (_aes_master_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --master-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);
                    //m_Desfire.AesNewKeyMaster = BinConvert.HexToBytes(_aes_new_master_key);
                    m_Desfire.AesKeyDueInfo = BinConvert.HexToBytes(_aes_base_key);
                    m_Desfire.Escn          = BinConvert.HexToBytes(_escn_id);
                    if (m_Desfire.Create())
                    {
                        LogManager.DoLogOperation("[INFO] DUEINFO Done ...");
                    }

                    EjectCard();
                }
            }
            #endregion
            #region erase
            else if ((_actions_to_do & ActionToDo.actDisable) != 0)
            {
                LogManager.DoLogOperation("[INFO] Erasing DUEINFO Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    if (_aes_master_key.Length == 32)
                    {
                        m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);

                        if (m_Desfire.Disable())
                        {
                            LogManager.DoLogOperation("[INFO] DUEINFO is disabled ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion

            #region read
            else if ((_actions_to_do & ActionToDo.actRead) != 0)
            {
                LogManager.DoLogOperation("[INFO] Reading DUEINFO Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    if (_iso_enable == false)
                    {
                        m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                        m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                        if (m_Desfire.Read(ref _escn, ref _signature, ref _certificate))
                        {
                            LogManager.DoLogOperation("[INFO] Read Done ...");
                        }
                    }
                    else
                    {
                        if (Iso_Read(ref _escn, ref _signature, ref _certificate))
                        {
                            LogManager.DoLogOperation("[INFO] Read Done ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion

            #region check
            else if ((_actions_to_do & ActionToDo.actCheck) != 0)
            {
                LogManager.DoLogOperation("[INFO] Checking DUEINFO Desfire Card...");

                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                /* read data from card */
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping           = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire               = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);
                    m_Desfire.AesKeyDueInfo = BinConvert.HexToBytes(_aes_base_key);

                    if (m_Desfire.Read(ref _escn, ref _signature, ref _certificate))
                    {
                        LogManager.DoLogOperation("[INFO] Read Done ...");
                        if (m_Desfire.Check(_escn, _signature, _certificate))
                        {
                            LogManager.DoLogOperation("[INFO] Card is from DUEINFO ...");
                        }
                        else
                        {
                            LogManager.DoLogOperation("ERROR Card is out of DUEINFO ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion
            #region diversification
            else if ((_actions_to_do & ActionToDo.actDiversification) != 0)
            {
                LogManager.DoLogOperation("[INFO] Check AES 128 diversification...");

                if (_aes_base_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --base=XXXX...X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (_escn_id.Length == 0)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set ESCn. Add --escn=XX.. to console command.");
                    return(ERROR_READER_ERROR);
                }
                byte[] diversified_key   = new byte[16];
                byte[] data_to_diversify = BinConvert.HexToBytes(_escn_id);
                DueInfo.Diversification.Diversification_AES128(BinConvert.HexToBytes(_aes_base_key),
                                                               data_to_diversify, data_to_diversify.Length, ref diversified_key);
            }
            #endregion

            #region load_aes_master_keys
            if ((_actions_to_do & ActionToDo.actLoadMasterKey) != 0)
            {
                LogManager.DoLogOperation("[INFO] Load Master and DAM keys...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_aes_master_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --master-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }


                if (_aes_owner_divert_root_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a root key for diversification. Add --base=XXXX...X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_card_uid.Length == 0)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set card uid for diversification. Add --uid=XXXX...X to console command.");
                    return(ERROR_READER_ERROR);
                }

                byte[] UID = BinConvert.HexToBytes(_card_uid);

                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);

                    byte[] diversified_key = new byte[16];

                    m_Desfire.DAMAuthKey = new byte[16];// BinConvert.HexToBytes(_dam_auth_key);
                    DueInfo.Diversification.Diversification_AES128(
                        BinConvert.HexToBytes(_aes_owner_divert_root_key),
                        UID, UID.Length, ref diversified_key);
                    Array.Copy(diversified_key, 0, m_Desfire.DAMAuthKey, 0, 16);
                    LogManager.DoLogOperation("[INFO] PICCDAMAuthKey " + BinConvert.ToHex(m_Desfire.DAMAuthKey));

                    byte[] data_to_diversify = BinConvert.HexToBytes(_card_uid);
                    data_to_diversify[0] = 0x00;
                    m_Desfire.DAMENCKey  = new byte[16]; //BinConvert.HexToBytes(_dam_enc_key);
                    DueInfo.Diversification.Diversification_AES128(
                        BinConvert.HexToBytes(_aes_owner_divert_root_key),
                        data_to_diversify, data_to_diversify.Length, ref diversified_key);
                    Array.Copy(diversified_key, 0, m_Desfire.DAMENCKey, 0, 16);
                    LogManager.DoLogOperation("[INFO] PICCDAMEncKey " + BinConvert.ToHex(m_Desfire.DAMENCKey));

                    data_to_diversify    = BinConvert.HexToBytes(_card_uid);
                    data_to_diversify[0] = 0xFF;

                    m_Desfire.DAMMACKey = new byte[16]; //BinConvert.HexToBytes(_dam_mac_key);
                    DueInfo.Diversification.Diversification_AES128(
                        BinConvert.HexToBytes(_aes_owner_divert_root_key),
                        data_to_diversify, data_to_diversify.Length, ref diversified_key);
                    Array.Copy(diversified_key, 0, m_Desfire.DAMMACKey, 0, 16);
                    LogManager.DoLogOperation("[INFO] PICCDAMMACKey " + BinConvert.ToHex(m_Desfire.DAMMACKey));

                    /* we do this to be sure that masker key is AES type, needed for PICCDAMKEY */
                    if (m_Desfire.ChangeMasterKeyToAES())
                    {
                        LogManager.DoLogOperation("[INFO] Master key set to AES ...");
                        if (m_Desfire.LoadPICCDAMKeys())
                        {
                            LogManager.DoLogOperation("[INFO] PICC DAM keys loaded ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion
            #region request_web
            if ((_actions_to_do & ActionToDo.actDammac) != 0)
            {
                LogManager.DoLogOperation("[INFO] Create DAMMAC...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (_dam_auth_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set PICCDAMAUTHKEY. Add --master-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.DAMAuthKey = BinConvert.HexToBytes(_dam_auth_key);

                    LogManager.DoLogOperation("[INFO] Create DAMMAC ...");
                    if (m_Desfire.CreateDammacRequest())
                    {
                        LogManager.DoLogOperation("[INFO] DAMMAC JSON REQUEST is created ...");
                    }

                    EjectCard();
                }
            }

            #endregion request_web
            #region dam
            if ((_actions_to_do & ActionToDo.actNewDam) != 0)
            {
                LogManager.DoLogOperation("[INFO] Create delegated application...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (_dam_auth_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set DAMAuthKey. Add --x-damauth-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (_dam_enck.Length == 0)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set EncK. Add --n-enck=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }
                if (_dam_dammac.Length != 16)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set DAMMAC. Add --q-dammac=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }


                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.DAMAuthKey = BinConvert.HexToBytes(_dam_auth_key);
                    m_Desfire.EncK       = BinConvert.HexToBytes(_dam_enck);
                    m_Desfire.DAMMAC     = BinConvert.HexToBytes(_dam_dammac);

                    LogManager.DoLogOperation("[INFO] Create DAM ...");
                    if (m_Desfire.AddDelegatedApplication())
                    {
                        LogManager.DoLogOperation("[INFO] DAM is created ...");
                    }

                    EjectCard();
                }
            }
            if ((_actions_to_do & ActionToDo.actNewDamAlone) != 0)
            {
                LogManager.DoLogOperation("[INFO] Create delegated application alone...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_dam_auth_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set DAMAuthKey. Add --x-damauth-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (_dam_mac_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a DAMMAC key. Add --y-dammac-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }
                if (_dam_enc_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a Encryption key. Add --z-damenc-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.DAMAuthKey = BinConvert.HexToBytes(_dam_auth_key);
                    m_Desfire.DAMENCKey  = BinConvert.HexToBytes(_dam_enc_key);
                    m_Desfire.DAMMACKey  = BinConvert.HexToBytes(_dam_mac_key);

                    LogManager.DoLogOperation("[INFO] Create DAM ...");
                    if (m_Desfire.AddDelegatedApplicationWithoutWebService())
                    {
                        LogManager.DoLogOperation("[INFO] DAM is created ...");
                    }

                    EjectCard();
                }
            }
            if ((_actions_to_do & ActionToDo.actFreeDam) != 0)
            {
                LogManager.DoLogOperation("[INFO] Free delegated application...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }


                if (_dam_auth_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set DAMAuthKey. Add --x-damauth-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);
                    m_Desfire.DAMAuthKey   = BinConvert.HexToBytes(_dam_auth_key);

                    LogManager.DoLogOperation("[INFO] Delete DAM ...");
                    if (m_Desfire.FormatDelegatedApplication())
                    {
                        LogManager.DoLogOperation("[INFO] DAM is formatted ...");
                    }

                    EjectCard();
                }
            }
            if ((_actions_to_do & ActionToDo.actEraseDam) != 0)
            {
                LogManager.DoLogOperation("[INFO] Erase delegated application...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_aes_master_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --master-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfireEv2.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfireEv2(m_hCard, m_isoWrapping);

                    m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);

                    LogManager.DoLogOperation("[INFO] Delete DAM ...");
                    if (m_Desfire.EraseDelegatedApplication())
                    {
                        LogManager.DoLogOperation("[INFO] DAM is deleted ...");
                    }

                    EjectCard();
                }
            }

            #endregion
            #region list
            if ((_actions_to_do & ActionToDo.actList) != 0)
            {
                LogManager.DoLogOperation("[INFO]List PCSC readers...");
                for (i = 0; i < m_ReaderList.Count; i++)
                {
                    LogManager.DoLogOperation(string.Format("[INFO]\t{0:X02}\t{1}", i, m_ReaderList[i]));
                }
            }
            #endregion
            #region pause
            if ((_actions_to_do & ActionToDo.actPause) != 0)
            {
                Console.WriteLine("Hit any key to exit.");
                Console.ReadKey();
            }
            #endregion
            return(ERROR_NO_ERROR);
        }
        private static bool Iso_Read(ref byte[] escn, ref byte[] sign, ref byte[] cert)
        {
            byte[] SELECT_APP  = new byte[] { 0x00, 0xA4, 0x04, 0x00, 0x09, 0xA0, 0x00, 0x00, 0x06, 0x14, 0x04, 0xF5, 0x88, 0x40, 0x00 };
            byte[] SELECT_ESCN = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x10, 0x01 };
            byte[] SELECT_SIGN = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x10, 0x02 };
            byte[] SELECT_CERT = new byte[] { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x10, 0x03 };

            byte[] READ_ESCN = new byte[] { 0x00, 0xB0, 0x00, 0x00, 0x00 };
            byte[] READ_SIGN = new byte[] { 0x00, 0xB0, 0x00, 0x00, 0x00 };
            byte[] READ_CERT = new byte[] { 0x00, 0xB0, 0x00, 0x00, 0x00 };


            byte[] response;

            /* DUEINFO, select by its ISO name */
            LogManager.DoLogOperation("[DEBUG] Select DUEINFO Application");
            if (Transmit(SELECT_APP, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] Select DUEINFO Application"));
                return(false);
            }

            /* ESCN */
            LogManager.DoLogOperation("[DEBUG] SELECT ESCN FILE 0x1001");
            if (Transmit(SELECT_ESCN, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] Select ESCN File"));
                return(false);
            }
            LogManager.DoLogOperation("[DEBUG] READ ESCN FILE 0x1001");
            if (Transmit(READ_ESCN, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] READ ESCN File"));
                return(false);
            }
            escn = new byte[response.Length - 2];
            Array.Copy(response, 0, escn, 0, escn.Length);
            LogManager.DoLogOperation(BinConvert.ToHex(escn));

            /* SIGNATURE */
            LogManager.DoLogOperation("[DEBUG] SELECT SIGNATURE FILE 0x1002");
            if (Transmit(SELECT_SIGN, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] Select SIGNATURE File"));
                return(false);
            }

            LogManager.DoLogOperation("[DEBUG] READ SIGNATURE FILE 0x1002");
            if (Transmit(READ_ESCN, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] READ ESCN File"));
                return(false);
            }
            sign = new byte[response.Length - 2];
            Array.Copy(response, 0, sign, 0, sign.Length);
            LogManager.DoLogOperation(BinConvert.ToHex(sign));

            /* CERTIFICATE */
            LogManager.DoLogOperation("[DEBUG] SELECT CERTIFICATE FILE 0x1003");
            if (Transmit(SELECT_CERT, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] Select CERTIFICATE File"));
                return(false);
            }
            LogManager.DoLogOperation("[DEBUG] READ CERTIFICATE FILE 0x1003");
            if (Transmit(READ_CERT, out response) == false)
            {
                LogManager.DoLogOperation(string.Format("[ERROR] READ ESCN File"));
                return(false);
            }
            cert = new byte[response.Length - 2];
            Array.Copy(response, 0, cert, 0, cert.Length);
            LogManager.DoLogOperation(BinConvert.ToHex(cert));

            return(true);
        }
Esempio n. 7
0
        static public int Diversification_AES128(byte[] base_key, byte[] diversification_input, int diversification_lenght, ref byte[] diversified_key)
        {
            int i = 0;

            byte[] M    = new byte[32];
            bool   padd = false;

            // prepare the padding
            init(base_key);
#if _DEBUG_DIVERSIFICATION
            LogManager.DoLogOperation(string.Format("TEST K0={0}", BinConvert.ToHex(cmac_subkey_0)));
            LogManager.DoLogOperation(string.Format("TEST K1={0}", BinConvert.ToHex(cmac_subkey_1)));
            LogManager.DoLogOperation(string.Format("TEST K2={0}", BinConvert.ToHex(cmac_subkey_2)));
#endif

            // add the div constant at the beginning of M
            M[0] = 0x01;
            for (i = 0; i < diversification_lenght; i++)
            {
                M[1 + i] = diversification_input[i];
            }
            i++;

            // add the padding
            if (((i % 32) != 0) && (i < 32))
            {
                M[i] = 0x80;
                i++;
                for (; i < 32; i++)
                {
                    M[i] = 0x00;
                }
                padd = true;
            }
#if _DEBUG_DIVERSIFICATION
            LogManager.DoLogOperation(string.Format("CMAC Input D={0}", BinConvert.ToHex(M, 32)));
#endif

            /* XOR the last 16 bytes with CMAC_SubKey */
            for (i = 0; i < 16; i++)
            {
                if (padd)
                {
                    M[16 + i] ^= cmac_subkey_2[i];
                }
                else
                {
                    M[16 + i] ^= cmac_subkey_1[i];
                }
            }


#if _DEBUG_DIVERSIFICATION
            LogManager.DoLogOperation(string.Format("XOR the last 16 bytes with CMAC_SubKey2={0}", BinConvert.ToHex(M, 32)));
            int lsize = 32;
#endif

            byte[] IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };


            /* Encryption using M */
            byte[] result = AES_Encrypt(M, base_key, IV);

#if _DEBUG_DIVERSIFICATION
            LogManager.DoLogOperation(string.Format("Encryption using M={0}", BinConvert.ToHex(M, lsize)));
#endif

            for (i = 0; i < 16; i++)
            {
                diversified_key[i] = result[16 + i];
            }

#if _DEBUG_DIVERSIFICATION
            LogManager.DoLogOperation(string.Format("Diversification key={0}", BinConvert.ToHex(diversified_key, 16)));
#endif

            return(0);
        }
Esempio n. 8
0
        static int Main(string[] args)
        {
            LogManager.InstantiateLogManager();
            _aes_master_key = "";
            _aes_base_key   = "";
            _iso_enable     = false;
            Logger.ReadArgs(args);

            //Logger.ConsoleLevel = Logger.Level.Info;
            Console.Title = string.Format("{0} {1} v.{2}", Application.CompanyName, Application.ProductName, Application.ProductVersion);

            if (args.Length > 0)
            {
                if (!ParseArgs(args))
                {
                    LogManager.DoLogOperation("[ERROR] Fails to parse argument !!!");

                    Console.WriteLine("Hit any key to exit.");
                    Console.ReadKey();
                    return(ERROR_PARSE_ERROR);
                }
            }
            else
            {
                goto done;
            }


done:

            m_ReaderList = new List <string>();
            int i = 0;

            if (SCARD.Readers == null)
            {
                return(ERROR_READER_ERROR);
            }
            for (i = 0; i < SCARD.Readers.Length - 1; i++)
            {
                m_ReaderList.Add(SCARD.Readers[i]);
            }

            if (SCARD.Readers.Length == 0)
            {
                LogManager.DoLogOperation("[ERROR] No PCSC reader available !!!");
                return(ERROR_READER_ERROR);
            }
            m_ReaderList.Add(SCARD.Readers[SCARD.Readers.Length - 1]);

            #region new
            if ((_actions_to_do & ActionToDo.actNew) != 0)
            {
                LogManager.DoLogOperation("[INFO] Creating new DUEINFO Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                if (_aes_base_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set DUEINFO base key for diversification. Add --dueinfo-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (_aes_master_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --master-key=XXXX...X to console command.");
                    return(ERROR_PARSE_ERROR);
                }

                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfire.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfire(m_hCard, m_isoWrapping);

                    m_Desfire.AesKeyMaster  = BinConvert.HexToBytes(_aes_master_key);
                    m_Desfire.AesKeyDueInfo = BinConvert.HexToBytes(_aes_base_key);
                    m_Desfire.Escn          = BinConvert.HexToBytes(_escn_id);
                    if (m_Desfire.Create())
                    {
                        LogManager.DoLogOperation("[INFO] DUEINFO Done ...");
                    }

                    EjectCard();
                }
            }
            #endregion
            #region erase
            else if ((_actions_to_do & ActionToDo.actDisable) != 0)
            {
                LogManager.DoLogOperation("[INFO] Erasing DUEINFO Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping = DueInfoDesfire.DF_ISO_WRAPPING_CARD;
                    m_Desfire     = new DueInfoDesfire(m_hCard, m_isoWrapping);

                    if (_aes_master_key.Length == 32)
                    {
                        m_Desfire.AesKeyMaster = BinConvert.HexToBytes(_aes_master_key);

                        if (m_Desfire.Disable())
                        {
                            LogManager.DoLogOperation("[INFO] DUEINFO is disabled ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion

            #region read
            else if ((_actions_to_do & ActionToDo.actRead) != 0)
            {
                LogManager.DoLogOperation("[INFO] Reading DUEINFO Desfire Card...");
                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    if (_iso_enable == false)
                    {
                        m_isoWrapping = DueInfoDesfire.DF_ISO_WRAPPING_CARD;
                        m_Desfire     = new DueInfoDesfire(m_hCard, m_isoWrapping);

                        if (m_Desfire.Read(ref _escn, ref _signature, ref _certificate))
                        {
                            LogManager.DoLogOperation("[INFO] Read Done ...");
                        }
                    }
                    else
                    {
                        if (Iso_Read(ref _escn, ref _signature, ref _certificate))
                        {
                            LogManager.DoLogOperation("[INFO] Read Done ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion

            #region check
            else if ((_actions_to_do & ActionToDo.actCheck) != 0)
            {
                LogManager.DoLogOperation("[INFO] Checking DUEINFO Desfire Card...");

                if (_reader_id == -1)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a reader. Add --reader=X to console command.");
                    return(ERROR_READER_ERROR);
                }

                /* read data from card */
                if (InsertCard() == ERROR_NO_ERROR)
                {
                    m_isoWrapping           = DueInfoDesfire.DF_ISO_WRAPPING_CARD;
                    m_Desfire               = new DueInfoDesfire(m_hCard, m_isoWrapping);
                    m_Desfire.AesKeyDueInfo = BinConvert.HexToBytes(_aes_base_key);

                    if (m_Desfire.Read(ref _escn, ref _signature, ref _certificate))
                    {
                        LogManager.DoLogOperation("[INFO] Read Done ...");
                        if (m_Desfire.Check(_escn, _signature, _certificate))
                        {
                            LogManager.DoLogOperation("[INFO] Card is from DUEINFO ...");
                        }
                        else
                        {
                            LogManager.DoLogOperation("ERROR Card is out of DUEINFO ...");
                        }
                    }

                    EjectCard();
                }
            }
            #endregion
            #region diversification
            else if ((_actions_to_do & ActionToDo.actDiversification) != 0)
            {
                LogManager.DoLogOperation("[INFO] Check AES 128 diversification...");

                if (_aes_base_key.Length != 32)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set a base key. Add --base=XXXX...X to console command.");
                    return(ERROR_READER_ERROR);
                }
                if (_escn_id.Length == 0)
                {
                    LogManager.DoLogOperation("[WARNING] You have to set ESCn. Add --escn=XX.. to console command.");
                    return(ERROR_READER_ERROR);
                }
                byte[] diversified_key   = new byte[16];
                byte[] data_to_diversify = BinConvert.HexToBytes(_escn_id);
                DueInfo.Diversification.Diversification_AES128(BinConvert.HexToBytes(_aes_base_key),
                                                               data_to_diversify, data_to_diversify.Length, ref diversified_key);
            }
            #endregion


            #region list
            if ((_actions_to_do & ActionToDo.actList) != 0)
            {
                LogManager.DoLogOperation("[INFO]List PCSC readers...");
                for (i = 0; i < m_ReaderList.Count; i++)
                {
                    LogManager.DoLogOperation(string.Format("[INFO]\t{0:X02}\t{1}", i, m_ReaderList[i]));
                }
            }
            #endregion
            #region pause
            if ((_actions_to_do & ActionToDo.actPause) != 0)
            {
                Console.WriteLine("Hit any key to exit.");
                Console.ReadKey();
            }
            #endregion
            return(ERROR_NO_ERROR);
        }