输入80E3,可执行算法正确性检验,验证通过,对len=38Bytes明文加密结果符合预期、解密结果符合输入;
输入80E2,可写入密钥到flash,若算法类型、key id, key版本一致,就写入,已满就报错,无记录就写入新记录; 输入80CA,可执行伪位置加密,原封不动将输入的data返回回来。
This commit is contained in:
@@ -58,6 +58,7 @@ public final class Method {
|
||||
ctx = new Zuc256EncryptCtx(); // 仅创建一次
|
||||
}
|
||||
|
||||
|
||||
public void processData(APDU apdu) {
|
||||
short L = (short) INPUT.length;
|
||||
byte[] buf1; // Enc(Input)
|
||||
@@ -92,8 +93,113 @@ public final class Method {
|
||||
apdu.sendBytes((short)0, outLen);
|
||||
}
|
||||
|
||||
// 本任务不需要更新Key,这里留空
|
||||
public void updateKey(APDU apdu) {
|
||||
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
|
||||
/**
|
||||
* fake数据生成函数
|
||||
* 输入: stmsi[6], data[5]
|
||||
* 输出: fakedata[5]
|
||||
*/
|
||||
private void makeFakeData(byte[] stmsi, byte[] data, byte[] fakedata) {
|
||||
// 示例:逐字节异或 stmsi 前5字节
|
||||
for (short i = 0; i < (short)5; i++) {
|
||||
fakedata[i] = (byte)(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU处理函数
|
||||
*/
|
||||
public short processDataFake(byte[] buffer, short off, short len, byte[] key_store) {
|
||||
// 至少要有 12 个字节:1+1+1+6+5
|
||||
if (len < (short)12) {
|
||||
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
|
||||
}
|
||||
|
||||
// === 解析入参 ===
|
||||
byte inType = buffer[(short)(off + 0)]; // 类型 A1
|
||||
byte inLen = buffer[(short)(off + 1)]; // 长度 0x0C
|
||||
byte secParam = buffer[(short)(off + 2)]; // 安全参数
|
||||
|
||||
// STMSI
|
||||
byte[] stmsi = JCSystem.makeTransientByteArray((short)6, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||
Util.arrayCopyNonAtomic(buffer, (short)(off + 3), stmsi, (short)0, (short)6);
|
||||
|
||||
// data
|
||||
byte[] data = JCSystem.makeTransientByteArray((short)5, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||
Util.arrayCopyNonAtomic(buffer, (short)(off + 9), data, (short)0, (short)5);
|
||||
|
||||
// === 生成 fakedata ===
|
||||
byte[] fakedata = JCSystem.makeTransientByteArray((short)5, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||
makeFakeData(stmsi, data, fakedata);
|
||||
|
||||
// === 出参组装 ===
|
||||
buffer[(short)(off + 0)] = (byte)0xA1; // 类型
|
||||
buffer[(short)(off + 1)] = (byte)0x06; // 长度
|
||||
buffer[(short)(off + 2)] = (byte)0x01; // 密钥选取
|
||||
Util.arrayCopyNonAtomic(fakedata, (short)0, buffer, (short)(off + 3), (short)5);
|
||||
|
||||
return (short)8; // 出参总长度
|
||||
}
|
||||
|
||||
|
||||
|
||||
public short updateKey(byte[] buffer, short off, short len, byte[] key_store) {
|
||||
final short SLOT_SIZE = 40; // 每个槽固定40字节
|
||||
final short HDR_LEN = 4; // 报文头长度: [0]=keyLenField, [1]=alg, [2]=keyId, [3]=ver
|
||||
|
||||
// === 解析头 ===
|
||||
byte keyLenField = buffer[(short)(off + 0)]; // 包含头部+密钥的总长度
|
||||
byte alg = buffer[(short)(off + 1)];
|
||||
byte keyId = buffer[(short)(off + 2)];
|
||||
byte ver = buffer[(short)(off + 3)];
|
||||
|
||||
// 计算实际密钥长度
|
||||
short realKeyLen = (short)(keyLenField - (byte)3); // 长度字段 = key长度 + 3字节头
|
||||
if (realKeyLen <= 0) {
|
||||
ISOException.throwIt(ISO7816.SW_DATA_INVALID); // key长度不合法
|
||||
}
|
||||
|
||||
// 检查APDU长度和key长度是否匹配
|
||||
if (len != (short)(HDR_LEN + realKeyLen)) {
|
||||
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
|
||||
}
|
||||
if (len > SLOT_SIZE) {
|
||||
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
|
||||
}
|
||||
|
||||
// === 将原有 key_store 拷贝到 RAM,避免直接覆盖 EEPROM (可选) ===
|
||||
byte[] key_buf = JCSystem.makeTransientByteArray((short)80, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||
Util.arrayCopyNonAtomic(key_store, (short)0, key_buf, (short)0, (short)key_store.length);
|
||||
|
||||
// === 遍历槽,找到匹配的 (alg, keyId, ver),否则找空槽 ===
|
||||
short slots = (short)(key_store.length / SLOT_SIZE);
|
||||
short target = -1;
|
||||
for (short i = 0; i < slots; i++) {
|
||||
short base = (short)(i * SLOT_SIZE);
|
||||
byte algOld = key_store[(short)(base + 1)];
|
||||
byte keyIdOld = key_store[(short)(base + 2)];
|
||||
byte verOld = key_store[(short)(base + 3)];
|
||||
|
||||
if (algOld == alg && keyId == keyIdOld && ver == verOld) {
|
||||
target = i; // 找到已存在的,覆盖它
|
||||
break;
|
||||
}
|
||||
if (key_store[base] == (byte)0x00 && target == -1) {
|
||||
target = i; // 找到第一个空槽
|
||||
}
|
||||
}
|
||||
|
||||
if (target == -1) {
|
||||
ISOException.throwIt(ISO7816.SW_FILE_FULL); // 没有空位
|
||||
}
|
||||
|
||||
// === 覆盖写入本次APDU的头+密钥数据 ===
|
||||
short base = (short)(target * SLOT_SIZE);
|
||||
// 先清空槽
|
||||
Util.arrayFillNonAtomic(key_store, base, SLOT_SIZE, (byte)0x00);
|
||||
// 再写入APDU传入的头+数据 (len 个字节)
|
||||
Util.arrayCopyNonAtomic(buffer, off, key_store, base, len);
|
||||
|
||||
return 0; // 无返回数据
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user