/**
* This file is part of CardApplet-VCBP which is card applet implementation
* of V Cloud-Based Payments for SimplyTapp cloud platform.
* Copyright 2014 SimplyTapp, Inc.
*
* CardApplet-VCBP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CardApplet-VCBP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CardApplet-VCBP. If not, see <http://www.gnu.org/licenses/>.
*/
package com.st.vcbp.data;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
/**
* Use AccountParamsStatic object to share data between Card Applet and Card Agent.
*
* @author SimplyTapp, Inc.
* @version 1.0
*/
final public class AccountParamsStatic implements Serializable {
private static final long serialVersionUID = 1L;
// PPSE AID
private static final byte[] AID_PPSE = {
(byte) 0x32, (byte) 0x50, (byte) 0x41, (byte) 0x59, (byte) 0x2E,
(byte) 0x53, (byte) 0x59, (byte) 0x53, (byte) 0x2E,
(byte) 0x44, (byte) 0x44, (byte) 0x46, (byte) 0x30, (byte) 0x31
};
// PPSE Response
private static final byte[] PPSE_RESPONSE = {
(byte) 0x6F, (byte) 0x23,
(byte) 0x84, (byte) 0x0E,
(byte) 0x32, (byte) 0x50, (byte) 0x41, (byte) 0x59, (byte) 0x2E,
(byte) 0x53, (byte) 0x59, (byte) 0x53, (byte) 0x2E,
(byte) 0x44, (byte) 0x44, (byte) 0x46, (byte) 0x30, (byte) 0x31,
(byte) 0xA5, (byte) 0x11,
(byte) 0xBF, (byte) 0x0C, (byte) 0x0E,
(byte) 0x61, (byte) 0x0C,
(byte) 0x4F, (byte) 0x07
};
private static final short PPSE_RESPONSE_TAG_6F_LENGTH_OFFSET = (short) 1;
private static final short PPSE_RESPONSE_TAG_A5_LENGTH_OFFSET = (short) 19;
private static final short PPSE_RESPONSE_TAG_BF0C_LENGTH_OFFSET = (short) 22;
private static final short PPSE_RESPONSE_TAG_61_LENGTH_OFFSET = (short) 24;
private static final short PPSE_RESPONSE_TAG_4F_LENGTH_OFFSET = (short) 26;
private static final byte[] PPSE_RESPONSE_TRAILER = {
(byte) 0x87, (byte) 0x01,
(byte) 0x01,
};
private byte[] aid;
private byte[] aidPpse;
private byte[] ppseResp;
private byte[] tagA5Data;
public static final short GPO_RESPONSE_OFFSET_AIP = (short) 2;
public static final short GPO_RESPONSE_OFFSET_AFL_LENGTH = (short) 5;
public static final short GPO_RESPONSE_OFFSET_AFL = (short) 6;
private byte[] gpoRespMsd;
private byte[] gpoRespQvsdc;
private HashMap<Short, byte[]> records = new HashMap<Short, byte[]>();
public static final short IAD_VALUE_OFFSET = (short) 3;
public static final short IAD_OFFSET_CVR_BYTE_1 = (short) 6;
public static final short IAD_OFFSET_DERIVATION_DATA = (short) 16;
private byte[] iad;
private byte[] psn;
public static final short CTQ_OFFSET_BYTE_1 = (short) 3;
public static final short CTQ_OFFSET_BYTE_2 = (short) 4;
private byte[] ctq;
public static final short TRACK2_OFFSET_DD = (short) 14;
private byte[] track2Data;
private byte[] cardholderName;
private byte[] cvmList;
private byte[] iccPrivKeyCrtCoefficient;
private byte[] iccPrivKeyPrimeExponentQ;
private byte[] iccPrivKeyPrimeExponentP;
private byte[] iccPrivKeyPrimeQ;
private byte[] iccPrivKeyPrimeP;
private int iccKeyModulusLength;
// Supports 1 to 255.
private int maxNumAcctParamsDynamic = 1;
// Supports 1 to 255.
private int minThresholdNumAcctParamsDynamic = 1;
// Time to Live Check Interval in Minutes
// Supports:
// - 0 = never check
// - 1-255 = check every 1-255 minutes
private int checkIntervalTimeToExp = 0;
// Supports 0-255.
private int maxTransactionVerificationLogs = 0;
public AccountParamsStatic() {
this.aidPpse = AID_PPSE;
}
public byte[] getAid() {
return this.aid;
}
public void setAid(byte[] aidBuffer, short aidOffset, byte aidLength) {
try {
this.aid = Arrays.copyOfRange(aidBuffer,
aidOffset,
aidOffset + aidLength);
}
catch (Exception e) {
this.aid = null;
return;
}
try {
this.ppseResp = new byte[PPSE_RESPONSE.length +
this.aid.length +
PPSE_RESPONSE_TRAILER.length];
ByteBuffer ppseResponseByteBuffer = ByteBuffer.wrap(this.ppseResp);
ppseResponseByteBuffer.put(PPSE_RESPONSE);
ppseResponseByteBuffer.put(this.aid);
ppseResponseByteBuffer.put(PPSE_RESPONSE_TRAILER);
if (aidLength != (byte) 7) {
byte aidLengthDiff = (byte) (aidLength - 7);
this.ppseResp[PPSE_RESPONSE_TAG_6F_LENGTH_OFFSET] += aidLengthDiff;
this.ppseResp[PPSE_RESPONSE_TAG_A5_LENGTH_OFFSET] += aidLengthDiff;
this.ppseResp[PPSE_RESPONSE_TAG_BF0C_LENGTH_OFFSET] += aidLengthDiff;
this.ppseResp[PPSE_RESPONSE_TAG_61_LENGTH_OFFSET] += aidLengthDiff;
this.ppseResp[PPSE_RESPONSE_TAG_4F_LENGTH_OFFSET] += aidLengthDiff;
}
}
catch (Exception e) {
this.ppseResp = null;
}
}
public byte[] getAidPpse() {
return this.aidPpse;
}
public byte[] getPpseResponse() {
return this.ppseResp;
}
public byte[] getTagA5Data() {
return this.tagA5Data;
}
public void setTagA5Data(byte[] tagA5Buffer, short tagA5Offset, short tagA5Length) {
try {
this.tagA5Data = Arrays.copyOfRange(tagA5Buffer,
tagA5Offset,
tagA5Offset + tagA5Length);
}
catch (Exception e) {
this.tagA5Data = null;
}
}
public byte[] getGpoResponseMsd() {
return this.gpoRespMsd;
}
public void setGpoResponseMsd(byte[] gpoResponseMsdBuffer,
short gpoResponseMsdOffset,
short gpoResponseMsdLength) {
try {
this.gpoRespMsd = Arrays.copyOfRange(gpoResponseMsdBuffer,
gpoResponseMsdOffset,
gpoResponseMsdOffset + gpoResponseMsdLength);
}
catch (Exception e) {
this.gpoRespMsd = null;
}
}
public byte[] getGpoResponseQvsdc() {
return this.gpoRespQvsdc;
}
public void setGpoResponseQvsdc(byte[] gpoResponseQvsdcBuffer,
short gpoResponseQvsdcOffset,
short gpoResponseQvsdcLength) {
try {
this.gpoRespQvsdc = Arrays.copyOfRange(gpoResponseQvsdcBuffer,
gpoResponseQvsdcOffset,
gpoResponseQvsdcOffset + gpoResponseQvsdcLength);
}
catch (Exception e) {
this.gpoRespQvsdc = null;
}
}
public byte[] getSfiRecord(short sfiRecord) {
return this.records.get(sfiRecord);
}
public void setSfiRecords(HashMap<Short, byte[]> records) {
try {
this.records = (HashMap<Short, byte[]>) records.clone();
this.records.putAll(records);
}
catch (Exception e) {
this.records = null;
}
}
public byte[] getIssuerApplicationData() {
return this.iad;
}
public void setIssuerApplicationData(byte[] iadBuffer, short iadOffset, short iadLength) {
try {
this.iad = Arrays.copyOfRange(iadBuffer,
iadOffset,
iadOffset + iadLength);
}
catch (Exception e) {
this.iad = null;
}
}
public byte[] getPanSequenceNumber() {
return this.psn;
}
public void setPanSequenceNumber(byte[] psnBuffer, short psnOffset, short psnLength) {
try {
this.psn = Arrays.copyOfRange(psnBuffer,
psnOffset,
psnOffset + psnLength);
}
catch (Exception e) {
this.psn = null;
}
}
public byte[] getCardTransactionQualifier() {
return this.ctq;
}
public void setCardTransactionQualifier(byte[] ctqBuffer, short ctqOffset, short ctqLength) {
try {
this.ctq = Arrays.copyOfRange(ctqBuffer,
ctqOffset,
ctqOffset + ctqLength);
}
catch (Exception e) {
this.ctq = null;
}
}
public byte[] getTrack2EquivalentData() {
return this.track2Data;
}
public void setTrack2EquivalentData(byte[] track2Buffer, short track2Offset, short track2Length) {
try {
this.track2Data = Arrays.copyOfRange(track2Buffer,
track2Offset,
track2Offset + track2Length);
}
catch (Exception e) {
this.track2Data = null;
}
}
public byte[] getCardholderName() {
return this.cardholderName;
}
public void setCardholderName(byte[] cardholderNameBuffer, short cardholderNameOffset, short cardholderNameLength) {
try {
this.cardholderName = Arrays.copyOfRange(cardholderNameBuffer,
cardholderNameOffset,
cardholderNameOffset + cardholderNameLength);
}
catch (Exception e) {
this.cardholderName = null;
}
}
public byte[] getCvmList() {
return this.cvmList;
}
public void setCvmList(byte[] cvmListBuffer, short cvmListOffset, short cvmListLength) {
try {
this.cvmList = Arrays.copyOfRange(cvmListBuffer,
cvmListOffset,
cvmListOffset + cvmListLength);
}
catch (Exception e) {
this.cvmList = null;
}
}
public byte[] getIccPrivKeyCrtCoefficient() {
return this.iccPrivKeyCrtCoefficient;
}
public void setIccPrivKeyCrtCoefficient(byte[] crtComponentBuffer,
short crtComponentOffset,
short crtComponentLength) {
try {
this.iccPrivKeyCrtCoefficient = Arrays.copyOfRange(crtComponentBuffer,
crtComponentOffset,
crtComponentOffset + crtComponentLength);
}
catch (Exception e) {
this.iccPrivKeyCrtCoefficient = null;
}
}
public byte[] getIccPrivKeyPrimeExponentQ() {
return this.iccPrivKeyPrimeExponentQ;
}
public void setIccPrivKeyPrimeExponentQ(byte[] crtComponentBuffer,
short crtComponentOffset,
short crtComponentLength) {
try {
this.iccPrivKeyPrimeExponentQ = Arrays.copyOfRange(crtComponentBuffer,
crtComponentOffset,
crtComponentOffset + crtComponentLength);
}
catch (Exception e) {
this.iccPrivKeyPrimeExponentQ = null;
}
}
public byte[] getIccPrivKeyPrimeExponentP() {
return this.iccPrivKeyPrimeExponentP;
}
public void setIccPrivKeyPrimeExponentP(byte[] crtComponentBuffer,
short crtComponentOffset,
short crtComponentLength) {
try {
this.iccPrivKeyPrimeExponentP = Arrays.copyOfRange(crtComponentBuffer,
crtComponentOffset,
crtComponentOffset + crtComponentLength);
}
catch (Exception e) {
this.iccPrivKeyPrimeExponentP = null;
}
}
public byte[] getIccPrivKeyPrimeQ() {
return this.iccPrivKeyPrimeQ;
}
public void setIccPrivKeyPrimeQ(byte[] crtComponentBuffer,
short crtComponentOffset,
short crtComponentLength) {
try {
this.iccPrivKeyPrimeQ = Arrays.copyOfRange(crtComponentBuffer,
crtComponentOffset,
crtComponentOffset + crtComponentLength);
}
catch (Exception e) {
this.iccPrivKeyPrimeQ = null;
}
}
public byte[] getIccPrivKeyPrimeP() {
return this.iccPrivKeyPrimeP;
}
public void setIccPrivKeyPrimeP(byte[] crtComponentBuffer,
short crtComponentOffset,
short crtComponentLength) {
try {
this.iccPrivKeyPrimeP = Arrays.copyOfRange(crtComponentBuffer,
crtComponentOffset,
crtComponentOffset + crtComponentLength);
}
catch (Exception e) {
this.iccPrivKeyPrimeP = null;
}
}
public int getIccKeyModulusLength() {
return this.iccKeyModulusLength;
}
public void setIccKeyModulusLength(int iccKeyModulusLength) {
this.iccKeyModulusLength = iccKeyModulusLength;
}
public int getMaxNumberAccountParamsDynamic() {
return this.maxNumAcctParamsDynamic;
}
public void setMaxNumberAccountParamsDynamic(byte maxNumberAccountParamsDynamic) {
if (maxNumberAccountParamsDynamic == (byte) 0) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
this.maxNumAcctParamsDynamic = (int) (maxNumberAccountParamsDynamic & 0xFF);
}
public int getMinThresholdNumberAccountParamsDynamic() {
return this.minThresholdNumAcctParamsDynamic;
}
public void setMinThresholdNumberAccountParamsDynamic(byte minThresholdNumberAccountParamsDynamic) {
if (minThresholdNumberAccountParamsDynamic == (byte) 0) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
this.minThresholdNumAcctParamsDynamic = (int) (minThresholdNumberAccountParamsDynamic & 0xFF);
}
public int getCheckIntervalTimeToExpire() {
return this.checkIntervalTimeToExp;
}
public void setCheckIntervalTimeToExpire(byte checkIntervalTimeToExpire) {
this.checkIntervalTimeToExp = (int) (checkIntervalTimeToExpire & 0xFF);
}
public int getMaxTransactionVerificationLogs() {
return this.maxTransactionVerificationLogs;
}
public void setMaxTransactionVerificationLogs(byte maxTransactionVerificationLogs) {
this.maxTransactionVerificationLogs = (int) (maxTransactionVerificationLogs & 0xFF);
}
}