private byte[] EncodeKeyData(Key key, Key kek, bool addKCV, int keyFormat)
        {
            MemoryStream keyData = new MemoryStream();

            if (keyFormat == KEY_FORMAT_1)
            {
                // Key encryption algorithm
                keyData.WriteByte(CryptoUtil.ALG_DES);

                // Encrypted key data length
                keyData.WriteByte(0x10);

                byte[] encryptedKey = CryptoUtil.TripleDESECB(kek, key.Value, CryptoUtil.MODE_ENCRYPT);
                keyData.Write(encryptedKey, 0, encryptedKey.Length);

                if (addKCV)
                {
                    // KCV length
                    keyData.WriteByte(0x03);

                    // Calculate KCV
                    byte[] kcv = CryptoUtil.TripleDESECB(new Key(key.BuildTripleDesKey()),
                                                         CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK,
                                                         CryptoUtil.MODE_ENCRYPT);
                    keyData.Write(kcv, 0, 3);
                }
                else
                {
                    keyData.WriteByte(0x00);
                }
            }

            return(keyData.ToArray());
        }
        private KeySet GenerateSessionKeysSCP01(byte[] cardResponse)
        {
            KeySet sessionKeySet = new KeySet();

            byte[] derivationData = new byte[16];

            System.Array.Copy(cardResponse, 16, derivationData, 0, 4);
            System.Array.Copy(mHostChallenge, 0, derivationData, 4, 4);
            System.Array.Copy(cardResponse, 12, derivationData, 8, 4);
            System.Array.Copy(mHostChallenge, 4, derivationData, 12, 4);

            sessionKeySet.EncKey =
                new Key(CryptoUtil.TripleDESECB(new Key(mStaticKeys.EncKey.BuildTripleDesKey()), derivationData,
                                                CryptoUtil.MODE_ENCRYPT));
            sessionKeySet.MacKey =
                new Key(CryptoUtil.TripleDESECB(new Key(mStaticKeys.MacKey.BuildTripleDesKey()), derivationData,
                                                CryptoUtil.MODE_ENCRYPT));
            sessionKeySet.KekKey = new Key(mStaticKeys.KekKey.Value);

            return(sessionKeySet);
        }
        public CommandAPDU wrap(CommandAPDU command)
        {
            // Apply R-MAC
            if ((mSecurityLevel & net.SecurityLevel.R_MAC) != 0)
            {
                if (mRMACStream != null)
                {
                    throw new Exception("There exists an unwrapped response while R-MAC security level set. Secure channel can only work correctly if " +
                                        "for each wrapped command the corresponding response be unwrapped immediately.");
                }
                mRMACStream = new MemoryStream();

                //Clear 3 LSB of CLA
                mRMACStream.WriteByte((byte)(command.CLA & ~0x07));
                mRMACStream.WriteByte((byte)command.INS);
                mRMACStream.WriteByte((byte)command.P1);
                mRMACStream.WriteByte((byte)command.P2);
                if (command.LC > 0)
                {
                    mRMACStream.WriteByte((byte)command.LC);
                    mRMACStream.Write(command.Data, 0, command.Data.Length);
                }
            }

            if ((mSecurityLevel & (net.SecurityLevel.C_MAC | net.SecurityLevel.C_DECRYPTION)) == 0)
            {
                return(command);
            }

            int secureCLA = command.CLA;

            byte[] wrappedData     = null;
            int    wrappedDataSize = command.LC;

            MemoryStream commandStream = new MemoryStream();

            int maxCommandSize = 255;

            if ((mSecurityLevel & net.SecurityLevel.C_MAC) != 0)
            {
                maxCommandSize -= 8;
            }
            if ((mSecurityLevel & net.SecurityLevel.C_DECRYPTION) != 0)
            {
                maxCommandSize -= 8;
            }
            if (command.LC > maxCommandSize)
            {
                throw new Exception("APDU command too large. Max command length = 255 - 8(for C-MAC if present) - 8(for C-DECRYTPION padding if present).");
            }

            if ((mSecurityLevel & net.SecurityLevel.C_MAC) != 0)
            {
                if (mFirstCommandInChain)
                {
                    mFirstCommandInChain = false;
                }
                else if (mICVEncryption)
                {
                    if (mSCPIdentifier == GlobalPlatform.SCP_01)
                    {
                        mICV = CryptoUtil.TripleDESECB(new Key(mSessionKeys.MacKey.BuildTripleDesKey()), mICV,
                                                       CryptoUtil.MODE_ENCRYPT);
                    }
                    else
                    {
                        mICV = CryptoUtil.DESECB(new Key(mSessionKeys.MacKey.BuildDesKey()), mICV,
                                                 CryptoUtil.MODE_ENCRYPT);
                    }
                } // If ICV Encryption

                if (mApplyToModifiedAPDU)
                {
                    secureCLA        = command.CLA | 0x04;
                    wrappedDataSize += 8;
                }

                commandStream.WriteByte((byte)secureCLA);
                commandStream.WriteByte((byte)command.INS);
                commandStream.WriteByte((byte)command.P1);
                commandStream.WriteByte((byte)command.P2);
                commandStream.WriteByte((byte)wrappedDataSize);
                commandStream.Write(command.Data, 0, command.Data.Length);
                if (mSCPIdentifier == GlobalPlatform.SCP_01)
                {
                    mICV = CryptoUtil.FullTripleDESMAC(mSessionKeys.MacKey, mICV, CryptoUtil.DESPad(commandStream.ToArray()));
                }
                else
                {
                    mICV = CryptoUtil.SingleDESFullTripleDESMAC(mSessionKeys.MacKey, mICV, CryptoUtil.DESPad(commandStream.ToArray()));
                }

                if (!mApplyToModifiedAPDU)
                {
                    secureCLA        = command.CLA | 0x04;
                    wrappedDataSize += 8;
                }
                wrappedData   = command.Data;
                commandStream = new MemoryStream();
            } // If C-MAC

            if (((mSecurityLevel & net.SecurityLevel.C_DECRYPTION) != 0) && command.LC > 0)
            {
                if (mSCPIdentifier == GlobalPlatform.SCP_01)
                {
                    if ((command.LC + 1) % 8 != 0)
                    {
                        commandStream.WriteByte((byte)command.LC);
                        commandStream.Write(command.Data, 0, command.Data.Length);
                        byte[] paddedData = CryptoUtil.DESPad(commandStream.ToArray());
                        commandStream = new MemoryStream();
                        commandStream.Write(paddedData, 0, paddedData.Length);
                    }
                    else
                    {
                        commandStream.WriteByte((byte)command.LC);
                        commandStream.Write(command.Data, 0, command.Data.Length);
                    }
                } // If SCP '01'
                else
                {
                    byte[] paddedData = CryptoUtil.DESPad(command.Data);
                    commandStream.Write(paddedData, 0, paddedData.Length);
                }
                wrappedDataSize += (int)(commandStream.Length - command.Data.Length);
                wrappedData      = CryptoUtil.TripleDESCBC(new Key(mSessionKeys.EncKey.BuildTripleDesKey()),
                                                           CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, commandStream.ToArray(), CryptoUtil.MODE_ENCRYPT);
                commandStream = new MemoryStream();
            }  // If C-DECRYPTION
            commandStream.WriteByte((byte)secureCLA);
            commandStream.WriteByte((byte)command.INS);
            commandStream.WriteByte((byte)command.P1);
            commandStream.WriteByte((byte)command.P2);
            if (wrappedDataSize > 0)
            {
                commandStream.WriteByte((byte)wrappedDataSize);
                commandStream.Write(wrappedData, 0, wrappedData.Length);
            }

            if ((mSecurityLevel & net.SecurityLevel.C_MAC) != 0)
            {
                commandStream.Write(mICV, 0, mICV.Length);
            }
            if (command.LE > 0)
            {
                commandStream.WriteByte((byte)command.LE);
            }

            return(new CommandAPDU(commandStream.ToArray()));
        }