forked from Bottersnike/a7firm
Initial code commit
This commit is contained in:
parent
b4f5823828
commit
dccd926fc9
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
lib/
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
> _"A wise man never leaves debugging symbols in production firmware"_
|
||||||
|
>
|
||||||
|
> Sun Tzu, Art of War
|
||||||
|
|
||||||
|
# What?
|
||||||
|
If you have to ask, this repo isn't useful for you.
|
164
src/sega/a7/A7Firm.java
Normal file
164
src/sega/a7/A7Firm.java
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.APDU;
|
||||||
|
import javacard.framework.Applet;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
import javacard.security.RandomData;
|
||||||
|
import javacardx.apdu.ExtendedLength;
|
||||||
|
|
||||||
|
public class A7Firm extends Applet implements ExtendedLength {
|
||||||
|
private CommandServer m_ee_server = new CommandServer();
|
||||||
|
MessageDigest m_ee_sha1 = MessageDigest.getInstance((byte) 1, false);
|
||||||
|
HmacSha1 m_ee_hmacSha1 = new HmacSha1();
|
||||||
|
RandomData m_ee_random = RandomData.getInstance((byte) 2);
|
||||||
|
private AppData m_ee_data = new AppData(this.m_ee_random);
|
||||||
|
|
||||||
|
private MakePacket m_ee_makePacket = new MakePacket();
|
||||||
|
private Crypt m_ee_crypt = new Crypt();
|
||||||
|
private AppBuffer m_ee_buffer = new AppBuffer();
|
||||||
|
|
||||||
|
public boolean select() {
|
||||||
|
if (!super.select())
|
||||||
|
return false;
|
||||||
|
this.m_ee_buffer.clear_ramD();
|
||||||
|
this.m_ee_data.init();
|
||||||
|
this.m_ee_server.select();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public A7Firm() {
|
||||||
|
byte[] modulus = this.m_ee_data.getRsaDefaultPriModulus_ee();
|
||||||
|
byte[] exponent = this.m_ee_data.getRsaDefaultPriExponent_ee();
|
||||||
|
byte[] tmp = this.m_ee_data.getCryptBuffer_ramD();
|
||||||
|
Util.arrayFillNonAtomic(tmp, (short) 0, (short) tmp.length, (byte) -1);
|
||||||
|
|
||||||
|
// Zero all the keys
|
||||||
|
this.m_ee_crypt.init(tmp, (short) 0, (short) tmp.length, tmp, (short) 0, (short) tmp.length,
|
||||||
|
Crypt.AES_MODE_CKEY_DECRYPT);
|
||||||
|
this.m_ee_crypt.init(tmp, (short) 0, (short) tmp.length, tmp, (short) 0, (short) tmp.length,
|
||||||
|
Crypt.AES_MODE_CKEY_ENCRYPT);
|
||||||
|
this.m_ee_crypt.init(tmp, (short) 0, (short) tmp.length, tmp, (short) 0, (short) tmp.length,
|
||||||
|
Crypt.AES_MODE_GKEY_DECRYPT);
|
||||||
|
this.m_ee_crypt.init(tmp, (short) 0, (short) tmp.length, tmp, (short) 0, (short) tmp.length,
|
||||||
|
Crypt.AES_MODE_GKEY_ENCRYPT);
|
||||||
|
this.m_ee_crypt.init(modulus, (short) 0, (short) modulus.length, exponent, (short) 0, (short) exponent.length,
|
||||||
|
Crypt.RSA_MODE_DECRYPT);
|
||||||
|
|
||||||
|
this.m_ee_server.setNoCommand(new NoCommand((short) -1, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(
|
||||||
|
new SessionOpen(AppConfig.A7_ORD_SESSION_OPEN, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(
|
||||||
|
new SessionClose(AppConfig.A7_ORD_SESSION_CLOSE, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(new AuthStart(AppConfig.A7_ORD_AUTH_START, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new HmacChange(AppConfig.A7_ORD_HMAC_CHANGE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new KeyChange(AppConfig.A7_ORD_KEY_CHANGE, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(
|
||||||
|
new LvGet(AppConfig.A7_ORD_LV_GET, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(new KeychipInfoWrite(AppConfig.A7_ORD_KEYCHIP_INFO_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new KeychipInfoRead(AppConfig.A7_ORD_KEYCHIP_INFO_READ, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new GkeyWrite(AppConfig.A7_ORD_GKEY_WRITE, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new GkeyEnc(AppConfig.A7_ORD_GKEY_ENC, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new GkeyDec(AppConfig.A7_ORD_GKEY_DEC, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new SflagWrite(AppConfig.A7_ORD_SFLAG_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(
|
||||||
|
new ErrorGet(AppConfig.A7_ORD_ERROR_GET, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(
|
||||||
|
new LvEnable(AppConfig.A7_ORD_LV_ENABLE, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(new EepInit(AppConfig.A7_ORD_EEP_INIT, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(
|
||||||
|
new VerGet(AppConfig.A7_ORD_VER_GET, this.m_ee_data, this.m_ee_makePacket, this.m_ee_sha1));
|
||||||
|
this.m_ee_server.attachCommand(new PrivkeyModulusWrite(AppConfig.A7_ORD_GPRIKEY_MODULUS_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new PrikeyExponentWrite(AppConfig.A7_ORD_GPRIKEY_EXPONENS_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new UdataWrite(AppConfig.A7_ORD_UDATA_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new UdataRead(AppConfig.A7_ORD_UDATA_READ, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new StorageWrite(AppConfig.A7_ORD_STORAGE_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new StorageRead(AppConfig.A7_ORD_STORAGE_READ, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new RanGet(AppConfig.A7_ORD_RAN_GET, this.m_ee_data, this.m_ee_makePacket,
|
||||||
|
this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt, this.m_ee_random));
|
||||||
|
this.m_ee_server.attachCommand(new PlayCountIncrement(AppConfig.A7_ORD_PLAY_COUNT_INCREMENT, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new PlayCountRead(AppConfig.A7_ORD_PLAY_COUNT_READ, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt, this.m_ee_random));
|
||||||
|
this.m_ee_server.attachCommand(new TraceDataInfoWrite(AppConfig.A7_ORD_TRACE_DATA_INFO_WRITE, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new TraceDataInfoRead(AppConfig.A7_ORD_TRACE_DATA_INFO_READ, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt));
|
||||||
|
this.m_ee_server.attachCommand(new StorageSizeGet(AppConfig.A7_ORD_STORAGE_SIZE_GET, this.m_ee_data,
|
||||||
|
this.m_ee_makePacket, this.m_ee_sha1, this.m_ee_hmacSha1, this.m_ee_crypt, this.m_ee_random));
|
||||||
|
}
|
||||||
|
|
||||||
|
private short makeErrorPacket(short error, short cmd, byte[] sendPacket, short packetOffset, short packetLength) {
|
||||||
|
this.m_ee_data.setLastError_ramD((short) error);
|
||||||
|
this.m_ee_makePacket.setData(null, (short) 0, (short) 0, AppConfig.A7_TAG_RSP_COMMAND,
|
||||||
|
(short) 26,
|
||||||
|
(short) error, (short) cmd, null, (short) 0, (short) 0, null, (short) 0,
|
||||||
|
(short) 0, null,
|
||||||
|
(short) 0, (short) 0, sendPacket, packetOffset, packetLength,
|
||||||
|
this.m_ee_sha1, null);
|
||||||
|
return 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(APDU apdu) {
|
||||||
|
short ramD_sendSize = (short) 0;
|
||||||
|
if (selectingApplet())
|
||||||
|
return;
|
||||||
|
byte[] ramD_packetData = apdu.getBuffer();
|
||||||
|
if (this.m_ee_data.getSflag_ee() && this.m_ee_data.getLevel_ramD() == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.m_ee_data.getLevel_ramD() == 0)
|
||||||
|
this.m_ee_data.setLevel_ramD((byte) 1);
|
||||||
|
|
||||||
|
short ramD_length = Util.getShort(ramD_packetData, (short) 5);
|
||||||
|
boolean ramD_bRet = this.m_ee_buffer.setData_ramD(ramD_packetData, (short) 7, ramD_length);
|
||||||
|
if (!ramD_bRet) {
|
||||||
|
this.m_ee_buffer.clear_ramD();
|
||||||
|
ramD_sendSize = makeErrorPacket(AppConfig.A7_FAIL, (short) 0, ramD_packetData, (short) 0, (short)ramD_packetData.length);
|
||||||
|
apdu.setOutgoingAndSend((short) 0, (short) ramD_sendSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] ramD_buffer = this.m_ee_buffer.getBuffer_ramD();
|
||||||
|
short ramD_size = Util.getShort(ramD_buffer, AppConfig.A7_PARAMSIZE_OFFSET);
|
||||||
|
if (ramD_size > this.m_ee_buffer.getBufferSize_ramD())
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ramD_sendSize = this.m_ee_server.execute(ramD_buffer, (short) 0, this.m_ee_buffer.getBufferSize_ramD(), ramD_packetData, (short) 0, (short) ramD_packetData.length);
|
||||||
|
} catch (Exception e) {
|
||||||
|
short ramD_cmd = Util.getShort(ramD_buffer, AppConfig.A7_COMMAND_OFFSET);
|
||||||
|
this.m_ee_data.setLastError_ramD(AppConfig.A7_FAIL);
|
||||||
|
ramD_sendSize = makeErrorPacket(AppConfig.A7_FAIL, ramD_cmd, ramD_packetData, (short) 0, (short) ramD_packetData.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.m_ee_buffer.clear_ramD();
|
||||||
|
if (ramD_sendSize != 0)
|
||||||
|
apdu.setOutgoingAndSend((short) 0, ramD_sendSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void install(byte[] bArray, short bOffset, byte bLength) {
|
||||||
|
(new PrivkeyModulusWrite()).register(bArray, (short) ((short) bOffset + 1),
|
||||||
|
bArray[(short) bOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deselect() {
|
||||||
|
super.deselect();
|
||||||
|
}
|
||||||
|
}
|
36
src/sega/a7/AppBuffer.java
Normal file
36
src/sega/a7/AppBuffer.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
|
||||||
|
public class AppBuffer {
|
||||||
|
private static final short BUFFER_SIZE = 416;
|
||||||
|
|
||||||
|
private short[] m_ramD_size = JCSystem.makeTransientShortArray((short) 1, (byte) 1);
|
||||||
|
private byte[] m_ramD_buffer = JCSystem.makeTransientByteArray(BUFFER_SIZE, (byte) 1);
|
||||||
|
|
||||||
|
public AppBuffer() {
|
||||||
|
this.m_ramD_size[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBuffer_ramD() {
|
||||||
|
return this.m_ramD_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getBufferSize_ramD() {
|
||||||
|
return this.m_ramD_size[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setData_ramD(byte[] data, short offset, short length) {
|
||||||
|
if (this.m_ramD_size[0] + length > this.m_ramD_buffer.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Util.arrayCopyNonAtomic(data, offset, this.m_ramD_buffer, this.m_ramD_size[0], length);
|
||||||
|
this.m_ramD_size[0] = (short) (this.m_ramD_size[0] + length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear_ramD() {
|
||||||
|
this.m_ramD_size[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
94
src/sega/a7/AppConfig.java
Normal file
94
src/sega/a7/AppConfig.java
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
public interface AppConfig {
|
||||||
|
public static final short VERSION = 0x0205;
|
||||||
|
|
||||||
|
public static final short HEADER_SIZE = 6;
|
||||||
|
public static final short FOOTER_SIZE = 40;
|
||||||
|
|
||||||
|
public static final short NONCE_ODD_SIZE = 20;
|
||||||
|
public static final short NONCE_EVEN_SIZE = 20;
|
||||||
|
public static final short HMAC_SIZE = 20;
|
||||||
|
public static final short AES_KEY_SIZE = 0x10;
|
||||||
|
public static final short AES_IV_SIZE = 0x10;
|
||||||
|
public static final short AES_DATA_SIZE = 0x10;
|
||||||
|
public static final short RSA_PRI_MODULUS_SIZE = 0x100;
|
||||||
|
public static final short RSA_PRI_EXPONENT_SIZE = 0x100;
|
||||||
|
public static final short UDATA_SIZE = 0x10;
|
||||||
|
public static final short PLAY_COUNT_VALUE_SIZE = 4;
|
||||||
|
public static final short STORAGE_SIZE = 0x2800;
|
||||||
|
public static final short STORAGE_SURPLUS_SIZE = 0x10;
|
||||||
|
public static final short KEYCHIP_INFO_SIZE = 96;
|
||||||
|
public static final short TRACE_DATA_INFO_SIZE = 0x10;
|
||||||
|
public static final short STORAGE_DATA_MAX_READ_SIZE = 192;
|
||||||
|
|
||||||
|
public static final short A7_TAG_OFFSET = 0;
|
||||||
|
public static final short A7_PARAMSIZE_OFFSET = 2;
|
||||||
|
public static final short A7_COMMAND_OFFSET = 4;
|
||||||
|
public static final short A7_TAG_SIZE = 2;
|
||||||
|
public static final short A7_PARAMSIZE_SIZE = 2;
|
||||||
|
public static final short A7_COMMAND_SIZE = 2;
|
||||||
|
public static final short A7_CHECKSUM_SIZE = 20;
|
||||||
|
public static final short A7_AUTH_SIZE = 20;
|
||||||
|
|
||||||
|
// Tag codes
|
||||||
|
public static final short A7_TAG_RQU_COMMAND = 0xC1;
|
||||||
|
public static final short A7_TAG_RQU_AUTH_COMMAND = 0xC2;
|
||||||
|
public static final short A7_TAG_RSP_COMMAND = 0xC3;
|
||||||
|
public static final short A7_TAG_RSP_AUTH_COMMAND = 0xC4;
|
||||||
|
public static final short A7_TAG_RQU_RSA_COMMAND = 0xC5;
|
||||||
|
public static final short A7_TAG_RSP_RSA_COMMAND = 0xC6;
|
||||||
|
public static final short A7_TAG_NG = 0;
|
||||||
|
|
||||||
|
// cmd codes
|
||||||
|
public static final short A7_ORD_SESSION_OPEN = 1;
|
||||||
|
public static final short A7_ORD_SESSION_CLOSE = 2;
|
||||||
|
public static final short A7_ORD_AUTH_START = 3;
|
||||||
|
public static final short A7_ORD_HMAC_CHANGE = 4;
|
||||||
|
public static final short A7_ORD_KEY_CHANGE = 5;
|
||||||
|
public static final short A7_ORD_LV_GET = 6;
|
||||||
|
public static final short A7_ORD_ERROR_GET = 7;
|
||||||
|
public static final short A7_ORD_VER_GET = 8;
|
||||||
|
public static final short A7_ORD_KEYCHIP_INFO_WRITE = 9;
|
||||||
|
public static final short A7_ORD_KEYCHIP_INFO_READ = 10;
|
||||||
|
public static final short A7_ORD_GKEY_WRITE = 11;
|
||||||
|
public static final short A7_ORD_GKEY_ENC = 12;
|
||||||
|
public static final short A7_ORD_GKEY_DEC = 13;
|
||||||
|
public static final short A7_ORD_SFLAG_WRITE = 14;
|
||||||
|
public static final short A7_ORD_EEP_INIT = 15;
|
||||||
|
public static final short A7_ORD_LV_ENABLE = 16;
|
||||||
|
public static final short A7_ORD_GPRIKEY_MODULUS_WRITE = 17;
|
||||||
|
public static final short A7_ORD_GPRIKEY_EXPONENS_WRITE = 18;
|
||||||
|
public static final short A7_ORD_UDATA_WRITE = 19;
|
||||||
|
public static final short A7_ORD_UDATA_READ = 20;
|
||||||
|
public static final short A7_ORD_STORAGE_WRITE = 21;
|
||||||
|
public static final short A7_ORD_STORAGE_READ = 22;
|
||||||
|
public static final short A7_ORD_RAN_GET = 23;
|
||||||
|
public static final short A7_ORD_PLAY_COUNT_INCREMENT = 24;
|
||||||
|
public static final short A7_ORD_PLAY_COUNT_READ = 25;
|
||||||
|
public static final short A7_ORD_TRACE_DATA_INFO_WRITE = 26;
|
||||||
|
public static final short A7_ORD_TRACE_DATA_INFO_READ = 27;
|
||||||
|
public static final short A7_ORD_STORAGE_SIZE_GET = 28;
|
||||||
|
|
||||||
|
//Errors
|
||||||
|
public static final short A7_SUCCESS = 0;
|
||||||
|
public static final short A7_INVALID_AUTH = 1;
|
||||||
|
public static final short A7_AUTHFAIL = 2;
|
||||||
|
public static final short A7_LV_ERROR = 3;
|
||||||
|
public static final short A7_BAD_PARAMETER = 4;
|
||||||
|
public static final short A7_EEP_WRITEFAIL = 5;
|
||||||
|
public static final short A7_BAD_TAG = 6;
|
||||||
|
public static final short A7_BAD_ORDINAL = 7;
|
||||||
|
public static final short A7_SUMFAIL = 8;
|
||||||
|
public static final short A7_EEPWRITE_DISABLE = 9;
|
||||||
|
public static final short A7_BAD_DATASIZE = 10;
|
||||||
|
public static final short A7_FAIL = 11;
|
||||||
|
|
||||||
|
public static final short GENERAL_BUFFER_SIZE = 0x100;
|
||||||
|
public static final short FOOTER_BUFFER_SIZE = 20;
|
||||||
|
public static final short NONCE_ODD_BUFFER_SIZE = 20;
|
||||||
|
public static final short SEND_OUT_BUFFER_SIZE = 0x100;
|
||||||
|
public static final short SEND_BUUFER_INFO_ARRAY_SIZE = 2;
|
||||||
|
public static final short SEND_BUUFER_INFO_OFFSET = 0;
|
||||||
|
public static final short SEND_BUUFER_INFO_SIZE = 1;
|
||||||
|
}
|
429
src/sega/a7/AppData.java
Normal file
429
src/sega/a7/AppData.java
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.RandomData;
|
||||||
|
|
||||||
|
public class AppData {
|
||||||
|
/**
|
||||||
|
* 9FD0A43A697329C54BAEC33CF07303BB25F4EB0F366B214633D48ABF639C1057
|
||||||
|
* 55BD87F4071A20E5A139DCF283C86DE5E4D13DA34A023E21AC1B27A452C49044
|
||||||
|
* 97E625C32F6F9762BB80235D11D592965EA6F5839586C3066F2079E70C96055A
|
||||||
|
* FC5A7FC25789B54DB0833D3625B8DAE173A127A681CCE210103BB72FD0205CD3
|
||||||
|
* F024C1BB26E261664D638390F8EF7D512DCF2BC72A826EEC413F233788BA1309
|
||||||
|
* 264018EFDBD8CB748E08917C992A67B7B2C0357E45AB9C9E51CF308EFCC0256F
|
||||||
|
* 28999B079BBB3ADF67D7221A1DE8F3F587A1A49662E0DFE6F5FA557351F04779
|
||||||
|
* 3FCE52641D2C7DC6B0EABA8AE529D1DFF4DC793BB82994CB49B6E4EFD80F142B
|
||||||
|
*/
|
||||||
|
private static final byte[] m_ee_defaultPriModulus = new byte[] {
|
||||||
|
-97, -48, -92, 58, 105, 115, 41, -59, 75, -82,
|
||||||
|
-61, 60, -16, 115, 3, -69, 37, -12, -21, 15,
|
||||||
|
54, 107, 33, 70, 51, -44, -118, -65, 99, -100,
|
||||||
|
16, 87, 85, -67, -121, -12, 7, 26, 32, -27,
|
||||||
|
-95, 57, -36, -14, -125, -56, 109, -27, -28, -47,
|
||||||
|
61, -93, 74, 2, 62, 33, -84, 27, 39, -92,
|
||||||
|
82, -60, -112, 68, -105, -26, 37, -61, 47, 111,
|
||||||
|
-105, 98, -69, -128, 35, 93, 17, -43, -110, -106,
|
||||||
|
94, -90, -11, -125, -107, -122, -61, 6, 111, 32,
|
||||||
|
121, -25, 12, -106, 5, 90, -4, 90, 127, -62,
|
||||||
|
87, -119, -75, 77, -80, -125, 61, 54, 37, -72,
|
||||||
|
-38, -31, 115, -95, 39, -90, -127, -52, -30, 16,
|
||||||
|
16, 59, -73, 47, -48, 32, 92, -45, -16, 36,
|
||||||
|
-63, -69, 38, -30, 97, 102, 77, 99, -125, -112,
|
||||||
|
-8, -17, 125, 81, 45, -49, 43, -57, 42, -126,
|
||||||
|
110, -20, 65, 63, 35, 55, -120, -70, 19, 9,
|
||||||
|
38, 64, 24, -17, -37, -40, -53, 116, -114, 8,
|
||||||
|
-111, 124, -103, 42, 103, -73, -78, -64, 53, 126,
|
||||||
|
69, -85, -100, -98, 81, -49, 48, -114, -4, -64,
|
||||||
|
37, 111, 40, -103, -101, 7, -101, -69, 58, -33,
|
||||||
|
103, -41, 34, 26, 29, -24, -13, -11, -121, -95,
|
||||||
|
-92, -106, 98, -32, -33, -26, -11, -6, 85, 115,
|
||||||
|
81, -16, 71, 121, 63, -50, 82, 100, 29, 44,
|
||||||
|
125, -58, -80, -22, -70, -118, -27, 41, -47, -33,
|
||||||
|
-12, -36, 121, 59, -72, 41, -108, -53, 73, -74,
|
||||||
|
-28, -17, -40, 15, 20, 43
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 310A06BADDCCB6CE91B0A8BC3454369AE0C4CCB438509B3F3D7C44AF01D3CBB7
|
||||||
|
* E0D96DB455D190B2A5CC699E090E219ADFA1CD3623E9984320DA9C4972145AE8
|
||||||
|
* 916BCFBE9AF9B50C58D8B301460DB1136F2BF03E564DA9DE798F0F98F465BC72
|
||||||
|
* F4E898377C41075F3580AFF1C3957BA49EA49ED41B145171F8693A86F3685AD3
|
||||||
|
* 39BEFDA3188141990787977FD8BE7D588886A67E4EEBEB38FBB09FAF44468FF9
|
||||||
|
* EF74BB7961ED1063714CCA6ECAEC8389CE4A6F315C3069EA4BF2F6CAEF2028A2
|
||||||
|
* 09B0307200475F775CCAD248E2E93C42C312F954183D233EB1B29409388C03E6
|
||||||
|
* 2961A8833F5A508305B7D8013AABE6CD1A01034A18E4438DCD46A52825F539F1
|
||||||
|
*/
|
||||||
|
private static final byte[] m_ee_defaultPriExponent = new byte[] {
|
||||||
|
49, 10, 6, -70, -35, -52, -74, -50, -111, -80,
|
||||||
|
-88, -68, 52, 84, 54, -102, -32, -60, -52, -76,
|
||||||
|
56, 80, -101, 63, 61, 124, 68, -81, 1, -45,
|
||||||
|
-53, -73, -32, -39, 109, -76, 85, -47, -112, -78,
|
||||||
|
-91, -52, 105, -98, 9, 14, 33, -102, -33, -95,
|
||||||
|
-51, 54, 35, -23, -104, 67, 32, -38, -100, 73,
|
||||||
|
114, 20, 90, -24, -111, 107, -49, -66, -102, -7,
|
||||||
|
-75, 12, 88, -40, -77, 1, 70, 13, -79, 19,
|
||||||
|
111, 43, -16, 62, 86, 77, -87, -34, 121, -113,
|
||||||
|
15, -104, -12, 101, -68, 114, -12, -24, -104, 55,
|
||||||
|
124, 65, 7, 95, 53, -128, -81, -15, -61, -107,
|
||||||
|
123, -92, -98, -92, -98, -44, 27, 20, 81, 113,
|
||||||
|
-8, 105, 58, -122, -13, 104, 90, -45, 57, -66,
|
||||||
|
-3, -93, 24, -127, 65, -103, 7, -121, -105, 127,
|
||||||
|
-40, -66, 125, 88, -120, -122, -90, 126, 78, -21,
|
||||||
|
-21, 56, -5, -80, -97, -81, 68, 70, -113, -7,
|
||||||
|
-17, 116, -69, 121, 97, -19, 16, 99, 113, 76,
|
||||||
|
-54, 110, -54, -20, -125, -119, -50, 74, 111, 49,
|
||||||
|
92, 48, 105, -22, 75, -14, -10, -54, -17, 32,
|
||||||
|
40, -94, 9, -80, 48, 114, 0, 71, 95, 119,
|
||||||
|
92, -54, -46, 72, -30, -23, 60, 66, -61, 18,
|
||||||
|
-7, 84, 24, 61, 35, 62, -79, -78, -108, 9,
|
||||||
|
56, -116, 3, -26, 41, 97, -88, -125, 63, 90,
|
||||||
|
80, -125, 5, -73, -40, 1, 58, -85, -26, -51,
|
||||||
|
26, 1, 3, 74, 24, -28, 67, -115, -51, 70,
|
||||||
|
-91, 40, 37, -11, 57, -15
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte VALUE_AUTH_LEVEL = 0;
|
||||||
|
private static final byte VALUE_SESSION = 1;
|
||||||
|
private static final byte VALUE_ERROR_RESULT_H = 2;
|
||||||
|
private static final byte VALUE_ERROR_COUNT = 4;
|
||||||
|
private static final byte VALUE_WRITE_FLAG = 5;
|
||||||
|
private static final byte VALUE_SIZE = 6;
|
||||||
|
|
||||||
|
private byte[] m_ee_sflag = new byte[1];
|
||||||
|
private byte[] m_ramD_rsa_update_status;
|
||||||
|
private byte[] m_ramD_value;
|
||||||
|
private byte[] m_ramD_kh;
|
||||||
|
private byte[] m_ramD_cryptBuffer;
|
||||||
|
private byte[] m_ee_gkeyIv;
|
||||||
|
private byte[] m_ramD_cKeyIv;
|
||||||
|
private byte[] m_ramD_newNonceEvent;
|
||||||
|
private byte[] m_ramD_lastNonceEvent;
|
||||||
|
private byte[] m_ramD_generalBuffer;
|
||||||
|
private byte[] m_ramD_sendOutBuffer;
|
||||||
|
private short[] m_ramD_sendOutInfo;
|
||||||
|
private byte[] m_ramD_footerBuffer;
|
||||||
|
private byte[] m_ramD_nonceOddBuffer;
|
||||||
|
private byte[] m_ee_priModulus = new byte[AppConfig.RSA_PRI_MODULUS_SIZE];
|
||||||
|
private byte[] m_ee_priExponent = new byte[AppConfig.RSA_PRI_EXPONENT_SIZE];
|
||||||
|
private byte[] m_ee_udata = new byte[AppConfig.UDATA_SIZE];
|
||||||
|
private byte[] m_ee_storage = new byte[AppConfig.STORAGE_SIZE];
|
||||||
|
private byte[] m_ee_keychipInfo = new byte[AppConfig.KEYCHIP_INFO_SIZE];
|
||||||
|
private byte[] m_ee_traceDataInfo = new byte[AppConfig.TRACE_DATA_INFO_SIZE];
|
||||||
|
private byte[] m_ee_playCount = new byte[AppConfig.PLAY_COUNT_VALUE_SIZE];
|
||||||
|
private RandomData m_ee_rand;
|
||||||
|
|
||||||
|
public static final byte SESSION_DISABLE = 0;
|
||||||
|
public static final byte SESSION_ENABLE = 1;
|
||||||
|
public static final byte SHIPMENT_FLAG = 0x04;
|
||||||
|
public static final byte BLOCK_FLAG = 0x20;
|
||||||
|
public static final byte RSA_UPDATE_FLAG = 1;
|
||||||
|
public static final byte RSA_UPDATE_STATUS_SIZE = 1;
|
||||||
|
public static final byte RSA_UPDATE_EXPONENT = 0x08;
|
||||||
|
public static final byte RSA_UPDATE_MODULUS = 0x40;
|
||||||
|
|
||||||
|
public AppData(RandomData rand) {
|
||||||
|
this.m_ee_rand = rand;
|
||||||
|
this.m_ee_gkeyIv = new byte[16];
|
||||||
|
Util.arrayCopy(m_ee_defaultPriModulus, (short) 0, this.m_ee_priModulus, (short) 0,
|
||||||
|
(short) this.m_ee_priModulus.length);
|
||||||
|
Util.arrayCopy(m_ee_defaultPriExponent, (short) 0, this.m_ee_priExponent, (short) 0,
|
||||||
|
(short) this.m_ee_priExponent.length);
|
||||||
|
this.m_ee_sflag[0] = 0;
|
||||||
|
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_keychipInfo, (short) 0, (short) this.m_ee_keychipInfo.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_udata, (short) 0, (short) this.m_ee_udata.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_storage, (short) 0, (short) this.m_ee_storage.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_traceDataInfo, (short) 0, (short) this.m_ee_traceDataInfo.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_playCount, (short) 0, (short) this.m_ee_playCount.length, (byte) 0);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_gkeyIv, (short) 0, (short) this.m_ee_gkeyIv.length, (byte) -1);
|
||||||
|
|
||||||
|
this.m_ramD_value = JCSystem.makeTransientByteArray(VALUE_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_rsa_update_status = JCSystem.makeTransientByteArray(RSA_UPDATE_STATUS_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_kh = JCSystem.makeTransientByteArray((short) 20, (byte) 1);
|
||||||
|
this.m_ramD_newNonceEvent = JCSystem.makeTransientByteArray((short) 20, (byte) 1);
|
||||||
|
this.m_ramD_lastNonceEvent = JCSystem.makeTransientByteArray((short) 20, (byte) 1);
|
||||||
|
this.m_ramD_cKeyIv = JCSystem.makeTransientByteArray(AppConfig.AES_IV_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_generalBuffer = JCSystem.makeTransientByteArray(AppConfig.GENERAL_BUFFER_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_footerBuffer = JCSystem.makeTransientByteArray(AppConfig.FOOTER_BUFFER_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_nonceOddBuffer = JCSystem.makeTransientByteArray(AppConfig.NONCE_ODD_BUFFER_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_sendOutBuffer = JCSystem.makeTransientByteArray(AppConfig.SEND_OUT_BUFFER_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_sendOutInfo = JCSystem.makeTransientShortArray(AppConfig.SEND_BUUFER_INFO_ARRAY_SIZE, (byte) 1);
|
||||||
|
this.m_ramD_cryptBuffer = JCSystem.makeTransientByteArray((short) 16, (byte) 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
if (getBlockFlag_ee()) {
|
||||||
|
this.m_ramD_value[VALUE_AUTH_LEVEL] = -1;
|
||||||
|
} else {
|
||||||
|
this.m_ramD_value[VALUE_AUTH_LEVEL] = 0;
|
||||||
|
}
|
||||||
|
this.m_ramD_value[VALUE_SESSION] = SESSION_DISABLE;
|
||||||
|
this.m_ramD_value[VALUE_ERROR_COUNT] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
this.m_ee_sflag[0] = 0;
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_keychipInfo, (short) 0, (short) this.m_ee_keychipInfo.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_udata, (short) 0, (short) this.m_ee_udata.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_storage, (short) 0, (short) this.m_ee_storage.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_traceDataInfo, (short) 0, (short) this.m_ee_traceDataInfo.length, (byte) -1);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_playCount, (short) 0, (short) this.m_ee_playCount.length, (byte) 0);
|
||||||
|
Util.arrayFillNonAtomic(this.m_ee_gkeyIv, (short) 0, (short) this.m_ee_gkeyIv.length, (byte) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel_ramD(byte setLevel) {
|
||||||
|
this.m_ramD_value[VALUE_AUTH_LEVEL] = setLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getLevel_ramD() {
|
||||||
|
return this.m_ramD_value[VALUE_AUTH_LEVEL];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSession_ramD(byte setSession) {
|
||||||
|
this.m_ramD_value[VALUE_SESSION] = setSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addValuePlayCounter_ee(byte value) {
|
||||||
|
short ramD_tmp = 0;
|
||||||
|
short ramD_setValue = (short) value;
|
||||||
|
short ramD_ii = 0;
|
||||||
|
|
||||||
|
while (ramD_ii < this.m_ee_playCount.length) {
|
||||||
|
short ramD_index = (short) ((this.m_ee_playCount.length - ramD_ii) - 1);
|
||||||
|
ramD_tmp = (short) ((ramD_setValue & 0xFF) + (this.m_ee_playCount[ramD_index] & 0xFF));
|
||||||
|
this.m_ee_playCount[ramD_index] = (byte) (ramD_tmp & 0xFF);
|
||||||
|
|
||||||
|
if (ramD_tmp > 255) {
|
||||||
|
ramD_setValue = 1;
|
||||||
|
ramD_ii++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getPlayCounter_ee(byte[] playCount, short offset, short length) {
|
||||||
|
if (length < this.m_ee_playCount.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Util.arrayCopyNonAtomic(this.m_ee_playCount, (short) 0, playCount, offset, (short) this.m_ee_playCount.length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getSession_ramD() {
|
||||||
|
return this.m_ramD_value[VALUE_SESSION];
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getNewNonceEvent_ramD() {
|
||||||
|
this.m_ee_rand.generateData(this.m_ramD_newNonceEvent, (short) 0,
|
||||||
|
(short) this.m_ramD_newNonceEvent.length);
|
||||||
|
return this.m_ramD_newNonceEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getLastNonceEvent_ramD() {
|
||||||
|
return this.m_ramD_lastNonceEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setLastNonceEvent_ramD(byte[] lastNonceEvent, short offset, short length) {
|
||||||
|
if (length > this.m_ramD_lastNonceEvent.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
short ramD_writeSize = Util.arrayCopyNonAtomic(lastNonceEvent, offset, this.m_ramD_lastNonceEvent, (short) 0,
|
||||||
|
length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getKh_ramD() {
|
||||||
|
return this.m_ramD_kh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setKh_ramD(byte[] kh, short offset, short length) {
|
||||||
|
if (length > this.m_ramD_kh.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
short ramD_writeSize = Util.arrayCopyNonAtomic(kh, offset, this.m_ramD_kh, (short) 0, length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getGkeyIv_ee() {
|
||||||
|
return this.m_ee_gkeyIv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setGkeyIv_ee(byte[] newGkeyIv, short offset, short length) {
|
||||||
|
if (length > this.m_ee_gkeyIv.length)
|
||||||
|
return false;
|
||||||
|
short ramD_writeSize = Util.arrayCopy(newGkeyIv, offset, this.m_ee_gkeyIv, (short) 0, length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getCkeyIv_ramD() {
|
||||||
|
return this.m_ramD_cKeyIv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setCkeyIv_ramD(byte[] newCkeyIv, short offset, short length) {
|
||||||
|
if (length > this.m_ee_gkeyIv.length)
|
||||||
|
return false;
|
||||||
|
short ramD_writeSize = Util.arrayCopyNonAtomic(newCkeyIv, offset, this.m_ramD_cKeyIv, (short) 0, length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getRsaDefaultPriModulus_ee() {
|
||||||
|
return m_ee_defaultPriModulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getRsaDefaultPriExponent_ee() {
|
||||||
|
return m_ee_defaultPriExponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getRsaPriModulus_ee() {
|
||||||
|
return this.m_ee_priModulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getRsaPriExponent_ee() {
|
||||||
|
return this.m_ee_priExponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setRsaPriKeyModulus_ee(byte[] exponent, short eOfset, short eLength) {
|
||||||
|
if (eLength > this.m_ee_priModulus.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
short ramD_writeSize = Util.arrayCopy(exponent, eOfset, this.m_ee_priModulus, (short) 0, eLength);
|
||||||
|
return ramD_writeSize == eLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setRsaPriKeyExponent_ee(byte[] modulus, short mOffset, short mLength) {
|
||||||
|
if (mLength > this.m_ee_priExponent.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
short ramD_writeSize = Util.arrayCopy(modulus, mOffset, this.m_ee_priExponent, (short) 0, mLength);
|
||||||
|
return ramD_writeSize == mLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSflag_ee() {
|
||||||
|
return (this.m_ee_sflag[0] & SHIPMENT_FLAG) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activeSflag() {
|
||||||
|
this.m_ramD_value[VALUE_WRITE_FLAG] = this.m_ee_sflag[0];
|
||||||
|
this.m_ramD_value[VALUE_WRITE_FLAG] |= SHIPMENT_FLAG;
|
||||||
|
Util.arrayCopy(this.m_ramD_value, VALUE_WRITE_FLAG, this.m_ee_sflag, (short) 0, (short) 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getRsaExponentUpdate_ramD() {
|
||||||
|
return (this.m_ramD_rsa_update_status[0] & RSA_UPDATE_EXPONENT) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activeRssaExponentUpdate_ramD() {
|
||||||
|
this.m_ramD_rsa_update_status[0] = (byte) (this.m_ramD_rsa_update_status[0] | RSA_UPDATE_EXPONENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getRsaModulusUpdate_ramD() {
|
||||||
|
return (this.m_ramD_rsa_update_status[0] & RSA_UPDATE_MODULUS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activeRssaModulusUpdate_ramD() {
|
||||||
|
this.m_ramD_rsa_update_status[0] = (byte) (this.m_ramD_rsa_update_status[0] | RSA_UPDATE_MODULUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBlockFlag_ee() {
|
||||||
|
return (this.m_ee_sflag[0] & BLOCK_FLAG) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activeBlockFlag() {
|
||||||
|
this.m_ramD_value[VALUE_WRITE_FLAG] = this.m_ee_sflag[0];
|
||||||
|
this.m_ramD_value[VALUE_WRITE_FLAG] |= BLOCK_FLAG;
|
||||||
|
Util.arrayCopy(this.m_ramD_value, VALUE_WRITE_FLAG, this.m_ee_sflag, (short) 0, (short) 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getKeychipInfo_ee() {
|
||||||
|
return this.m_ee_keychipInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setKeychipInfo_ee(byte[] newKeychipInfo, short offset, short length) {
|
||||||
|
if (length > this.m_ee_keychipInfo.length)
|
||||||
|
return false;
|
||||||
|
short ramD_writeSize = Util.arrayCopy(newKeychipInfo, offset, this.m_ee_keychipInfo, (short) 0, length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getTraceDataInfo_ee() {
|
||||||
|
return this.m_ee_traceDataInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setTraceDataInfo_ee(byte[] newTraceDataInfo, short offset, short length) {
|
||||||
|
if (length > this.m_ee_traceDataInfo.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
short ramD_writeSize = Util.arrayCopy(newTraceDataInfo, offset, this.m_ee_traceDataInfo, (short) 0, length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getUdata_ee() {
|
||||||
|
return this.m_ee_udata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setUdata_ee(byte[] newUdata, short offset, short length) {
|
||||||
|
if (length > newUdata.length)
|
||||||
|
return false;
|
||||||
|
short ramD_writeSize = Util.arrayCopy(newUdata, offset, this.m_ee_udata, (short) 0, length);
|
||||||
|
return ramD_writeSize == length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getStorageData_ee() {
|
||||||
|
return this.m_ee_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setStorageData_ee(byte[] newStorage, short offset, short length, short dstOffset) {
|
||||||
|
if (length > (this.m_ee_storage.length - dstOffset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
short ramD_writeSize = Util.arrayCopy(newStorage, offset, this.m_ee_storage, dstOffset, length);
|
||||||
|
return ramD_writeSize == (dstOffset + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getGeneralBuffer_ramD() {
|
||||||
|
return this.m_ramD_generalBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSendOutBuffer_ramD() {
|
||||||
|
return this.m_ramD_sendOutBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short[] getSendOutInfo_ramD() {
|
||||||
|
return this.m_ramD_sendOutInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getCryptBuffer_ramD() {
|
||||||
|
return this.m_ramD_cryptBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getFooterBuffer_ramD() {
|
||||||
|
return this.m_ramD_footerBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getNonceOddBuffer_ramD() {
|
||||||
|
return this.m_ramD_nonceOddBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastError_ramD(short error) {
|
||||||
|
Util.setShort(this.m_ramD_value, VALUE_ERROR_RESULT_H, (short) error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getLastError_ramD() {
|
||||||
|
short ramD_result = Util.getShort(this.m_ramD_value, VALUE_ERROR_RESULT_H);
|
||||||
|
return ramD_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementErrorCount() {
|
||||||
|
this.m_ramD_value[VALUE_ERROR_COUNT]++;
|
||||||
|
if (this.m_ramD_value[VALUE_ERROR_COUNT] + 1 == 3) {
|
||||||
|
activeBlockFlag();
|
||||||
|
this.m_ramD_value[VALUE_AUTH_LEVEL] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearErrorCount() {
|
||||||
|
this.m_ramD_value[VALUE_ERROR_COUNT] = 0;
|
||||||
|
}
|
||||||
|
}
|
215
src/sega/a7/AuthCommand.java
Normal file
215
src/sega/a7/AuthCommand.java
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
72
src/sega/a7/AuthStart.java
Normal file
72
src/sega/a7/AuthStart.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class AuthStart extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 302;
|
||||||
|
private static final byte AUTH_LEVEL = 1;
|
||||||
|
private static final byte SET_AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public AuthStart(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, (short) 2, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short execute(byte[] data, short dataOffset, short dataLength, byte[] dst, short dstOffset,
|
||||||
|
short dstLength) {
|
||||||
|
short dataSize = 256;
|
||||||
|
if (this.m_ee_data.getSession_ramD() != 1)
|
||||||
|
return makeErrorPacket(AppConfig.A7_INVALID_AUTH, dst, dstOffset, dstLength);
|
||||||
|
if (this.m_ee_data.getLevel_ramD() != SET_AUTH_LEVEL)
|
||||||
|
return makeErrorPacket(AppConfig.A7_LV_ERROR, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
short error = checkHeader(data, dataOffset, dataLength);
|
||||||
|
if (error != AppConfig.A7_SUCCESS)
|
||||||
|
return makeErrorPacket(error, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
byte[] newData = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (dataSize > newData.length)
|
||||||
|
return makeErrorPacket(AppConfig.A7_FAIL, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
short decSize = 0;
|
||||||
|
try {
|
||||||
|
decSize = rsaDecData(data, (short) (6 + dataOffset), dataSize, newData, (short) 0);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return makeErrorPacket(AppConfig.A7_AUTHFAIL, dst, dstOffset, dstLength);
|
||||||
|
}
|
||||||
|
if (decSize < 52)
|
||||||
|
return makeErrorPacket(AppConfig.A7_AUTHFAIL, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
boolean bRet = this.m_ee_data.setKh_ramD(newData, (short) 32, (short) 20);
|
||||||
|
if (!bRet)
|
||||||
|
return makeErrorPacket(AppConfig.A7_FAIL, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
error = checkFooter(data, dataOffset, dataLength);
|
||||||
|
if (error != AppConfig.A7_SUCCESS)
|
||||||
|
return makeErrorPacket(error, dst, dstOffset, dstLength);
|
||||||
|
bRet = changeConnectionKey_ee(newData, (short) 0, AppConfig.AES_KEY_SIZE, newData, AppConfig.AES_KEY_SIZE, AppConfig.AES_IV_SIZE);
|
||||||
|
if (!bRet)
|
||||||
|
return makeErrorPacket(AppConfig.A7_FAIL, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
byte[] nonceOdd = this.m_ee_data.getNonceOddBuffer_ramD();
|
||||||
|
Util.arrayCopyNonAtomic(data, (short) (262 + dataOffset), nonceOdd, (short) 0, (short) 20);
|
||||||
|
this.m_ee_data.setLevel_ramD((byte) 2);
|
||||||
|
return makeSendAuthPacket(AppConfig.A7_TAG_RSP_RSA_COMMAND, PARAM_SIZE, (short) 0, null, (short) 0,
|
||||||
|
(short) 0, data, (short) (262 + dataOffset), (short) 20, dst, dstOffset, dstLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected short checkHeader(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (dataLength != this.m_ee_recvPacketSize)
|
||||||
|
return AppConfig.A7_BAD_DATASIZE;
|
||||||
|
|
||||||
|
short tag = Util.getShort(data, (short) (dataOffset + 0));
|
||||||
|
if (tag != AppConfig.A7_TAG_RQU_RSA_COMMAND)
|
||||||
|
return AppConfig.A7_BAD_TAG;
|
||||||
|
short paramsize = Util.getShort(data, (short) (dataOffset + 2));
|
||||||
|
|
||||||
|
if (paramsize != this.m_ee_recvPacketSize)
|
||||||
|
return AppConfig.A7_BAD_DATASIZE;
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
135
src/sega/a7/Command.java
Normal file
135
src/sega/a7/Command.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class Command {
|
||||||
|
protected short m_ee_cmd;
|
||||||
|
protected short m_ee_recvPacketSize;
|
||||||
|
protected short m_ee_sendPacketSize;
|
||||||
|
protected short[] m_ramD_setSendPacketSize;
|
||||||
|
protected short m_ee_tag;
|
||||||
|
protected MakePacket m_ee_packet;
|
||||||
|
protected AppData m_ee_data;
|
||||||
|
protected MessageDigest m_ee_sha1;
|
||||||
|
|
||||||
|
private static final short ERROR_PACKET_SIZE = 26;
|
||||||
|
protected static final short SET_SEND_PACKET_SIZE_ARRAY_SIZE = 1;
|
||||||
|
|
||||||
|
protected byte[] m_ramD_outData;
|
||||||
|
protected short[] m_ramD_outDataInfo;
|
||||||
|
|
||||||
|
public Command(short cmd, short recvPacketSize, short sendPacketSize, AppData data, MakePacket packet,
|
||||||
|
MessageDigest sha1) {
|
||||||
|
this.m_ee_cmd = (short) cmd;
|
||||||
|
this.m_ee_data = data;
|
||||||
|
this.m_ee_packet = packet;
|
||||||
|
this.m_ee_recvPacketSize = (short) recvPacketSize;
|
||||||
|
this.m_ee_sendPacketSize = (short) sendPacketSize;
|
||||||
|
this.m_ee_tag = AppConfig.A7_TAG_RQU_COMMAND;
|
||||||
|
this.m_ee_sha1 = sha1;
|
||||||
|
this.m_ramD_setSendPacketSize = JCSystem.makeTransientShortArray((short) 1, (byte) 1);
|
||||||
|
this.m_ramD_setSendPacketSize[0] = this.m_ee_sendPacketSize;
|
||||||
|
this.m_ramD_outData = data.getSendOutBuffer_ramD();
|
||||||
|
this.m_ramD_outDataInfo = data.getSendOutInfo_ramD();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean select() {
|
||||||
|
this.m_ramD_setSendPacketSize[0] = this.m_ee_sendPacketSize;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short execute(byte[] data, short dataOffset, short dataLength, byte[] dst, short dstOffset,
|
||||||
|
short dstLength) {
|
||||||
|
short ramD_error = checkHeader(data, dataOffset, dataLength);
|
||||||
|
if (ramD_error != AppConfig.A7_SUCCESS)
|
||||||
|
return makeErrorPacket(ramD_error, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
ramD_error = checkFooter(data, dataOffset, 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, dataOffset, dataLength);
|
||||||
|
|
||||||
|
if (ramD_error != AppConfig.A7_SUCCESS)
|
||||||
|
return makeErrorPacket(ramD_error, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
return makeSendPacket(AppConfig.A7_TAG_RSP_COMMAND, this.m_ramD_setSendPacketSize[0], ramD_error,
|
||||||
|
this.m_ramD_outData, this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1],
|
||||||
|
dst, dstOffset, dstLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getCmd_ee() {
|
||||||
|
return this.m_ee_cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected short setSendPacketSize_ramD(short sendSize) {
|
||||||
|
this.m_ramD_setSendPacketSize[0] = sendSize;
|
||||||
|
return this.m_ramD_setSendPacketSize[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate packet header.
|
||||||
|
* The header is 6 bytes.
|
||||||
|
* 2 bytes: tag
|
||||||
|
* 2 bytes: paramsize
|
||||||
|
* 2 bytes: command
|
||||||
|
*/
|
||||||
|
protected short checkHeader(byte[] data, short dataOfset, short dataLength) {
|
||||||
|
short ramD_paramsize = Util.getShort(data, (short) (dataOfset + AppConfig.A7_PARAMSIZE_OFFSET));
|
||||||
|
if (dataLength != ramD_paramsize)
|
||||||
|
return AppConfig.A7_BAD_DATASIZE;
|
||||||
|
|
||||||
|
short ramD_tag = Util.getShort(data, (short) (dataOfset + AppConfig.A7_TAG_OFFSET));
|
||||||
|
|
||||||
|
if (ramD_tag != this.m_ee_tag)
|
||||||
|
return AppConfig.A7_BAD_TAG;
|
||||||
|
if (this.m_ee_recvPacketSize != 0 && dataLength != this.m_ee_recvPacketSize)
|
||||||
|
return AppConfig.A7_BAD_DATASIZE;
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate an unauthenticated packet footer.
|
||||||
|
* The footer is a 20 byte SHA1 sum of the packet.
|
||||||
|
*/
|
||||||
|
protected short checkFooter(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
short ramD_paramsize = (short) (dataOffset + dataLength - AppConfig.A7_CHECKSUM_SIZE);
|
||||||
|
byte[] ramD_buffer = this.m_ee_data.getFooterBuffer_ramD();
|
||||||
|
this.m_ee_sha1.reset();
|
||||||
|
this.m_ee_sha1.doFinal(data, dataOffset, (short) (dataLength - AppConfig.A7_CHECKSUM_SIZE), ramD_buffer,
|
||||||
|
(short) 0);
|
||||||
|
if (Util.arrayCompare(data, ramD_paramsize, ramD_buffer, (short) 0, (short) AppConfig.A7_CHECKSUM_SIZE) != 0)
|
||||||
|
return AppConfig.A7_SUMFAIL;
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected short makeSendPacket(short tag, short paramSize, short result,
|
||||||
|
byte[] data, short dataOffset, short dataSize, byte[] sendPacket, short packetOffset,
|
||||||
|
short packetLength) {
|
||||||
|
if (!this.m_ee_packet.setData(null, (short) 0, (short) 0, tag, paramSize, result, this.m_ee_cmd, data,
|
||||||
|
dataOffset,
|
||||||
|
dataSize, null, (short) 0, (short) 0, null, (short) 0, (short) 0, sendPacket, packetOffset,
|
||||||
|
packetLength,
|
||||||
|
this.m_ee_sha1, null)) {
|
||||||
|
return makeErrorPacket(AppConfig.A7_FAIL, sendPacket, packetOffset, packetLength);
|
||||||
|
}
|
||||||
|
return paramSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected short makeErrorPacket(short error, byte[] sendPacket, short packetOffset, short packetLength) {
|
||||||
|
this.m_ee_data.setLastError_ramD(error);
|
||||||
|
this.m_ee_packet.setData(null, (short) 0, (short) 0, AppConfig.A7_TAG_RSP_COMMAND, ERROR_PACKET_SIZE,
|
||||||
|
error, this.m_ee_cmd, null, (short) 0, (short) 0, null, (short) 0, (short) 0,
|
||||||
|
null, (short) 0, (short) 0, sendPacket, packetOffset, packetLength,
|
||||||
|
this.m_ee_sha1, null);
|
||||||
|
return ERROR_PACKET_SIZE;
|
||||||
|
}
|
||||||
|
}
|
55
src/sega/a7/CommandServer.java
Normal file
55
src/sega/a7/CommandServer.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
|
||||||
|
public class CommandServer {
|
||||||
|
private Command m_ee_noCommand = null;
|
||||||
|
private Command[] m_ee_list = new Command[4];
|
||||||
|
private short m_ee_listCount = 0;
|
||||||
|
|
||||||
|
public void setNoCommand(Command cmdClass) {
|
||||||
|
this.m_ee_noCommand = cmdClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attachCommand(Command cmdClass) {
|
||||||
|
if (this.m_ee_listCount >= this.m_ee_list.length) {
|
||||||
|
Command[] ee_tmpCommand = new Command[this.m_ee_list.length * 2];
|
||||||
|
for (short ii = 0; ii < this.m_ee_list.length; ii++)
|
||||||
|
ee_tmpCommand[ii] = this.m_ee_list[ii];
|
||||||
|
this.m_ee_list = ee_tmpCommand;
|
||||||
|
}
|
||||||
|
this.m_ee_list[this.m_ee_listCount++] = cmdClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short findCommand(short cmd) {
|
||||||
|
for (short ramD_ii = 0; ramD_ii < this.m_ee_listCount; ramD_ii++) {
|
||||||
|
if (this.m_ee_list[ramD_ii].getCmd_ee() == cmd)
|
||||||
|
return ramD_ii;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean select() {
|
||||||
|
boolean ramD_bRet = true;
|
||||||
|
for (short ramD_ii = 0; ramD_ii < this.m_ee_listCount; ramD_ii++) {
|
||||||
|
if (!this.m_ee_list[ramD_ii].select())
|
||||||
|
ramD_bRet = false;
|
||||||
|
}
|
||||||
|
return ramD_bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short execute(byte[] data, short dataOffset, short dataLength, byte[] dst, short dstOffset,
|
||||||
|
short dstLength) {
|
||||||
|
short ramD_cmd = -1;
|
||||||
|
if (6 <= dataLength)
|
||||||
|
ramD_cmd = Util.getShort(data, (short) (dataOffset + AppConfig.A7_COMMAND_OFFSET));
|
||||||
|
|
||||||
|
short damD_list = findCommand(ramD_cmd);
|
||||||
|
if (damD_list >= 0)
|
||||||
|
return this.m_ee_list[damD_list].execute(data, dataOffset, dataLength, dst, dstOffset, dstLength);
|
||||||
|
|
||||||
|
if (this.m_ee_noCommand == null)
|
||||||
|
return -1;
|
||||||
|
return this.m_ee_noCommand.execute(data, ramD_cmd, dataLength, dst, dstOffset, dstLength);
|
||||||
|
}
|
||||||
|
}
|
104
src/sega/a7/Crypt.java
Normal file
104
src/sega/a7/Crypt.java
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.AESKey;
|
||||||
|
import javacard.security.KeyBuilder;
|
||||||
|
import javacard.security.RSAPrivateKey;
|
||||||
|
import javacardx.crypto.Cipher;
|
||||||
|
|
||||||
|
public class Crypt {
|
||||||
|
public static final short AES_MODE_GKEY_ENCRYPT = 0;
|
||||||
|
public static final short AES_MODE_GKEY_DECRYPT = 1;
|
||||||
|
public static final short AES_MODE_CKEY_ENCRYPT = 2;
|
||||||
|
public static final short AES_MODE_CKEY_DECRYPT = 3;
|
||||||
|
public static final short RSA_MODE_DECRYPT = 4;
|
||||||
|
|
||||||
|
private AESKey m_ee_aesKeyEnc = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, (short) 128, false);
|
||||||
|
private AESKey m_ee_aesKeyDec = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, (short) 128, false);
|
||||||
|
|
||||||
|
private AESKey m_ee_aesConnectionKeyEnc = (AESKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_RSA_CRT_PRIVATE,
|
||||||
|
(short) 128, false);
|
||||||
|
private AESKey m_ee_aesConnectionKeyDec = (AESKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_RSA_CRT_PRIVATE,
|
||||||
|
(short) 128, false);
|
||||||
|
|
||||||
|
private RSAPrivateKey key_ecf2m = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.ALG_TYPE_EC_F2M_PUBLIC,
|
||||||
|
(short) 2048,
|
||||||
|
false);
|
||||||
|
private Cipher m_ee_cipherRsa = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
|
||||||
|
|
||||||
|
private Cipher m_ee_cipherAesEnc = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||||
|
private Cipher m_ee_cipherAesDec = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||||
|
private Cipher m_ee_cipherConnectionAesDec = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||||
|
private Cipher m_ee_cipherConnectionAesEnc = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
|
||||||
|
|
||||||
|
public short doFinal(byte[] src, short srcOffset, short srcLength, byte[] dst, short dstOffset, short which) {
|
||||||
|
if (srcLength > (src.length - srcOffset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (which) {
|
||||||
|
case AES_MODE_GKEY_ENCRYPT:
|
||||||
|
return this.m_ee_cipherAesEnc.doFinal(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case AES_MODE_GKEY_DECRYPT:
|
||||||
|
return this.m_ee_cipherAesDec.doFinal(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case AES_MODE_CKEY_ENCRYPT:
|
||||||
|
return this.m_ee_cipherConnectionAesEnc.doFinal(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case AES_MODE_CKEY_DECRYPT:
|
||||||
|
return this.m_ee_cipherConnectionAesDec.doFinal(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case RSA_MODE_DECRYPT:
|
||||||
|
return this.m_ee_cipherRsa.doFinal(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short update(byte[] src, short srcOffset, short srcLength, byte[] dst, short dstOffset, short mode) {
|
||||||
|
if (srcLength > (src.length - srcOffset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case AES_MODE_GKEY_ENCRYPT:
|
||||||
|
return this.m_ee_cipherAesEnc.update(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case AES_MODE_GKEY_DECRYPT:
|
||||||
|
return this.m_ee_cipherAesDec.update(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case AES_MODE_CKEY_ENCRYPT:
|
||||||
|
return this.m_ee_cipherConnectionAesEnc.update(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case AES_MODE_CKEY_DECRYPT:
|
||||||
|
return this.m_ee_cipherConnectionAesDec.update(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
case RSA_MODE_DECRYPT:
|
||||||
|
return this.m_ee_cipherRsa.update(src, srcOffset, srcLength, dst, dstOffset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean init(byte[] data1, short data1Offset, short data1Length, byte[] data2, short data2Offset,
|
||||||
|
short data2Length, short mode) {
|
||||||
|
if (data1Length > (data1.length - data1Offset) || data2Length > (data2.length - data2Offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case AES_MODE_GKEY_ENCRYPT:
|
||||||
|
this.m_ee_aesKeyEnc.setKey(data1, data1Offset);
|
||||||
|
this.m_ee_cipherAesEnc.init(this.m_ee_aesKeyEnc, Cipher.MODE_ENCRYPT, data2, data2Offset, data2Length);
|
||||||
|
return true;
|
||||||
|
case AES_MODE_GKEY_DECRYPT:
|
||||||
|
this.m_ee_aesKeyDec.setKey(data1, data1Offset);
|
||||||
|
this.m_ee_cipherAesDec.init(this.m_ee_aesKeyDec, Cipher.MODE_DECRYPT, data2, data2Offset, data2Length);
|
||||||
|
return true;
|
||||||
|
case AES_MODE_CKEY_ENCRYPT:
|
||||||
|
this.m_ee_aesConnectionKeyEnc.setKey(data1, data1Offset);
|
||||||
|
this.m_ee_cipherConnectionAesEnc.init(this.m_ee_aesConnectionKeyEnc, Cipher.MODE_ENCRYPT, data2,
|
||||||
|
data2Offset, data2Length);
|
||||||
|
return true;
|
||||||
|
case AES_MODE_CKEY_DECRYPT:
|
||||||
|
this.m_ee_aesConnectionKeyDec.setKey(data1, data1Offset);
|
||||||
|
this.m_ee_cipherConnectionAesDec.init(this.m_ee_aesConnectionKeyDec, Cipher.MODE_DECRYPT, data2,
|
||||||
|
data2Offset,
|
||||||
|
data2Length);
|
||||||
|
return true;
|
||||||
|
case RSA_MODE_DECRYPT:
|
||||||
|
this.key_ecf2m.setModulus(data1, data1Offset, data1Length);
|
||||||
|
this.key_ecf2m.setExponent(data2, data2Offset, data2Length);
|
||||||
|
this.m_ee_cipherRsa.init(this.key_ecf2m, Cipher.MODE_DECRYPT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
35
src/sega/a7/EepInit.java
Normal file
35
src/sega/a7/EepInit.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class EepInit extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public EepInit(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
this.m_ee_data.reset();
|
||||||
|
byte[] modulus = this.m_ee_data.getRsaDefaultPriModulus_ee();
|
||||||
|
byte[] exponent = this.m_ee_data.getRsaDefaultPriExponent_ee();
|
||||||
|
byte[] tmp = this.m_ee_data.getCryptBuffer_ramD();
|
||||||
|
Util.arrayFillNonAtomic(tmp, (short) 0, (short) tmp.length, (byte) -1);
|
||||||
|
|
||||||
|
if (!this.m_ee_data.setRsaPriKeyExponent_ee(exponent, (short) 0, AppConfig.RSA_PRI_EXPONENT_SIZE))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
|
||||||
|
if (!this.m_ee_data.setRsaPriKeyModulus_ee(modulus, (short) 0, AppConfig.RSA_PRI_MODULUS_SIZE))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
|
||||||
|
changeRsaKey_ee(modulus, (short) 0, AppConfig.RSA_PRI_MODULUS_SIZE, exponent, (short) 0, AppConfig.RSA_PRI_EXPONENT_SIZE);
|
||||||
|
changeGKey_ee(tmp, (short) 0, (short) tmp.length, tmp, (short) 0, (short) tmp.length);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
24
src/sega/a7/ErrorGet.java
Normal file
24
src/sega/a7/ErrorGet.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class ErrorGet extends Command {
|
||||||
|
private static final short RECV_PACKET_SIZE = 26;
|
||||||
|
private static final short PARAM_SIZE = 28;
|
||||||
|
|
||||||
|
public ErrorGet(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_errorBuf = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
short ramD_lastError = this.m_ee_data.getLastError_ramD();
|
||||||
|
Util.setShort(ramD_errorBuf, (short) 0, ramD_lastError);
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = 2;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_errorBuf, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
44
src/sega/a7/GkeyDec.java
Normal file
44
src/sega/a7/GkeyDec.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class GkeyDec extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 63;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
private static final short IV_INIT_OFFSET = 6;
|
||||||
|
private static final short DATA_OFFSET = 7;
|
||||||
|
private static final short DATA_SIZE = 16;
|
||||||
|
|
||||||
|
public GkeyDec(short cmd, AppData data, MakePacket packet, MessageDigest sha1,
|
||||||
|
HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte ramD_ivInit = data[dataOffset + IV_INIT_OFFSET];
|
||||||
|
byte[] ramD_decData = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
boolean bInit = false;
|
||||||
|
if (ramD_decData.length < 48)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + DATA_OFFSET), DATA_SIZE, ramD_decData,
|
||||||
|
(short) 0);
|
||||||
|
if (16 > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (1 == ramD_ivInit)
|
||||||
|
bInit = true;
|
||||||
|
decUpdate_Gkey(ramD_decData, (short) 0, (short) 16, ramD_decData, (short) 16, bInit);
|
||||||
|
short ramD_encSize = encData(ramD_decData, (short) 16, (short) 16, ramD_decData, (short) 32);
|
||||||
|
if (16 != ramD_encSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = 32;
|
||||||
|
this.m_ramD_outDataInfo[1] = 16;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_decData, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
44
src/sega/a7/GkeyEnc.java
Normal file
44
src/sega/a7/GkeyEnc.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class GkeyEnc extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 63;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
private static final short IV_INIT_OFFSET = 6;
|
||||||
|
private static final short DATA_OFFSET = 7;
|
||||||
|
private static final short DATA_SIZE = 16;
|
||||||
|
|
||||||
|
public GkeyEnc(short cmd, AppData data, MakePacket packet, MessageDigest sha1,
|
||||||
|
HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte ramD_ivInit = data[dataOffset + IV_INIT_OFFSET];
|
||||||
|
byte[] ramD_encData = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
boolean bInit = false;
|
||||||
|
if (ramD_encData.length < 48)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + DATA_OFFSET), DATA_SIZE, ramD_encData,
|
||||||
|
(short) 0);
|
||||||
|
if (16 > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (1 == ramD_ivInit)
|
||||||
|
bInit = true;
|
||||||
|
encUpdate_GKey(ramD_encData, (short) 0, (short) 16, ramD_encData, (short) 16, bInit);
|
||||||
|
short ramD_encSize = encData(ramD_encData, (short) 16, (short) 16, ramD_encData, (short) 32);
|
||||||
|
if (16 != ramD_encSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = 32;
|
||||||
|
this.m_ramD_outDataInfo[1] = 16;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_encData, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
34
src/sega/a7/GkeyWrite.java
Normal file
34
src/sega/a7/GkeyWrite.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class GkeyWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 78;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public GkeyWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
short ramD_dataSize = AppConfig.AES_KEY_SIZE + AppConfig.AES_IV_SIZE;
|
||||||
|
byte[] ramD_newGKey = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newGKey.length < (short) ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + 6), ramD_dataSize, ramD_newGKey, (short) 0);
|
||||||
|
|
||||||
|
if (ramD_decSize < 32)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (!changeGKey_ee(ramD_newGKey, (short) 0, AppConfig.AES_KEY_SIZE, ramD_newGKey, AppConfig.AES_KEY_SIZE,
|
||||||
|
AppConfig.AES_IV_SIZE))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
28
src/sega/a7/HmacChange.java
Normal file
28
src/sega/a7/HmacChange.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class HmacChange extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 78;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public HmacChange(short cmd, AppData data, MakePacket packet, MessageDigest sha1,
|
||||||
|
HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
short ramD_dataSize = (short) 32;
|
||||||
|
byte[] ramD_newHmac = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newHmac.length < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + 6), ramD_dataSize, ramD_newHmac, (short) 0);
|
||||||
|
if (20 > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ee_data.setKh_ramD(ramD_newHmac, (short) 0, (short) 20);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
59
src/sega/a7/HmacSha1.java
Normal file
59
src/sega/a7/HmacSha1.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class HmacSha1 {
|
||||||
|
public static short HMAC_BLOCK_SIZE = 64;
|
||||||
|
public static short INNER_PAD = 54;
|
||||||
|
public static short OUTER_PAD = 92;
|
||||||
|
|
||||||
|
private byte[] m_ramD_key = JCSystem.makeTransientByteArray(HMAC_BLOCK_SIZE, (byte) 1);
|
||||||
|
private byte[] m_ramD_padBuffer = JCSystem.makeTransientByteArray(HMAC_BLOCK_SIZE, (byte) 1);
|
||||||
|
private MessageDigest m_ee_sha1 = MessageDigest.getInstance((byte) 1, false);
|
||||||
|
|
||||||
|
public boolean update(byte[] inBuff, short inOffset, short inLength) {
|
||||||
|
if (inBuff == null || inLength <= 0 || inBuff.length < inOffset)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.m_ee_sha1.update(inBuff, inOffset, inLength);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset) {
|
||||||
|
if (inBuff == null || inLength <= 0 || sigBuff == null || inOffset + inLength > inBuff.length
|
||||||
|
|| sigOffset + 20 > sigBuff.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.m_ee_sha1.doFinal(inBuff, inOffset, inLength, sigBuff, sigOffset);
|
||||||
|
for (short ii = 0; ii < HMAC_BLOCK_SIZE; ii++)
|
||||||
|
this.m_ramD_padBuffer[ii] = (byte) (this.m_ramD_key[(short) ii] ^ OUTER_PAD);
|
||||||
|
this.m_ee_sha1.update(this.m_ramD_padBuffer, (short) 0, (short) this.m_ramD_padBuffer.length);
|
||||||
|
this.m_ee_sha1.doFinal(sigBuff, sigOffset, (short) 20, sigBuff, sigOffset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean init(byte[] key, short offset, short length) {
|
||||||
|
if (key == null || length <= 0 || key.length < offset + length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (length > this.m_ramD_key.length) {
|
||||||
|
this.m_ee_sha1.reset();
|
||||||
|
this.m_ee_sha1.doFinal(key, offset, length, this.m_ramD_key, (short) 0);
|
||||||
|
} else {
|
||||||
|
Util.arrayCopyNonAtomic(key, offset, this.m_ramD_key, (short) 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < this.m_ramD_key.length) {
|
||||||
|
Util.arrayFillNonAtomic(this.m_ramD_key, length, (short) (this.m_ramD_key.length - length), (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.m_ee_sha1.reset();
|
||||||
|
for (short ii = 0; ii < HMAC_BLOCK_SIZE; ii++) {
|
||||||
|
this.m_ramD_padBuffer[ii] = (byte) (this.m_ramD_key[ii] ^ INNER_PAD);
|
||||||
|
}
|
||||||
|
this.m_ee_sha1.init(this.m_ramD_padBuffer, (short) 0, (short) this.m_ramD_padBuffer.length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
28
src/sega/a7/KeyChange.java
Normal file
28
src/sega/a7/KeyChange.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class KeyChange extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 78;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public KeyChange(short cmd, AppData data, MakePacket packet, MessageDigest sha1,
|
||||||
|
HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
short ramD_dataSize = (short) 32;
|
||||||
|
byte[] ramD_newKey = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newKey.length < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + 6), ramD_dataSize, ramD_newKey, (short) 0);
|
||||||
|
if (32 > (short) ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
boolean bRet = changeConnectionKey_ee(ramD_newKey, (short) 0, (short) 16, ramD_newKey, (short) 16, (short) 16);
|
||||||
|
return (short) (bRet ? 0 : 11);
|
||||||
|
}
|
||||||
|
}
|
34
src/sega/a7/KeychipInfoRead.java
Normal file
34
src/sega/a7/KeychipInfoRead.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class KeychipInfoRead extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 142;
|
||||||
|
|
||||||
|
public KeychipInfoRead(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] dta, short dataOffset, short dataLength) {
|
||||||
|
byte[] ee_keychipInfo = this.m_ee_data.getKeychipInfo_ee();
|
||||||
|
byte[] ramD_encKeychipInfo = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_encKeychipInfo.length < ee_keychipInfo.length)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short encSize = encData(ee_keychipInfo, (short) 0, (short) ee_keychipInfo.length, ramD_encKeychipInfo,
|
||||||
|
(short) 0);
|
||||||
|
if (ee_keychipInfo.length > encSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_encKeychipInfo, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
33
src/sega/a7/KeychipInfoWrite.java
Normal file
33
src/sega/a7/KeychipInfoWrite.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class KeychipInfoWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 142;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public KeychipInfoWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
short ramD_dataSize = AppConfig.KEYCHIP_INFO_SIZE;
|
||||||
|
byte[] ramD_newKeychipInfo = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newKeychipInfo.length < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (AppConfig.HEADER_SIZE + dataOffset), ramD_dataSize, ramD_newKeychipInfo,
|
||||||
|
(short) 0);
|
||||||
|
if (ramD_dataSize > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (!this.m_ee_data.setKeychipInfo_ee(ramD_newKeychipInfo, (short) 0, ramD_decSize))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
25
src/sega/a7/LvEnable.java
Normal file
25
src/sega/a7/LvEnable.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class LvEnable extends Command {
|
||||||
|
private static final short RECV_PACKET_SIZE = 26;
|
||||||
|
private static final byte AUTH_LEVEL = -1;
|
||||||
|
private static final short PARAM_SIZE = 26;
|
||||||
|
private static final byte SET_AUTH_LEVEL = 0;
|
||||||
|
|
||||||
|
public LvEnable(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getLevel_ramD() != AUTH_LEVEL)
|
||||||
|
return AppConfig.A7_LV_ERROR;
|
||||||
|
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
this.m_ee_data.setLevel_ramD(SET_AUTH_LEVEL);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
25
src/sega/a7/LvGet.java
Normal file
25
src/sega/a7/LvGet.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class LvGet extends Command {
|
||||||
|
private static final short RECV_PACKET_SIZE = 26;
|
||||||
|
private static final short PARAM_SIZE = 27;
|
||||||
|
|
||||||
|
public LvGet(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_level = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
ramD_level[0] = this.m_ee_data.getLevel_ramD();
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = 1;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_level, this.m_ramD_outDataInfo[0], this.m_ramD_outData, this.m_ramD_outDataInfo[0],
|
||||||
|
this.m_ramD_outDataInfo[1]);
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
60
src/sega/a7/MakePacket.java
Normal file
60
src/sega/a7/MakePacket.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.JCSystem;
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class MakePacket {
|
||||||
|
private byte[] m_ramD_buffer = JCSystem.makeTransientByteArray((short) 20, (byte) 1);
|
||||||
|
|
||||||
|
public boolean setData(byte[] kh, short khOffset, short khLength, short tag,
|
||||||
|
short paramSize, short result, short cmd, byte[] data, short dataOffset,
|
||||||
|
short dataLength, byte[] nonceEvent, short eventOffset, short eventLength, byte[] nonceOdd,
|
||||||
|
short oddOffset, short oddLength, byte[] packet, short packetOffset, short packetLength,
|
||||||
|
MessageDigest sha1, HmacSha1 hmacSha1) {
|
||||||
|
short ramD_offset = packetOffset;
|
||||||
|
|
||||||
|
if (packet == null || packetLength < paramSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (tag != AppConfig.A7_TAG_RSP_COMMAND) {
|
||||||
|
if (tag == AppConfig.A7_TAG_RSP_AUTH_COMMAND || tag == AppConfig.A7_TAG_RSP_RSA_COMMAND) {
|
||||||
|
if (nonceEvent == null || nonceOdd == null || hmacSha1 == null)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sha1.reset();
|
||||||
|
Util.setShort(packet, ramD_offset, tag);
|
||||||
|
ramD_offset = (short) (ramD_offset + 2);
|
||||||
|
Util.setShort(packet, ramD_offset, paramSize);
|
||||||
|
ramD_offset = (short) (ramD_offset + 2);
|
||||||
|
Util.setShort(packet, ramD_offset, result);
|
||||||
|
ramD_offset = (short) (ramD_offset + 2);
|
||||||
|
Util.setShort(this.m_ramD_buffer, (short) 0, cmd);
|
||||||
|
if (data == null) {
|
||||||
|
sha1.update(packet, packetOffset, (short) (ramD_offset - packetOffset));
|
||||||
|
sha1.doFinal(this.m_ramD_buffer, (short) 0, (short) 2, packet, ramD_offset);
|
||||||
|
} else {
|
||||||
|
sha1.update(packet, packetOffset, (short) (ramD_offset - packetOffset));
|
||||||
|
sha1.update(this.m_ramD_buffer, (short) 0, (short) 2);
|
||||||
|
Util.arrayCopyNonAtomic(data, dataOffset, packet, ramD_offset, dataLength);
|
||||||
|
ramD_offset = (short) (ramD_offset + dataLength);
|
||||||
|
sha1.doFinal(data, dataOffset, dataLength, packet, ramD_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag == AppConfig.A7_TAG_RSP_COMMAND)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Util.arrayCopyNonAtomic(packet, (short) ramD_offset, this.m_ramD_buffer, (short) 0, (short) 20);
|
||||||
|
Util.arrayCopyNonAtomic(nonceEvent, (short) eventOffset, packet, (short) ramD_offset, (short) eventLength);
|
||||||
|
ramD_offset = (short) ((short) ramD_offset + (short) eventLength);
|
||||||
|
hmacSha1.init(kh, (short) khOffset, (short) khLength);
|
||||||
|
hmacSha1.update(this.m_ramD_buffer, (short) 0, (short) 20);
|
||||||
|
hmacSha1.update(nonceEvent, (short) eventOffset, (short) eventLength);
|
||||||
|
hmacSha1.sign(nonceOdd, (short) oddOffset, (short) oddLength, packet, (short) ramD_offset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
23
src/sega/a7/NoCommand.java
Normal file
23
src/sega/a7/NoCommand.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class NoCommand extends Command {
|
||||||
|
public NoCommand(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, (short) 0, (short) 26, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short execute(byte[] data, short cmd, short dataLength, byte[] dst, short dstOffset, short dstLength) {
|
||||||
|
return (6 > dataLength) ? makeNoCommandErrorPacket((short) 4, cmd, dst, dstOffset, dstLength)
|
||||||
|
: makeNoCommandErrorPacket((short) 7, cmd, dst, dstOffset, dstLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private short makeNoCommandErrorPacket(short error, short cmd, byte[] sendPacket, short packetOffset,
|
||||||
|
short packetLength) {
|
||||||
|
this.m_ee_data.setLastError_ramD(error);
|
||||||
|
this.m_ee_packet.setData(null, (short) 0, (short) 0, AppConfig.A7_TAG_RSP_COMMAND, (short) 26, error,
|
||||||
|
cmd, null, (short) 0, (short) 0, null, (short) 0, (short) 0, null, (short) 0, (short) 0,
|
||||||
|
sendPacket, packetOffset, packetLength, this.m_ee_sha1, null);
|
||||||
|
return 26;
|
||||||
|
}
|
||||||
|
}
|
27
src/sega/a7/PlayCountIncrement.java
Normal file
27
src/sega/a7/PlayCountIncrement.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class PlayCountIncrement extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 47;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public PlayCountIncrement(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] arrayOfByte = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (arrayOfByte.length < 1)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (dataLength < (short) (6 + dataOffset + 1))
|
||||||
|
return AppConfig.A7_BAD_DATASIZE;
|
||||||
|
|
||||||
|
arrayOfByte[0] = data[(short) (6 + dataOffset)];
|
||||||
|
this.m_ee_data.addValuePlayCounter_ee(arrayOfByte[0]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
40
src/sega/a7/PlayCountRead.java
Normal file
40
src/sega/a7/PlayCountRead.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
import javacard.security.RandomData;
|
||||||
|
|
||||||
|
public class PlayCountRead extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
private static final short PLAY_COUNT_VALUE_SIZE = 4;
|
||||||
|
private static final short RANDOM_VALUE_SIZE = 12;
|
||||||
|
private static final short ENC_DATA_SIZE = 16;
|
||||||
|
private RandomData m_ee_rand;
|
||||||
|
|
||||||
|
public PlayCountRead(short cmd, AppData data, MakePacket packet, MessageDigest sha1,
|
||||||
|
HmacSha1 hmacSha1, Crypt crypt, RandomData rand) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
this.m_ee_rand = rand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_playCount = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_playCount.length < PLAY_COUNT_VALUE_SIZE + RANDOM_VALUE_SIZE + ENC_DATA_SIZE)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
this.m_ee_rand.generateData(ramD_playCount, (short) 0, (short) (PLAY_COUNT_VALUE_SIZE + RANDOM_VALUE_SIZE));
|
||||||
|
this.m_ee_data.getPlayCounter_ee(ramD_playCount, (short) 0, PLAY_COUNT_VALUE_SIZE);
|
||||||
|
short ramD_encSize = encData(ramD_playCount, (short) 0, ENC_DATA_SIZE, ramD_playCount,
|
||||||
|
(short) (PLAY_COUNT_VALUE_SIZE + RANDOM_VALUE_SIZE));
|
||||||
|
if (ramD_encSize != ENC_DATA_SIZE)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_OFFSET] = 16;
|
||||||
|
this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_SIZE] = ramD_encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_playCount, this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_OFFSET],
|
||||||
|
this.m_ramD_outData, this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_OFFSET],
|
||||||
|
this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_SIZE]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
41
src/sega/a7/PrikeyExponentWrite.java
Normal file
41
src/sega/a7/PrikeyExponentWrite.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class PrikeyExponentWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 302;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public PrikeyExponentWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
short ramD_dataSize = (short) 256;
|
||||||
|
byte[] ramD_newRSAKey = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newRSAKey.length < (short) ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (6 + dataOffset), ramD_dataSize, ramD_newRSAKey, (short) 0);
|
||||||
|
if (ramD_dataSize > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
if (!this.m_ee_data.setRsaPriKeyExponent_ee(ramD_newRSAKey, (short) 0, (short) 256))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
|
||||||
|
this.m_ee_data.activeRssaExponentUpdate_ramD();
|
||||||
|
if (this.m_ee_data.getRsaModulusUpdate_ramD()) {
|
||||||
|
byte[] exponent = this.m_ee_data.getRsaPriExponent_ee();
|
||||||
|
byte[] modulus = this.m_ee_data.getRsaPriModulus_ee();
|
||||||
|
if (!changeRsaKey_ee(modulus, (short) 0, (short) modulus.length, exponent, (short) 0,
|
||||||
|
(short) exponent.length))
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
42
src/sega/a7/PrivkeyModulusWrite.java
Normal file
42
src/sega/a7/PrivkeyModulusWrite.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class PrivkeyModulusWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 302;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public PrivkeyModulusWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
short ramD_dataSize = (short) 256;
|
||||||
|
byte[] ramD_newRSAKey = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newRSAKey.length < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (6 + dataOffset), ramD_dataSize, ramD_newRSAKey, (short) 0);
|
||||||
|
if (ramD_dataSize > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (!this.m_ee_data.setRsaPriKeyModulus_ee(ramD_newRSAKey, (short) 0, (short) 256))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
|
||||||
|
this.m_ee_data.activeRssaModulusUpdate_ramD();
|
||||||
|
if (this.m_ee_data.getRsaExponentUpdate_ramD()) {
|
||||||
|
byte[] exponent = this.m_ee_data.getRsaPriExponent_ee();
|
||||||
|
byte[] modulus = this.m_ee_data.getRsaPriModulus_ee();
|
||||||
|
if (!changeRsaKey_ee(modulus, (short) 0, (short) modulus.length, exponent, (short) 0,
|
||||||
|
(short) exponent.length))
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
37
src/sega/a7/RanGet.java
Normal file
37
src/sega/a7/RanGet.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
import javacard.security.RandomData;
|
||||||
|
|
||||||
|
public class RanGet extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
private static final short RAN_SIZE = 16;
|
||||||
|
|
||||||
|
private RandomData m_ee_rand;
|
||||||
|
|
||||||
|
public RanGet(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt,
|
||||||
|
RandomData rand) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
this.m_ee_rand = rand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_ranData = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_ranData.length < 32)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ee_rand.generateData(ramD_ranData, (short) 0, RAN_SIZE);
|
||||||
|
short ramD_encSize = encData(ramD_ranData, (short) 0, RAN_SIZE, ramD_ranData, RAN_SIZE);
|
||||||
|
if (ramD_encSize != 16)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = RAN_SIZE;
|
||||||
|
this.m_ramD_outDataInfo[1] = ramD_encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_ranData, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
17
src/sega/a7/SessionClose.java
Normal file
17
src/sega/a7/SessionClose.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class SessionClose extends Command {
|
||||||
|
private static final short RECV_PACKET_SIZE = 26;
|
||||||
|
private static final short PARAM_SIZE = 26;
|
||||||
|
|
||||||
|
public SessionClose(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
this.m_ee_data.setSession_ramD(AppData.SESSION_DISABLE);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
25
src/sega/a7/SessionOpen.java
Normal file
25
src/sega/a7/SessionOpen.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class SessionOpen extends Command {
|
||||||
|
private static final short RECV_PACKET_SIZE = 26;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public SessionOpen(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_nonceEvent = this.m_ee_data.getNewNonceEvent_ramD();
|
||||||
|
this.m_ee_data.setLastNonceEvent_ramD(ramD_nonceEvent, (short) 0, (short) ramD_nonceEvent.length);
|
||||||
|
this.m_ee_data.setSession_ramD(AppData.SESSION_ENABLE);
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = (byte) ramD_nonceEvent.length;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_nonceEvent, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
21
src/sega/a7/SflagWrite.java
Normal file
21
src/sega/a7/SflagWrite.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class SflagWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public SflagWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
this.m_ee_data.activeSflag();
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
38
src/sega/a7/StorageRead.java
Normal file
38
src/sega/a7/StorageRead.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class StorageRead extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 50;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
private static final short READ_OFFSET_OFFSET = 6;
|
||||||
|
private static final short DATA_SIZE_OFFSET = 8;
|
||||||
|
|
||||||
|
public StorageRead(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
short ramD_readSize = Util.getShort(data, (short) (dataOffset + DATA_SIZE_OFFSET));
|
||||||
|
if ((ramD_readSize % 16) != 0)
|
||||||
|
ramD_readSize = (short) (ramD_readSize + (short) (16 - (short) (ramD_readSize % 16)));
|
||||||
|
short ramD_bufferOffset = (short) Util.getShort(data, (short) (dataOffset + READ_OFFSET_OFFSET));
|
||||||
|
byte[] ee_storageData = this.m_ee_data.getStorageData_ee();
|
||||||
|
byte[] ramD_encStorageData = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_encStorageData.length < ramD_readSize || 192 < ramD_readSize || ramD_readSize == 0
|
||||||
|
|| AppConfig.STORAGE_SIZE < (short) (ramD_readSize + ramD_bufferOffset))
|
||||||
|
return AppConfig.A7_BAD_PARAMETER;
|
||||||
|
short ramD_encSize = encData(ee_storageData, ramD_bufferOffset, ramD_readSize, ramD_encStorageData, (short) 0);
|
||||||
|
if (ramD_readSize > ramD_encSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = ramD_encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_encStorageData, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
setSendPacketSize_ramD((short) (46 + ramD_readSize));
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
41
src/sega/a7/StorageSizeGet.java
Normal file
41
src/sega/a7/StorageSizeGet.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
import javacard.security.RandomData;
|
||||||
|
|
||||||
|
public class StorageSizeGet extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
private static final short STORAGE_SIZE_VALUE_SIZE = 2;
|
||||||
|
private static final short RANDOM_VALUE_SIZE = 14;
|
||||||
|
private static final short ENC_DATA_SIZE = 16;
|
||||||
|
private RandomData m_ee_rand;
|
||||||
|
|
||||||
|
public StorageSizeGet(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt,
|
||||||
|
RandomData rand) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
this.m_ee_rand = rand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_storageSize = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_storageSize.length < (short) (STORAGE_SIZE_VALUE_SIZE + RANDOM_VALUE_SIZE + ENC_DATA_SIZE))
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ee_rand.generateData(ramD_storageSize, (short) 0, (short) (STORAGE_SIZE_VALUE_SIZE + RANDOM_VALUE_SIZE));
|
||||||
|
Util.setShort(ramD_storageSize, (short) 0, AppConfig.STORAGE_SIZE);
|
||||||
|
short ramD_encSize = encData(ramD_storageSize, (short) 0, ENC_DATA_SIZE, ramD_storageSize,
|
||||||
|
(short) (STORAGE_SIZE_VALUE_SIZE + RANDOM_VALUE_SIZE));
|
||||||
|
if (ramD_encSize != ENC_DATA_SIZE)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = (short) (STORAGE_SIZE_VALUE_SIZE + RANDOM_VALUE_SIZE);
|
||||||
|
this.m_ramD_outDataInfo[1] = ramD_encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_storageSize, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
41
src/sega/a7/StorageWrite.java
Normal file
41
src/sega/a7/StorageWrite.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class StorageWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 0;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
private static final short RECV_PACKET_EXCLUDING_DATA_SIZE = 50;
|
||||||
|
private static final short DATA_SIZE_OFFSET = 6;
|
||||||
|
private static final short WRITE_OFFSET_OFFSET = 8;
|
||||||
|
private static final short WRITE_DATA_OFFSET = 10;
|
||||||
|
|
||||||
|
public StorageWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
short ramD_paramsize = Util.getShort(data, (short) (dataOffset + 2));
|
||||||
|
short ramD_encDataSize = (short) (ramD_paramsize - RECV_PACKET_EXCLUDING_DATA_SIZE);
|
||||||
|
short ramD_wirteDataSize = Util.getShort(data, (short) (dataOffset + DATA_SIZE_OFFSET));
|
||||||
|
short ramD_bufferOffset = Util.getShort(data, (short) (dataOffset + WRITE_OFFSET_OFFSET));
|
||||||
|
byte[] ramD_newWriteData = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
|
||||||
|
if ((ramD_encDataSize % 16) != 0 || ramD_newWriteData.length < ramD_encDataSize
|
||||||
|
|| ramD_wirteDataSize == 0
|
||||||
|
|| ramD_wirteDataSize + ramD_bufferOffset > AppConfig.STORAGE_SIZE)
|
||||||
|
return AppConfig.A7_BAD_PARAMETER;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + WRITE_DATA_OFFSET), ramD_encDataSize,
|
||||||
|
ramD_newWriteData, (short) 0);
|
||||||
|
if (ramD_wirteDataSize > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (!this.m_ee_data.setStorageData_ee(ramD_newWriteData, (short) 0, ramD_wirteDataSize, ramD_bufferOffset))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
33
src/sega/a7/TraceDataInfoRead.java
Normal file
33
src/sega/a7/TraceDataInfoRead.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class TraceDataInfoRead extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
|
||||||
|
public TraceDataInfoRead(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ee_traceDataInfo = this.m_ee_data.getTraceDataInfo_ee();
|
||||||
|
byte[] ramD_encTraceDataInfo = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_encTraceDataInfo.length < ee_traceDataInfo.length)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_encSize = encData(ee_traceDataInfo, (short) 0, (short) ee_traceDataInfo.length,
|
||||||
|
ramD_encTraceDataInfo, (short) 0);
|
||||||
|
if (ee_traceDataInfo.length > (short) ramD_encSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = ramD_encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_encTraceDataInfo, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
30
src/sega/a7/TraceDataInfoWrite.java
Normal file
30
src/sega/a7/TraceDataInfoWrite.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class TraceDataInfoWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 62;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public TraceDataInfoWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1,
|
||||||
|
Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
short ramD_dataSize = 16;
|
||||||
|
byte[] ramD_newTraceDataInfo = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newTraceDataInfo.length < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + 6), ramD_dataSize, ramD_newTraceDataInfo, (short) 0);
|
||||||
|
|
||||||
|
if (ramD_decSize < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
if (!this.m_ee_data.setTraceDataInfo_ee(ramD_newTraceDataInfo, (short) 0, ramD_decSize))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
33
src/sega/a7/UdataRead.java
Normal file
33
src/sega/a7/UdataRead.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class UdataRead extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 46;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 62;
|
||||||
|
|
||||||
|
public UdataRead(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ee_udata = this.m_ee_data.getUdata_ee();
|
||||||
|
byte[] ramD_encUdata = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_encUdata.length < ee_udata.length)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_encSize = encData(ee_udata, (short) 0, (short) ee_udata.length, ramD_encUdata, (short) 0);
|
||||||
|
if (ramD_encSize < ee_udata.length)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_OFFSET] = 0;
|
||||||
|
this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_SIZE] = ramD_encSize;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_encUdata, this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_OFFSET],
|
||||||
|
this.m_ramD_outData, this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_OFFSET],
|
||||||
|
this.m_ramD_outDataInfo[AppConfig.SEND_BUUFER_INFO_SIZE]);
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
32
src/sega/a7/UdataWrite.java
Normal file
32
src/sega/a7/UdataWrite.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class UdataWrite extends AuthCommand {
|
||||||
|
private static final short RECV_PACKET_SIZE = 62;
|
||||||
|
private static final byte AUTH_LEVEL = 2;
|
||||||
|
private static final short PARAM_SIZE = 46;
|
||||||
|
|
||||||
|
public UdataWrite(short cmd, AppData data, MakePacket packet, MessageDigest sha1, HmacSha1 hmacSha1, Crypt crypt) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, AUTH_LEVEL, data, packet, sha1, hmacSha1, crypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
if (this.m_ee_data.getSflag_ee())
|
||||||
|
return AppConfig.A7_EEPWRITE_DISABLE;
|
||||||
|
|
||||||
|
short ramD_dataSize = AppConfig.UDATA_SIZE;
|
||||||
|
byte[] ramD_newUdata = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
if (ramD_newUdata.length < ramD_dataSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
|
||||||
|
short ramD_decSize = decData(data, (short) (dataOffset + 6), ramD_dataSize, ramD_newUdata, (short) 0);
|
||||||
|
|
||||||
|
if (ramD_dataSize > ramD_decSize)
|
||||||
|
return AppConfig.A7_FAIL;
|
||||||
|
if (!this.m_ee_data.setUdata_ee(ramD_newUdata, (short) 0, ramD_dataSize))
|
||||||
|
return AppConfig.A7_EEP_WRITEFAIL;
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
24
src/sega/a7/VerGet.java
Normal file
24
src/sega/a7/VerGet.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package sega.a7;
|
||||||
|
|
||||||
|
import javacard.framework.Util;
|
||||||
|
import javacard.security.MessageDigest;
|
||||||
|
|
||||||
|
public class VerGet extends Command {
|
||||||
|
private static final short RECV_PACKET_SIZE = 26;
|
||||||
|
private static final short PARAM_SIZE = 28;
|
||||||
|
|
||||||
|
public VerGet(short cmd, AppData data, MakePacket packet, MessageDigest sha1) {
|
||||||
|
super(cmd, RECV_PACKET_SIZE, PARAM_SIZE, data, packet, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short core(byte[] data, short dataOffset, short dataLength) {
|
||||||
|
byte[] ramD_version = this.m_ee_data.getGeneralBuffer_ramD();
|
||||||
|
Util.setShort(ramD_version, (short) 0, AppConfig.VERSION);
|
||||||
|
this.m_ramD_outDataInfo[0] = 0;
|
||||||
|
this.m_ramD_outDataInfo[1] = 2;
|
||||||
|
Util.arrayCopyNonAtomic(ramD_version, this.m_ramD_outDataInfo[0], this.m_ramD_outData,
|
||||||
|
this.m_ramD_outDataInfo[0], this.m_ramD_outDataInfo[1]);
|
||||||
|
|
||||||
|
return AppConfig.A7_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user