137 lines
3.8 KiB
Java
137 lines
3.8 KiB
Java
package com.tangem.domain.cardReader;
|
|
|
|
import com.tangem.util.Util;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.util.Arrays;
|
|
|
|
public class ResponseApdu {
|
|
|
|
private int mSw1 = 0x00;
|
|
private int mSw2 = 0x00;
|
|
|
|
private byte[] mData = new byte[0];
|
|
private byte[] mBytes = new byte[0];
|
|
|
|
private TLVList tlvList = new TLVList();
|
|
|
|
private String parseError = null;
|
|
|
|
private ResponseApdu() {
|
|
}
|
|
|
|
ResponseApdu(byte[] respApdu) {
|
|
if (respApdu.length < 2) {
|
|
return;
|
|
}
|
|
if (respApdu.length > 2) {
|
|
mData = new byte[respApdu.length - 2];
|
|
System.arraycopy(respApdu, 0, mData, 0, respApdu.length - 2);
|
|
|
|
try {
|
|
tlvList = TLVList.fromBytes(mData);
|
|
} catch (TLVException e) {
|
|
parseError = e.getMessage();
|
|
}
|
|
|
|
}else{
|
|
tlvList=new TLVList();
|
|
parseError=null;
|
|
}
|
|
mSw1 = 0x00FF & respApdu[respApdu.length - 2];
|
|
mSw2 = 0x00FF & respApdu[respApdu.length - 1];
|
|
mBytes = respApdu;
|
|
}
|
|
|
|
public static boolean isStatusWord(byte[] respApdu, int SW)
|
|
{
|
|
int mSw1 = 0x00FF & respApdu[respApdu.length - 2];
|
|
int mSw2 = 0x00FF & respApdu[respApdu.length - 1];
|
|
return ((mSw1 << 8) | mSw2)==SW;
|
|
}
|
|
|
|
public static ResponseApdu Decrypt(byte[] data, byte[] key) throws Exception{
|
|
|
|
if( data.length==2 )
|
|
{
|
|
ResponseApdu responseApdu = new ResponseApdu();
|
|
responseApdu.mSw1 = ((int) data[0] & 0xFF);
|
|
responseApdu.mSw2 = ((int) data[1] & 0xFF);
|
|
return responseApdu;
|
|
}else if( data.length>=18 ){
|
|
byte[] decryptedData = CardCrypto.Decrypt(key, Arrays.copyOfRange(data, 0, data.length - 2),true);
|
|
|
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(decryptedData);
|
|
byte[] baLength = new byte[2];
|
|
inputStream.read(baLength);
|
|
int length = ((int) baLength[0] & 0xFF) * 256 + ((int) baLength[1] & 0xFF);
|
|
if (length > decryptedData.length - 4)
|
|
throw new Exception("Can't decrypt - data size invalid");
|
|
byte[] baCRC = new byte[2];
|
|
inputStream.read(baCRC);
|
|
byte[] answerData = new byte[length];
|
|
inputStream.read(answerData);
|
|
byte[] crc = Util.calculateCRC16(answerData);
|
|
if (!Arrays.equals(baCRC, crc)) throw new Exception("Can't decrypt - crc invalid");
|
|
|
|
ResponseApdu responseApdu = new ResponseApdu();
|
|
responseApdu.mSw1 = ((int) data[data.length - 2] & 0xFF);
|
|
responseApdu.mSw2 = ((int) data[data.length - 1] & 0xFF);
|
|
responseApdu.mBytes = data;
|
|
responseApdu.mData = answerData;
|
|
|
|
try {
|
|
responseApdu.tlvList = TLVList.fromBytes(answerData);
|
|
} catch (TLVException e) {
|
|
responseApdu.parseError = e.getMessage();
|
|
}
|
|
|
|
return responseApdu;
|
|
}else{
|
|
throw new Exception("Can't decrypt - data size to small");
|
|
}
|
|
}
|
|
|
|
|
|
public int getSW1() {
|
|
return mSw1;
|
|
}
|
|
|
|
public int getSW2() {
|
|
return mSw2;
|
|
}
|
|
|
|
public int getSW1SW2() {
|
|
return (mSw1 << 8) | mSw2;
|
|
}
|
|
|
|
public byte[] getData() {
|
|
return mData;
|
|
}
|
|
|
|
public TLVList getTLVs() {
|
|
return tlvList;
|
|
}
|
|
|
|
public boolean isParsedWithError() {
|
|
return parseError != null;
|
|
}
|
|
public String getParseErroMessage() {
|
|
return parseError;
|
|
}
|
|
public byte[] toBytes() {
|
|
return mBytes;
|
|
}
|
|
|
|
public boolean isStatus(int sw1sw2) {
|
|
if (getSW1SW2() == sw1sw2) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public String getSW1SW2Description() {
|
|
return SW.getDescription(getSW1SW2());
|
|
}
|
|
}
|