public void deleteAID(AID aid, bool deleteDeps) { ByteArrayOutputStream bo = new ByteArrayOutputStream(); try { bo.Write((byte)0x4F); bo.Write((byte)aid.getLength()); bo.Write(aid.getBytes()); } catch (IOException ioe) { throw new Exception(ioe.Message); } GPInstallRequest delete = new GPInstallRequest(GPInstructionEnum.Delete, bo.ToByteArray(), 0x00, (byte)(deleteDeps ? 0x80 : 0x00)); GPInstallResponse response = (GPInstallResponse)SendCommand(delete); if (response.SW != (ushort)ISO7816ReturnCodes.SW_NO_ERROR) { throw new Exception("Deletion failed"); } }
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); } }
private byte[] getConcatenatedStatus(GPRegistry reg, byte p1, byte[] data) { // By default use tags byte p2 = (byte)(reg.tags ? 0x02 : 0x00); GPGetStatusRequest cmd = new GPGetStatusRequest(data, p1, p2); GPGetStatusResponse response = (GPGetStatusResponse)SendCommand(cmd); // Workaround for legacy cards, like SCE 6.0 FIXME: this does not work properly // Find a different way to adjust the response parser without touching the overall spec mode // If ISD-s are asked and none is returned, it could be either // - SSD // - no support for tags if (p1 == 0x80 && response.SW == 0x6A86) { if (p2 == 0x02) { // If no support for tags. Re-issue command without requesting tags reg.tags = false; return(getConcatenatedStatus(reg, p1, data)); } } int sw = response.SW; if ((sw != (int)ISO7816ReturnCodes.SW_NO_ERROR) && (sw != 0x6310)) { // Possible values: if (sw == 0x6A88) { // No data to report return(response.ResponseData); } // 0x6A86 - no tags support or ISD asked from SSD // 0a6A81 - Same as 6A88 ? //logger.warn("GET STATUS failed for " + HexUtils.bin2hex(cmd.getBytes()) + " with " + Integer.toHexString(sw)); return(response.ResponseData); } ByteArrayOutputStream bo = new ByteArrayOutputStream(); try { bo.Write(response.ResponseData); while (response.SW == 0x6310) { cmd = new GPGetStatusRequest(data, p1, (byte)(p2 | 0x01)); response = (GPGetStatusResponse)SendCommand(cmd); sw = response.SW; if ((sw != (int)ISO7816ReturnCodes.SW_NO_ERROR) && (sw != 0x6310)) { throw new Exception("GET STATUS failed for " + Formatting.ByteArrayToHexString(cmd.Serialize())); } bo.Write(response.ResponseData); } } catch (Exception e) { throw e; } return(bo.ToByteArray()); }
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); } }