a7firm/src/sega/a7/AuthCommand.java

216 lines
10 KiB
Java

package sega.a7;
import javacard.framework.Util;
import javacard.security.MessageDigest;
public class AuthCommand extends Command {
private Crypt m_ee_crypt;
private HmacSha1 m_ee_hmacSha1;
private byte m_ee_authLevel = 0;
public AuthCommand(short cmd, short recvPacketSize, short sendPacketSize, byte authLevel, AppData data,
MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
super(cmd, recvPacketSize, sendPacketSize, data, packet, sha1);
this.m_ee_crypt = crypt;
this.m_ee_hmacSha1 = hmacSha1;
this.m_ee_authLevel = authLevel;
this.m_ee_tag = AppConfig.A7_TAG_RQU_AUTH_COMMAND;
}
public short execute(byte[] data, short dataOffest, short dataLength, byte[] dst, short dstOffset,
short dstLength) {
if (this.m_ee_data.getSession_ramD() != 1)
return makeErrorPacket(AppConfig.A7_INVALID_AUTH, dst, dstOffset, dstLength);
if (this.m_ee_authLevel != this.m_ee_data.getLevel_ramD())
return makeErrorPacket(AppConfig.A7_LV_ERROR, dst, (short) dstOffset, (short) dstLength);
short ramD_error = checkHeader(data, dataOffest, dataLength);
if (ramD_error != AppConfig.A7_SUCCESS)
return makeErrorPacket(ramD_error, dst, dstOffset, dstLength);
ramD_error = checkFooter(data, dataOffest, dataLength);
if (ramD_error != AppConfig.A7_SUCCESS)
return makeErrorPacket(ramD_error, dst, dstOffset, dstLength);
this.m_ramD_outDataInfo[0] = 0;
this.m_ramD_outDataInfo[1] = 0;
ramD_error = core(data, dataOffest, dataLength);
if (ramD_error != AppConfig.A7_SUCCESS)
return makeErrorPacket(ramD_error, dst, dstOffset, dstLength);
return makeSendAuthPacket(AppConfig.A7_TAG_RSP_AUTH_COMMAND, this.m_ramD_setSendPacketSize[0], (short) 0,
this.m_ramD_outData, this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1], data,
(short) (dataLength - AppConfig.FOOTER_SIZE + dataOffest), (short) 20, dst, dstOffset, dstLength);
}
protected boolean changeConnectionKey_ee(byte[] aesKey, short aesKeyOffset, short aesKeyLength, byte[] aesIv,
short aesIvOffset, short aesIvLength) {
byte[] ramD_tmp = this.m_ee_data.getCryptBuffer_ramD();
Util.arrayFillNonAtomic(ramD_tmp, (short) 0, (short) ramD_tmp.length, (byte) 0);
if (!this.m_ee_crypt.init(aesKey, aesKeyOffset, aesKeyLength, ramD_tmp, (short) 0, (short) ramD_tmp.length,
Crypt.AES_MODE_CKEY_ENCRYPT))
return false;
if (!this.m_ee_crypt.init(aesKey, aesKeyOffset, aesKeyLength, ramD_tmp, (short) 0, (short) ramD_tmp.length,
Crypt.AES_MODE_CKEY_DECRYPT))
return false;
this.m_ee_data.setCkeyIv_ramD(aesIv, aesIvOffset, aesIvLength);
return true;
}
protected boolean changeGKey_ee(byte[] aesKey, short aesKeyOffset, short aesKeyLength, byte[] aesIv,
short aesIvOffset, short aesIvLength) {
byte[] ramD_tmp = this.m_ee_data.getCryptBuffer_ramD();
Util.arrayFillNonAtomic(ramD_tmp, (short) 0, (short) ramD_tmp.length, (byte) 0);
if (!this.m_ee_crypt.init(aesKey, aesKeyOffset, aesKeyLength, ramD_tmp, (short) 0, (short) ramD_tmp.length,
Crypt.AES_MODE_GKEY_ENCRYPT))
return false;
if (!this.m_ee_crypt.init(aesKey, aesKeyOffset, aesKeyLength, ramD_tmp, (short) 0, (short) ramD_tmp.length,
Crypt.AES_MODE_GKEY_DECRYPT))
return false;
this.m_ee_data.setGkeyIv_ee(aesIv, aesIvOffset, aesIvLength);
return true;
}
protected short decData(byte[] src, short srcOffset, short srcLength, byte[] dst, short dstOffset) {
byte[] ramD_iv = this.m_ee_data.getCkeyIv_ramD();
short size = this.m_ee_crypt.doFinal(src, srcOffset, srcLength, dst, dstOffset, Crypt.AES_MODE_CKEY_DECRYPT);
for (short ramD_ii = 0; ramD_ii < ramD_iv.length; ramD_ii++) {
short offset = (short) (ramD_ii + dstOffset);
dst[offset] = (byte) (dst[offset] ^ ramD_iv[ramD_ii]);
}
return size;
}
protected short decUpdate_Gkey(byte[] src, short srcOffset, short srcLength,
byte[] dst, short dstOffset, boolean bInit) {
if (bInit) {
byte[] tmp = this.m_ee_data.getCryptBuffer_ramD();
this.m_ee_crypt.doFinal(tmp, (short) 0, AppConfig.AES_DATA_SIZE, tmp, (short) 0,
Crypt.AES_MODE_GKEY_DECRYPT);
}
short size = this.m_ee_crypt.update(src, srcOffset, srcLength, dst, dstOffset, Crypt.AES_MODE_GKEY_DECRYPT);
if (bInit) {
byte[] ee_iv = this.m_ee_data.getGkeyIv_ee();
for (short ramD_ii = 0; ramD_ii < ee_iv.length; ramD_ii++) {
short offset = (short) (ramD_ii + dstOffset);
dst[offset] = (byte) (dst[offset] ^ ee_iv[ramD_ii]);
}
}
return size;
}
protected short encData(byte[] src, short srcOffset, short srcLength, byte[] dst, short dstOffset) {
byte[] ramD_tmp = this.m_ee_data.getCryptBuffer_ramD();
byte[] ramD_iv = this.m_ee_data.getCkeyIv_ramD();
short ramD_ii = (short) 0;
for (ramD_ii = 0; ramD_ii < 16; ramD_ii++) {
if (ramD_ii < srcLength) {
ramD_tmp[ramD_ii] = (byte) (src[ramD_ii + srcOffset] ^ ramD_iv[ramD_ii]);
} else {
ramD_tmp[ramD_ii] = (byte) (0x0 ^ ramD_iv[ramD_ii]);
}
ramD_tmp[ramD_ii] = (byte) (0x0 ^ ramD_tmp[ramD_ii]);
}
if (srcLength > 16) {
short size = 0;
size += this.m_ee_crypt.update(ramD_tmp, (short) 0, (short) ramD_tmp.length, dst, dstOffset, (short) 2);
size += this.m_ee_crypt.doFinal(src,
(short) (srcOffset + 16), (short) (srcLength - 16), dst,
(short) (dstOffset + 16), (short) 2);
return size;
}
return this.m_ee_crypt.doFinal(ramD_tmp, (short) 0, (short) ramD_tmp.length,
dst, dstOffset, Crypt.AES_MODE_CKEY_ENCRYPT);
}
protected short encUpdate_GKey(byte[] src, short srcOffset, short srcLength,
byte[] dst, short dstOffset, boolean bInit) {
if (!bInit)
return this.m_ee_crypt.update(src, srcOffset, srcLength, dst, dstOffset, Crypt.AES_MODE_GKEY_ENCRYPT);
byte[] ramD_tmp = this.m_ee_data.getCryptBuffer_ramD();
byte[] ee_iv = this.m_ee_data.getGkeyIv_ee();
this.m_ee_crypt.doFinal(ramD_tmp, (short) 0, AppConfig.AES_DATA_SIZE, ramD_tmp, (short) 0,
Crypt.AES_MODE_GKEY_ENCRYPT);
for (short ramD_ii = 0; ramD_ii < AppConfig.AES_DATA_SIZE; ramD_ii++) {
if (ramD_ii < srcLength) {
ramD_tmp[ramD_ii] = (byte) (src[ramD_ii + srcOffset] ^ ee_iv[ramD_ii]);
} else {
ramD_tmp[ramD_ii] = (byte) (short) (0x0 ^ ee_iv[ramD_ii]);
}
ramD_tmp[ramD_ii] = (byte) (short) (0x0 ^ ramD_tmp[ramD_ii]);
}
if (srcLength > AppConfig.AES_DATA_SIZE) {
short size = 0;
size += this.m_ee_crypt.update(ramD_tmp, (short) 0, (short) ramD_tmp.length, dst, dstOffset,
Crypt.AES_MODE_GKEY_ENCRYPT);
size += this.m_ee_crypt.update(src, (short) (srcOffset + AppConfig.AES_DATA_SIZE),
(short) (srcLength - AppConfig.AES_DATA_SIZE), dst, (short) (dstOffset + AppConfig.AES_DATA_SIZE),
Crypt.AES_MODE_GKEY_ENCRYPT);
return size;
}
return this.m_ee_crypt.update(ramD_tmp, (short) 0, (short) ramD_tmp.length, dst, dstOffset,
Crypt.AES_MODE_GKEY_ENCRYPT);
}
protected boolean changeRsaKey_ee(byte[] data1, short data1Offset, short data1Length,
byte[] data2, short data2Offset, short data2Length) {
return this.m_ee_crypt.init(data1, data1Offset, data1Length, data2, data2Offset, data2Length,
Crypt.RSA_MODE_DECRYPT);
}
protected short rsaDecData(byte[] src, short srcOffset, short srcLength, byte[] dst, short dstOffset) {
return this.m_ee_crypt.doFinal(src, srcOffset, srcLength, dst, dstOffset, Crypt.RSA_MODE_DECRYPT);
}
/**
* Validate authenticated packet footer.
* The footer is 40 bytes.
* 20 bytes: nonce
* 20 bytes: MAC(SHA1(packet[:footer]) | nonce) == signature
*/
protected short checkFooter(byte[] data, short dataOffset, short dataLength) {
short ramD_oddOffset = (short) (dataOffset + dataLength - AppConfig.FOOTER_SIZE);
short ramD_authOfset = (short) (dataOffset + dataLength - AppConfig.A7_AUTH_SIZE);
byte[] ramD_buffer = this.m_ee_data.getFooterBuffer_ramD();
byte[] ramD_kh = this.m_ee_data.getKh_ramD();
byte[] ramD_lastNonce = this.m_ee_data.getLastNonceEvent_ramD();
this.m_ee_sha1.reset();
this.m_ee_sha1.doFinal(data, dataOffset, (short) (dataLength - AppConfig.FOOTER_SIZE), ramD_buffer, (short) 0);
this.m_ee_hmacSha1.init(ramD_kh, (short) 0, (short) ramD_kh.length);
this.m_ee_hmacSha1.update(ramD_buffer, (short) 0, (short) 20);
this.m_ee_hmacSha1.update(ramD_lastNonce, (short) 0, (short) ramD_lastNonce.length);
this.m_ee_hmacSha1.sign(data, ramD_oddOffset, (short) 20, ramD_buffer, (short) 0);
if (Util.arrayCompare(data, ramD_authOfset, ramD_buffer, (short) 0, (short) 20) != 0) {
this.m_ee_data.incrementErrorCount();
return AppConfig.A7_AUTHFAIL;
}
this.m_ee_data.clearErrorCount();
return AppConfig.A7_SUCCESS;
}
protected short makeSendAuthPacket(short tag, short paramSize, short result,
byte[] data, short dataOffset, short dataSize, byte[] nonceOdd, short oddOffset,
short oddLength, byte[] sendPacket, short packetOffset, short packetLength) {
byte[] ramD_nonceEvent = this.m_ee_data.getNewNonceEvent_ramD();
if (!this.m_ee_packet.setData(this.m_ee_data.getKh_ramD(), (short) 0,
(short) this.m_ee_data.getKh_ramD().length, tag, paramSize, result, this.m_ee_cmd, data, dataOffset,
dataSize, ramD_nonceEvent, (short) 0, (short) ramD_nonceEvent.length, nonceOdd, oddOffset, oddLength,
sendPacket, packetOffset, packetLength, this.m_ee_sha1, this.m_ee_hmacSha1))
return makeErrorPacket(AppConfig.A7_FAIL, sendPacket, packetOffset, packetLength);
this.m_ee_data.setLastNonceEvent_ramD(ramD_nonceEvent, (short) 0, (short) ramD_nonceEvent.length);
return paramSize;
}
}