/// <summary> /// /// </summary> /// <returns></returns> public CommandAPDU CreateExternalAuthCommand() { MemoryStream memStream = new MemoryStream(); memStream.Write(mInitUpdateResponse, 12, 8); memStream.Write(mHostChallenge, 0, mHostChallenge.Length); byte[] hostCryptogram = CryptoUtil.FullTripleDESMAC(mSessionKeys.RetrieveKey(Key.KEY_TYPE_ENC), CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, CryptoUtil.DESPad(memStream.ToArray())); int P1 = mSecurityLevel; CommandAPDU externalAuth = new CommandAPDU(CLA_SECURE_GP, INS_EXT_AUTH, P1, 0x00, hostCryptogram); mSecureChannel = new SecureChannel(mSessionKeys, SecurityLevel.C_MAC, mSCPIdentifier, mSCPImplementationOption, CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK); externalAuth = mSecureChannel.wrap(externalAuth); return(externalAuth); }
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()); }
/// <summary> /// /// </summary> /// <param name="keys"></param> /// <param name="replaceExisting"></param> /// <param name="keyFormat"></param> /// <returns></returns> public CommandAPDU CreatePutKeyCommand(List <Key> keys, bool replaceExisting, bool addKCV, int keyFormat) { int p1; int p2; if (keyFormat == KEY_FORMAT_2) { throw new Exception("Format 2 is reserved for futrue use."); } if (keyFormat != KEY_FORMAT_1) { throw new Exception("Unknown format"); } int prevId = -1; for (int i = 0; i < keys.Count; i++) { Key key = keys[i]; if (i > 1) { if (key.KeyId != prevId + 1) { throw new Exception("Key Identifiers must sequentially increment. See See Global Platform 2.1.1 Card Spec section 9.8.2.3.1"); } } prevId = key.KeyId; } if (replaceExisting) { p1 = keys[0].KeyVersion; } else { p1 = 0; } p2 = keys[0].KeyId; // Multiple keys if (keys.Count > 1) { p2 |= 0x80; } Key kek = null; if (mSCPIdentifier == SCP_01) { kek = new Key(mStaticKeys.KekKey.BuildTripleDesKey()); } else if (mSCPIdentifier == SCP_02) { kek = new Key(mSessionKeys.KekKey.BuildTripleDesKey()); } MemoryStream allKeyData = new MemoryStream(); allKeyData.WriteByte((byte)keys[0].KeyVersion); for (int i = 0; i < keys.Count; i++) { Key key = keys[i]; byte[] keyDataBytes = EncodeKeyData(key, kek, addKCV, keyFormat); allKeyData.Write(keyDataBytes, 0, keyDataBytes.Length); } CommandAPDU putKeyCommand = new CommandAPDU(CLA_GP, INS_PUT_KEY, p1, p2, allKeyData.ToArray(), 0x00); putKeyCommand = mSecureChannel.wrap(putKeyCommand); return(putKeyCommand); }
/// <summary> /// Generates INITIALIZE UPDATE command with specified static key set. /// </summary> /// <param name="staticKeySet">Secure channel static key set</param> /// <param name="securityLevel">Security level. It must be a valid combination of /// security level bit pattern defined in <see cref="SecurityLevel"/>.</param> /// <param name="scpIdentifier">Secure Channel Identifier according to Global Platform 2.1.1 Card Spec section 8.6. /// Currently SCP '01' and SCP '02' is supported. Use <see cref="SCP_ANY"/> if you are not sure.</param> /// <param name="scpImplementationOption">Secure Channel Implementation Option according to /// Global Platform 2.1.1 Card Spec section D.1.1 for SCP '01' or section E.1.1 for SCP '02'. Use <see cref="IMPL_OPTION_ANY"/> /// along with <see cref="SCP_ANY"/> for Secure Channel Identifier, if you are not sure.</param> /// <returns>CommandAPDU for INITIALIZE UPDATE command for specified static key set</returns> public CommandAPDU CreateInitUpdateCommand(KeySet staticKeySet, int securityLevel, int scpIdentifier, int scpImplementationOption) { // Validate Secure Channel Identifier if ((scpIdentifier != SCP_01) && (scpIdentifier != SCP_02) && (scpIdentifier != SCP_ANY)) { throw new Exception( "Invalid secure channel protocol identifier. Currently SCP 01 (0x01) and SCP 02 (0x02) are valid." + " See Global Platform 2.1.1 Card Spec section 8.6."); } //Validate Secure Channel Implementation Option if (scpImplementationOption == IMPL_OPTION_ANY && scpIdentifier != SCP_ANY) { throw new Exception( "Secure Channel Implementation Option IMPL_OPTION_ANY can only be used along with Secure Channel Identifier SCP_ANY."); } if (scpIdentifier == SCP_ANY) { if (scpImplementationOption != IMPL_OPTION_I_05 && scpImplementationOption != IMPL_OPTION_I_15 && scpImplementationOption != IMPL_OPTION_ANY) { throw new Exception( "Invalid implementation option. Only IMPL_OPTION_I_05, IMPL_OPTION_I_15 or IMPL_OPTION_ANY can be used along with SCP_ANY."); } } // Validate Secure Channel Implementation Option for SCP 01 if (scpIdentifier == SCP_01) { if ((scpImplementationOption != IMPL_OPTION_I_05) && (scpImplementationOption != IMPL_OPTION_I_15)) { throw new Exception( "Invalid implementation option for SCP 01. See Global Platform 2.1.1 Card Spec section D.1.1."); } } // Validate Secure Channel Implementation Option for SCP 02 if (scpIdentifier == SCP_02) { if ((scpImplementationOption != IMPL_OPTION_I_04) && (scpImplementationOption != IMPL_OPTION_I_05) && (scpImplementationOption != IMPL_OPTION_I_0A) && (scpImplementationOption != IMPL_OPTION_I_0B) && (scpImplementationOption != IMPL_OPTION_I_14) && (scpImplementationOption != IMPL_OPTION_I_15) && (scpImplementationOption != IMPL_OPTION_I_1A) && (scpImplementationOption != IMPL_OPTION_I_1B)) { throw new Exception( "Invalid implementation option for SCP 02. See Global Platform 2.1.1 Card Spec section E.1.1."); } if ((scpImplementationOption == IMPL_OPTION_I_0A) || (scpImplementationOption == IMPL_OPTION_I_0B) || (scpImplementationOption == IMPL_OPTION_I_1A) || (scpImplementationOption == IMPL_OPTION_I_1B)) { throw new Exception("Implicit secure channel can't be initialized explicitly."); } } mSCPIdentifier = scpIdentifier; mSCPImplementationOption = scpImplementationOption; mStaticKeys = staticKeySet; mSecurityLevel = securityLevel; // C-DECRYPTION allways come with C-MAC if ((securityLevel & SecurityLevel.C_DECRYPTION) != 0) { securityLevel |= SecurityLevel.C_MAC; } // Validate security level if (securityLevel != (SecurityLevel.NO_SECURITY_LEVEL) && securityLevel != (SecurityLevel.C_DECRYPTION | SecurityLevel.C_MAC | SecurityLevel.R_MAC) && securityLevel != (SecurityLevel.C_MAC | SecurityLevel.R_MAC) && securityLevel != (SecurityLevel.R_MAC) && securityLevel != (SecurityLevel.C_DECRYPTION | SecurityLevel.C_MAC) && securityLevel != (SecurityLevel.C_MAC)) { throw new Exception( "Invalid security level. See Global Platform 2.1.1 Card Spec section E.5.2.3 or section D.4.2.3."); } // Host challenge mHostChallenge = new byte[8]; RandomNumberGenerator rng = RandomNumberGenerator.Create(); rng.GetBytes(mHostChallenge); // Build INITIALIZE UPDATE command CommandAPDU initUpdate = new CommandAPDU(CLA_GP, INS_INIT_UPDATE, staticKeySet.KeyVersion, staticKeySet.KeyId, mHostChallenge, 0x00); return(initUpdate); }
/// <summary> /// /// </summary> /// <param name="keys"></param> /// <param name="replaceExisting"></param> /// <param name="keyFormat"></param> /// <returns></returns> public CommandAPDU CreatePutKeyCommand(List<Key> keys, bool replaceExisting, bool addKCV, int keyFormat) { int p1; int p2; if (keyFormat == KEY_FORMAT_2) throw new Exception("Format 2 is reserved for futrue use."); if (keyFormat != KEY_FORMAT_1) throw new Exception("Unknown format"); int prevId = -1; for (int i = 0; i < keys.Count; i++) { Key key = keys[i]; if (i > 1) if (key.KeyId != prevId + 1) throw new Exception("Key Identifiers must sequentially increment. See See Global Platform 2.1.1 Card Spec section 9.8.2.3.1"); prevId = key.KeyId; } if (replaceExisting) p1 = keys[0].KeyVersion; else { p1 = 0; } p2 = keys[0].KeyId; // Multiple keys if (keys.Count > 1) p2 |= 0x80; Key kek = null; if (mSCPIdentifier == SCP_01) kek = new Key(mStaticKeys.KekKey.BuildTripleDesKey()); else if(mSCPIdentifier == SCP_02) { kek = new Key(mSessionKeys.KekKey.BuildTripleDesKey()); } MemoryStream allKeyData = new MemoryStream(); allKeyData.WriteByte((byte)keys[0].KeyVersion); for (int i = 0; i < keys.Count; i++) { Key key = keys[i]; byte[] keyDataBytes = EncodeKeyData(key, kek, addKCV, keyFormat); allKeyData.Write(keyDataBytes, 0, keyDataBytes.Length); } CommandAPDU putKeyCommand = new CommandAPDU(CLA_GP, INS_PUT_KEY, p1, p2, allKeyData.ToArray(), 0x00); putKeyCommand = mSecureChannel.wrap(putKeyCommand); return putKeyCommand; }
/// <summary> /// /// </summary> /// <returns></returns> public CommandAPDU CreateExternalAuthCommand() { MemoryStream memStream = new MemoryStream(); memStream.Write(mInitUpdateResponse, 12, 8); memStream.Write(mHostChallenge, 0, mHostChallenge.Length); byte[] hostCryptogram = CryptoUtil.FullTripleDESMAC(mSessionKeys.RetrieveKey(Key.KEY_TYPE_ENC), CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, CryptoUtil.DESPad(memStream.ToArray())); int P1 = mSecurityLevel; CommandAPDU externalAuth = new CommandAPDU(CLA_SECURE_GP, INS_EXT_AUTH, P1, 0x00, hostCryptogram); mSecureChannel = new SecureChannel(mSessionKeys, SecurityLevel.C_MAC, mSCPIdentifier, mSCPImplementationOption, CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK); externalAuth = mSecureChannel.wrap(externalAuth); return externalAuth; }
/// <summary> /// Generates INITIALIZE UPDATE command with specified static key set. /// </summary> /// <param name="staticKeySet">Secure channel static key set</param> /// <param name="securityLevel">Security level. It must be a valid combination of /// security level bit pattern defined in <see cref="SecurityLevel"/>.</param> /// <param name="scpIdentifier">Secure Channel Identifier according to Global Platform 2.1.1 Card Spec section 8.6. /// Currently SCP '01' and SCP '02' is supported. Use <see cref="SCP_ANY"/> if you are not sure.</param> /// <param name="scpImplementationOption">Secure Channel Implementation Option according to /// Global Platform 2.1.1 Card Spec section D.1.1 for SCP '01' or section E.1.1 for SCP '02'. Use <see cref="IMPL_OPTION_ANY"/> /// along with <see cref="SCP_ANY"/> for Secure Channel Identifier, if you are not sure.</param> /// <returns>CommandAPDU for INITIALIZE UPDATE command for specified static key set</returns> public CommandAPDU CreateInitUpdateCommand(KeySet staticKeySet, int securityLevel, int scpIdentifier, int scpImplementationOption) { // Validate Secure Channel Identifier if ((scpIdentifier != SCP_01) && (scpIdentifier != SCP_02) && (scpIdentifier != SCP_ANY)) throw new Exception( "Invalid secure channel protocol identifier. Currently SCP 01 (0x01) and SCP 02 (0x02) are valid." + " See Global Platform 2.1.1 Card Spec section 8.6."); //Validate Secure Channel Implementation Option if (scpImplementationOption == IMPL_OPTION_ANY && scpIdentifier != SCP_ANY) throw new Exception( "Secure Channel Implementation Option IMPL_OPTION_ANY can only be used along with Secure Channel Identifier SCP_ANY."); if (scpIdentifier == SCP_ANY) { if (scpImplementationOption != IMPL_OPTION_I_05 && scpImplementationOption != IMPL_OPTION_I_15 && scpImplementationOption != IMPL_OPTION_ANY) throw new Exception( "Invalid implementation option. Only IMPL_OPTION_I_05, IMPL_OPTION_I_15 or IMPL_OPTION_ANY can be used along with SCP_ANY."); } // Validate Secure Channel Implementation Option for SCP 01 if (scpIdentifier == SCP_01) if ((scpImplementationOption != IMPL_OPTION_I_05) && (scpImplementationOption != IMPL_OPTION_I_15)) throw new Exception( "Invalid implementation option for SCP 01. See Global Platform 2.1.1 Card Spec section D.1.1."); // Validate Secure Channel Implementation Option for SCP 02 if (scpIdentifier == SCP_02) { if ((scpImplementationOption != IMPL_OPTION_I_04) && (scpImplementationOption != IMPL_OPTION_I_05) && (scpImplementationOption != IMPL_OPTION_I_0A) && (scpImplementationOption != IMPL_OPTION_I_0B) && (scpImplementationOption != IMPL_OPTION_I_14) && (scpImplementationOption != IMPL_OPTION_I_15) && (scpImplementationOption != IMPL_OPTION_I_1A) && (scpImplementationOption != IMPL_OPTION_I_1B)) throw new Exception( "Invalid implementation option for SCP 02. See Global Platform 2.1.1 Card Spec section E.1.1."); if ((scpImplementationOption == IMPL_OPTION_I_0A) || (scpImplementationOption == IMPL_OPTION_I_0B) || (scpImplementationOption == IMPL_OPTION_I_1A) || (scpImplementationOption == IMPL_OPTION_I_1B)) throw new Exception("Implicit secure channel can't be initialized explicitly."); } mSCPIdentifier = scpIdentifier; mSCPImplementationOption = scpImplementationOption; mStaticKeys = staticKeySet; mSecurityLevel = securityLevel; // C-DECRYPTION allways come with C-MAC if ((securityLevel & SecurityLevel.C_DECRYPTION) != 0) securityLevel |= SecurityLevel.C_MAC; // Validate security level if (securityLevel != (SecurityLevel.NO_SECURITY_LEVEL) && securityLevel != (SecurityLevel.C_DECRYPTION | SecurityLevel.C_MAC | SecurityLevel.R_MAC) && securityLevel != (SecurityLevel.C_MAC | SecurityLevel.R_MAC) && securityLevel != (SecurityLevel.R_MAC) && securityLevel != (SecurityLevel.C_DECRYPTION | SecurityLevel.C_MAC) && securityLevel != (SecurityLevel.C_MAC)) throw new Exception( "Invalid security level. See Global Platform 2.1.1 Card Spec section E.5.2.3 or section D.4.2.3."); // Host challenge mHostChallenge = new byte[8]; RandomNumberGenerator rng = RandomNumberGenerator.Create(); rng.GetBytes(mHostChallenge); // Build INITIALIZE UPDATE command CommandAPDU initUpdate = new CommandAPDU(CLA_GP, INS_INIT_UPDATE, staticKeySet.KeyVersion, staticKeySet.KeyId, mHostChallenge, 0x00); return initUpdate; }
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())); }