Initial code commit

This commit is contained in:
Bottersnike 2023-04-13 19:16:03 +01:00
parent b4f5823828
commit dccd926fc9
41 changed files with 2329 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
lib/

6
README.md Normal file
View 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
View 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();
}
}

View 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;
}
}

View 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
View 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;
}
}

View 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;
}
}

View 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
View 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;
}
}

View 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
View 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
View 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
View 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
View 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
View 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;
}
}

View 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;
}
}

View 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
View 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;
}
}

View 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);
}
}

View 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;
}
}

View 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
View 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
View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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
View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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
View 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;
}
}