private KeySet GenerateSessionKeysSCP02(byte[] sequenceCoutner) { KeySet sessionKeySet = new KeySet(); byte[] derivationData = new byte[16]; System.Array.Copy(sequenceCoutner, 0, derivationData, 2, 2); System.Array.Clear(derivationData, 4, 12); // Todo: consider implicit case // Derivate session MAC key System.Array.Copy(CONSTANT_MAC_0101, 0, derivationData, 0, 2); sessionKeySet.MacKey = new Key(CryptoUtil.TripleDESCBC(new Key(mStaticKeys.MacKey.BuildTripleDesKey()), CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, derivationData, CryptoUtil.MODE_ENCRYPT)); // Derivate session R-MAC key // To build R-MAC key static MAC key is used. System.Array.Copy(CONSTANT_RMAC_0102, 0, derivationData, 0, 2); sessionKeySet.RmacKey = new Key(CryptoUtil.TripleDESCBC(new Key(mStaticKeys.MacKey.BuildTripleDesKey()), CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, derivationData, CryptoUtil.MODE_ENCRYPT)); // Derivate session ENC key System.Array.Copy(CONSTANT_ENC_0182, 0, derivationData, 0, 2); sessionKeySet.EncKey = new Key(CryptoUtil.TripleDESCBC(new Key(mStaticKeys.EncKey.BuildTripleDesKey()), CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, derivationData, CryptoUtil.MODE_ENCRYPT)); // Derivate session KEK key System.Array.Copy(CONSTANT_DEK_0181, 0, derivationData, 0, 2); sessionKeySet.KekKey = new Key(CryptoUtil.TripleDESCBC(new Key(mStaticKeys.KekKey.BuildTripleDesKey()), CryptoUtil.BINARY_ZEROS_8_BYTE_BLOCK, derivationData, CryptoUtil.MODE_ENCRYPT)); 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())); }