public override byte[] Wrap(GPCommand command) { byte[] cmd_mac = null; try { if (!mac && !enc) { return(command.Serialize()); } int cla = command.CLA; int lc = command.CommandData.Length; byte[] data = command.CommandData; // Encrypt if needed if (enc) { cla = 0x84; // Counter shall always be incremented Buffer_increment(encryption_counter); if (command.CommandData.Length > 0) { byte[] d = Pad80(command.CommandData, 16); // Encrypt with S-ENC, after increasing the counter byte[] iv = GPCrypto.DoEncrypt_AES_CBC(sessionKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), encryption_counter); data = GPCrypto.DoEncrypt_AES_CBC(sessionKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), d, iv); //Cipher c = Cipher.getInstance(GPCrypto.AES_CBC_CIPHER); //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeySessionType.ENC), GPCrypto.null_bytes_16); //byte[] iv = c.doFinal(encryption_counter); // Now encrypt the data with S-ENC. //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeySessionType.ENC), new IvParameterSpec(iv)); //data = c.doFinal(d); lc = data.Length; } } // Calculate C-MAC if (mac) { cla = 0x84; lc = lc + 8; ByteArrayOutputStream bo = new ByteArrayOutputStream(); bo.Write(chaining_value); bo.Write(cla); bo.Write(command.INS); bo.Write(command.P1); bo.Write(command.P2); bo.Write(lc); bo.Write(data); byte[] cmac_input = bo.ToByteArray(); byte[] cmac = Scp03_mac(sessionKeys.GetKey(KeySessionType.MAC), cmac_input, 128); // Set new chaining value Array.Copy(cmac, 0, chaining_value, 0, chaining_value.Length); // 8 bytes for actual mac cmd_mac = Arrays.CopyOf(cmac, 8); } // Construct new command ByteArrayOutputStream na = new ByteArrayOutputStream(); na.Write(cla); // possibly fiddled na.Write(command.INS); na.Write(command.P1); na.Write(command.P2); na.Write(lc); na.Write(data); if (mac) { na.Write(cmd_mac); } return(na.ToByteArray()); } catch (Exception e) { throw new Exception("APDU wrapping failed", e); } }
public override byte[] Wrap(GPCommand command) { try { if (!mac && !enc) { return(command.Serialize()); } if (rmac) { rMac.Reset(); rMac.Write(ClearBits((byte)command.CLA, (byte)0x07)); rMac.Write(command.INS); rMac.Write(command.P1); rMac.Write(command.P2); if (command.CommandData.Length >= 0) { rMac.Write(command.CommandData.Length); rMac.Write(command.CommandData); } } byte origCLA = command.CLA; byte newCLA = origCLA; byte origINS = command.INS; byte origP1 = command.P1; byte origP2 = command.P2; byte[] origData = command.CommandData; byte origLc = (byte)command.CommandData.Length; byte newLc = origLc; byte[] newData = null; byte le = command.Le.Value; ByteArrayOutputStream t = new ByteArrayOutputStream(); if (origLc > GetBlockSize()) { throw new Exception("APDU too long for wrapping."); } if (mac) { if (icv == null) { icv = new byte[8]; } else if (icvEnc) { //IBufferedCipher c = null; if (scp == 1) { icv = GPCrypto.DoEncrypt_DES3_ECB(sessionKeys.GetKeyFor(KeySessionType.MAC).GetEncoded(), icv); //c = Cipher.getInstance(GPCrypto.DES3_ECB_CIPHER); //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeyType.MAC)); } else { icv = GPCrypto.DoEncrypt_DES_ECB(sessionKeys.GetKey(KeySessionType.MAC).GetKey(KeyType.DES).GetEncoded(), icv); //c = Cipher.getInstance(GPCrypto.DES_ECB_CIPHER); //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKey(KeyType.MAC).getKey(Type.DES)); } // encrypts the future ICV ? //icv = c.doFinal(icv); } if (preAPDU) { newCLA = SetBits((byte)newCLA, (byte)0x04); newLc = (byte)(newLc + 8); } t.Write(newCLA); t.Write(origINS); t.Write(origP1); t.Write(origP2); t.Write(newLc); t.Write(origData); if (scp == 1) { icv = Mac_3des(sessionKeys.GetKey(KeySessionType.MAC), t.ToByteArray(), icv); } else if (scp == 2) { icv = Mac_des_3des(sessionKeys.GetKey(KeySessionType.MAC), t.ToByteArray(), icv); } if (postAPDU) { newCLA = SetBits((byte)newCLA, (byte)0x04); newLc = (byte)(newLc + 8); } t.Reset(); newData = origData; } if (enc && (origLc > 0)) { if (scp == 1) { t.Write(origLc); t.Write(origData); if ((t.Size() % 8) != 0) { byte[] x = Pad80(t.ToByteArray(), 8); t.Reset(); t.Write(x); } } else { t.Write(Pad80(origData, 8)); } newLc += (byte)(t.Size() - origData.Length); //Cipher c = Cipher.getInstance(GPCrypto.DES3_CBC_CIPHER); //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeyType.ENC), GPCrypto.iv_null_des); //newData = c.doFinal(t.toByteArray()); newData = GPCrypto.DoEncrypt_DES3_CBC(sessionKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), t.ToByteArray()); t.Reset(); } t.Write(newCLA); t.Write(origINS); t.Write(origP1); t.Write(origP2); if (newLc > 0) { t.Write(newLc); t.Write(newData); } if (mac) { t.Write(icv); } if (le > 0) { t.Write(le); } return(t.ToByteArray()); } catch (Exception e) { throw new Exception("APDU wrapping failed", e); } }