Compare commits
18 Commits
4dcf92584c
...
zcy_dev_ca
| Author | SHA1 | Date | |
|---|---|---|---|
| 4af4d3342e | |||
| 506c89cc09 | |||
| c8608321d9 | |||
| 7425c4d980 | |||
| 088c0c00f6 | |||
| 2549f565b4 | |||
| 2f79d18966 | |||
| 7f529c4bd2 | |||
| 9405e59ac9 | |||
| dec1fecc16 | |||
| fe4e0ff4e6 | |||
| 8e25aab97a | |||
| 5456e990e6 | |||
| b41fff9d09 | |||
| 98d411d70d | |||
| ed52d849a4 | |||
| a74ab6f212 | |||
| 57b385aaa2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ __pycache__
|
|||||||
/.gradle/
|
/.gradle/
|
||||||
/.idea/
|
/.idea/
|
||||||
/Project/bin/
|
/Project/bin/
|
||||||
|
/se-algo.iml
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.cscn;
|
|
||||||
|
|
||||||
import javacard.framework.APDU;
|
|
||||||
|
|
||||||
public class Method {
|
|
||||||
|
|
||||||
public void processData(APDU apdu)
|
|
||||||
{
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateKey(APDU apdu)
|
|
||||||
{
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.cscn;
|
|
||||||
|
|
||||||
import javacard.framework.APDU;
|
|
||||||
import javacard.framework.Applet;
|
|
||||||
import javacard.framework.ISO7816;
|
|
||||||
import javacard.framework.ISOException;
|
|
||||||
import org.globalplatform.GPSystem;
|
|
||||||
import org.globalplatform.SecureChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author liuww
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class XwSecurity extends Applet {
|
|
||||||
|
|
||||||
public static final byte INS_PROCESS_DATA = (byte)0xCA;
|
|
||||||
|
|
||||||
public static final byte INS_STORE_DATA = (byte)0xE2;
|
|
||||||
|
|
||||||
public static final byte INS_INITIAL_UPDATE = (byte)0x50;
|
|
||||||
|
|
||||||
public static final byte INS_EXTERNAL_AUTH = (byte)0x82;
|
|
||||||
|
|
||||||
private Method method;
|
|
||||||
|
|
||||||
public XwSecurity(byte[] bArray, short bOffset, byte bLength) {
|
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
method = new Method();
|
|
||||||
|
|
||||||
register(bArray, (short)(bOffset + 1), bArray[bOffset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void install(byte[] bArray, short bOffset, byte bLength)
|
|
||||||
{
|
|
||||||
// GP-compliant JavaCard applet registration
|
|
||||||
new XwSecurity(bArray, bOffset, bLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void process(APDU apdu)
|
|
||||||
{
|
|
||||||
// Good practice: Return 9000 on SELECT
|
|
||||||
if(selectingApplet())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(method == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] buf = apdu.getBuffer();
|
|
||||||
switch (buf[ISO7816.OFFSET_INS])
|
|
||||||
{
|
|
||||||
case INS_INITIAL_UPDATE:
|
|
||||||
SecureChannel sc = GPSystem.getSecureChannel();
|
|
||||||
sc.processSecurity(apdu);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INS_EXTERNAL_AUTH:
|
|
||||||
sc = GPSystem.getSecureChannel();
|
|
||||||
sc.processSecurity(apdu);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INS_PROCESS_DATA:
|
|
||||||
method.processData(apdu);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INS_STORE_DATA:
|
|
||||||
method.updateKey(apdu);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// good practice: If you don't know the INStruction, say so:
|
|
||||||
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
package com.zuc.zuc256;
|
|
||||||
|
|
||||||
import javacard.framework.JCSystem;
|
|
||||||
import javacard.framework.Util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密上下文类(Java Card兼容版本)
|
|
||||||
*/
|
|
||||||
public final class Zuc256EncryptCtx {
|
|
||||||
Zuc256State state;
|
|
||||||
byte[] buf;
|
|
||||||
short buflen;
|
|
||||||
|
|
||||||
// 构造函数 - 使用已分配的缓冲区
|
|
||||||
public Zuc256EncryptCtx(Zuc256State state, byte[] buf) {
|
|
||||||
this.state = state;
|
|
||||||
this.buf = buf;
|
|
||||||
this.buflen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构造函数 - 自动分配缓冲区
|
|
||||||
public Zuc256EncryptCtx(Zuc256State state) {
|
|
||||||
this.state = state;
|
|
||||||
this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
|
||||||
this.buflen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构造函数 - 完整初始化
|
|
||||||
public Zuc256EncryptCtx() {
|
|
||||||
this.state = new Zuc256State();
|
|
||||||
this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.CLEAR_ON_DESELECT);
|
|
||||||
this.buflen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化加密上下文
|
|
||||||
public void init(byte[] key32, short keyOff, short keyLen, byte[] iv, short ivOff, short ivLen) {
|
|
||||||
// 清空缓冲区
|
|
||||||
Util.arrayFillNonAtomic(buf, (short)0, (short)buf.length, (byte)0);
|
|
||||||
this.buflen = 0;
|
|
||||||
// 初始化状态
|
|
||||||
Zuc256Core.initState(this.state, key32, keyOff, keyLen, iv, ivOff, ivLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分阶段处理加密数据
|
|
||||||
public void update(byte[] in, short inOff, short inlen, byte[] out, short outOff) {
|
|
||||||
if (in == null || out == null || inlen == 0) return;
|
|
||||||
|
|
||||||
short currentInOff = inOff;
|
|
||||||
short currentOutOff = outOff;
|
|
||||||
|
|
||||||
// 处理缓冲区中剩余的非4字节数据
|
|
||||||
if (this.buflen > 0) {
|
|
||||||
short need = (short)(4 - this.buflen);
|
|
||||||
short copy = (short)Math.min(inlen, need);
|
|
||||||
|
|
||||||
// 复制数据到缓冲区
|
|
||||||
Util.arrayCopyNonAtomic(in, currentInOff, this.buf, this.buflen, copy);
|
|
||||||
this.buflen += copy;
|
|
||||||
|
|
||||||
// 调整输入指针和长度
|
|
||||||
currentInOff += copy;
|
|
||||||
inlen -= copy;
|
|
||||||
|
|
||||||
// 缓冲区已满,处理一个完整的4字节块
|
|
||||||
if (this.buflen == 4) {
|
|
||||||
short keystream = zuc256GenerateKeyword(this.state);
|
|
||||||
short plain = getU16(this.buf, (short)0); // 改为16位操作
|
|
||||||
putU16(out, currentOutOff, (short)(plain ^ keystream));
|
|
||||||
|
|
||||||
// 重置缓冲区
|
|
||||||
this.buflen = 0;
|
|
||||||
Util.arrayFillNonAtomic(this.buf, (short)0, (short)this.buf.length, (byte)0);
|
|
||||||
|
|
||||||
// 调整输出指针
|
|
||||||
currentOutOff += 2; // 16位数据占2字节
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理完整的2字节块(Java Card 16位操作)
|
|
||||||
if (inlen > 0) {
|
|
||||||
short fullBlocks = (short)(inlen / 2); // 16位块
|
|
||||||
if (fullBlocks > 0) {
|
|
||||||
short[] keystream = JCSystem.makeTransientShortArray(fullBlocks, JCSystem.CLEAR_ON_DESELECT);
|
|
||||||
zuc256GenerateKeystream(this.state, fullBlocks, keystream);
|
|
||||||
|
|
||||||
// 逐块异或加密
|
|
||||||
for (short i = 0; i < fullBlocks; i++) {
|
|
||||||
short plain = getU16(in, (short)(currentInOff + (short)(i * 2)));
|
|
||||||
putU16(out, (short)(currentOutOff + (short)(i * 2)), (short)(plain ^ keystream[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调整输入指针和长度
|
|
||||||
short processed = (short)(fullBlocks * 2);
|
|
||||||
currentInOff += processed;
|
|
||||||
inlen -= processed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存剩余不足2字节的数据
|
|
||||||
if (inlen > 0) {
|
|
||||||
Util.arrayCopyNonAtomic(in, currentInOff, this.buf, (short)0, inlen);
|
|
||||||
this.buflen = inlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 完成加密处理
|
|
||||||
public void finish(byte[] out, short outOff) {
|
|
||||||
if (out == null) return;
|
|
||||||
|
|
||||||
// 处理缓冲区中剩余的不足2字节数据
|
|
||||||
if (this.buflen > 0) {
|
|
||||||
short keystream = zuc256GenerateKeyword(this.state);
|
|
||||||
byte[] keystreamBytes = JCSystem.makeTransientByteArray((short)2, JCSystem.CLEAR_ON_DESELECT);
|
|
||||||
putU16(keystreamBytes, (short)0, keystream);
|
|
||||||
|
|
||||||
// 逐字节异或
|
|
||||||
for (short i = 0; i < this.buflen; i++) {
|
|
||||||
out[(short)(outOff + i)] = (byte)(this.buf[i] ^ keystreamBytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清理上下文
|
|
||||||
Util.arrayFillNonAtomic(this.buf, (short)0, (short)this.buf.length, (byte)0);
|
|
||||||
this.buflen = 0;
|
|
||||||
// 清理状态
|
|
||||||
Util.arrayFillNonAtomic(this.state.LFSR, (short)0, (short)this.state.LFSR.length, (short)0);
|
|
||||||
this.state.R1 = 0;
|
|
||||||
this.state.R2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 16位数据读取(替代原32位实现)
|
|
||||||
private short getU16(byte[] buf, short off) {
|
|
||||||
return (short)(((buf[off] & 0xFF) << 8) | (buf[(short)(off + 1)] & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 16位数据写入(替代原32位实现)
|
|
||||||
private void putU16(byte[] buf, short off, short value) {
|
|
||||||
buf[off] = (byte)((value >>> 8) & 0xFF);
|
|
||||||
buf[(short)(off + 1)] = (byte)(value & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.cscn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MAC上下文类(JavaCard版,int 拆分为两个 short)
|
|
||||||
*/
|
|
||||||
public final class Zuc256MacCtx {
|
|
||||||
// LFSR: 原本 int[16],拆成 hi/lo 各 16 short
|
|
||||||
short[] LFSR_hi = new short[16];
|
|
||||||
short[] LFSR_lo = new short[16];
|
|
||||||
|
|
||||||
// R1、R2: 原本 int,拆成 hi/lo
|
|
||||||
short R1_hi;
|
|
||||||
short R1_lo;
|
|
||||||
short R2_hi;
|
|
||||||
short R2_lo;
|
|
||||||
|
|
||||||
// 缓冲区
|
|
||||||
byte[] buf = new byte[4];
|
|
||||||
short buflen;
|
|
||||||
|
|
||||||
// T: 原本 int[4],拆成 hi/lo
|
|
||||||
short[] T_hi = new short[4];
|
|
||||||
short[] T_lo = new short[4];
|
|
||||||
|
|
||||||
// K0: 原本 int[4],拆成 hi/lo
|
|
||||||
short[] K0_hi = new short[4];
|
|
||||||
short[] K0_lo = new short[4];
|
|
||||||
|
|
||||||
// macbits: 原本 int,改成 short 足够
|
|
||||||
short macbits;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.cscn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ZUC状态类(JavaCard版,int 拆为 hi/lo short)
|
|
||||||
*/
|
|
||||||
public final class Zuc256State {
|
|
||||||
// LFSR: 原 int[16] -> hi/lo 各 16
|
|
||||||
public short[] LFSR_hi = new short[16];
|
|
||||||
public short[] LFSR_lo = new short[16];
|
|
||||||
|
|
||||||
// R1, R2: 原 int -> hi/lo
|
|
||||||
public short R1_hi;
|
|
||||||
public short R1_lo;
|
|
||||||
public short R2_hi;
|
|
||||||
public short R2_lo;
|
|
||||||
}
|
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
package com.cscn;
|
|
||||||
|
|
||||||
import javacard.framework.Util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 辅助工具:装载/存储、位运算、线性变换、打印等。
|
|
||||||
*/
|
|
||||||
public final class Zuc256Util {
|
|
||||||
|
|
||||||
private Zuc256Util() {}
|
|
||||||
|
|
||||||
// /** 辅助方法:将字节数组转换为32位整数 */
|
|
||||||
// public static int getU32(byte[] p, int offset) {
|
|
||||||
// return ((p[offset] & 0xFF) << 24) |
|
|
||||||
// ((p[offset + 1] & 0xFF) << 16) |
|
|
||||||
// ((p[offset + 2] & 0xFF) << 8) |
|
|
||||||
// (p[offset + 3] & 0xFF);
|
|
||||||
// }
|
|
||||||
/** 辅助方法:从字节数组取出 32 位整数,存放到 short[2] (lo, hi) */
|
|
||||||
public static void getU32(byte[] p, short offset, short[] out32 /* len=2 */) {
|
|
||||||
out32[0] = (short) (((p[offset + 2] & 0xFF) << 8) | (p[offset + 3] & 0xFF)); //低16位
|
|
||||||
out32[1] = (short) (((p[offset] & 0xFF) << 8) | (p[offset + 1] & 0xFF)); //高16位
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /** 辅助方法:将32位整数转换为字节数组 */
|
|
||||||
// public static void putU32(byte[] p, int offset, int v) {
|
|
||||||
// p[offset] = (byte) (v >> 24);
|
|
||||||
// p[offset + 1] = (byte) (v >> 16);
|
|
||||||
// p[offset + 2] = (byte) (v >> 8);
|
|
||||||
// p[offset + 3] = (byte) v;
|
|
||||||
// }
|
|
||||||
/** 辅助方法:将32位整数(vlo=低16位, vhi=高16位)写入字节数组 */
|
|
||||||
public static void putU32(byte[] p, short offset, short vlo, short vhi) {
|
|
||||||
// 写高16位
|
|
||||||
p[offset] = (byte) ((vhi >> 8) & 0xFF);
|
|
||||||
p[offset + 1] = (byte) (vhi & 0xFF);
|
|
||||||
|
|
||||||
// 写低16位
|
|
||||||
p[offset + 2] = (byte) ((vlo >> 8) & 0xFF);
|
|
||||||
p[offset + 3] = (byte) (vlo & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// === 31/32 位运算 ===
|
|
||||||
|
|
||||||
// /** 31位加法 */
|
|
||||||
// public static int add31(int a, int b) {
|
|
||||||
// long sum = (long)a + b;
|
|
||||||
// return (int) ((sum & 0x7FFFFFFF) + (sum >> 31));
|
|
||||||
// }
|
|
||||||
/** 31位加法: (a+b) mod (2^31 - 1)
|
|
||||||
* 输入: a_lo=低16位, a_hi=高15位
|
|
||||||
* b_lo=低16位, b_hi=高15位
|
|
||||||
* 输出: out[0]=lo, out[1]=hi
|
|
||||||
*/
|
|
||||||
public static void add31(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /* len==2 */) {
|
|
||||||
// ---- 低16位相加 ----
|
|
||||||
short lo = (short)(a_lo + b_lo);
|
|
||||||
short carry = (short)(((lo & 0xFFFF) < (a_lo & 0xFFFF)) ? 1 : 0);
|
|
||||||
|
|
||||||
// ---- 高15位相加 + 进位 ----
|
|
||||||
short hi_raw = (short)((short)((a_hi & 0x7FFF) + (b_hi & 0x7FFF)) + carry);
|
|
||||||
|
|
||||||
// 提取第31位(hi_raw bit15)
|
|
||||||
short topbit = (short)((hi_raw >>> 15) & 1);
|
|
||||||
short hi = (short)(hi_raw & 0x7FFF); // 保留15位
|
|
||||||
|
|
||||||
// ---- 若第31位=1,再+1 ----
|
|
||||||
if (topbit == 1) {
|
|
||||||
short lo2 = (short)(lo + 1);
|
|
||||||
short c2 = (short)((lo2 == 0) ? 1 : 0); // lo溢出时进位
|
|
||||||
lo = lo2;
|
|
||||||
hi = (short)((hi + c2) & 0x7FFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
out[0] = lo;
|
|
||||||
out[1] = hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /** 31位旋转 */
|
|
||||||
// public static int rot31(int a, int k) {
|
|
||||||
// return ((a << k) | (a >>> (31 - k))) & 0x7FFFFFFF;
|
|
||||||
// }
|
|
||||||
/** 31位循环左移: (a <<< k) mod (2^31 -1)
|
|
||||||
* 输入: a_lo=低16位, a_hi=高15位
|
|
||||||
* 输出: out[0]=lo, out[1]=hi
|
|
||||||
*/
|
|
||||||
public static void rot31(short a_lo, short a_hi, short k, short[] out /* len==2 */) {
|
|
||||||
k = (short)(k % 31); // 限制在 0..30
|
|
||||||
if (k == 0) {
|
|
||||||
out[0] = a_lo;
|
|
||||||
out[1] = (short)(a_hi & 0x7FFF);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拆成 31 位数组 [bit0..bit30]
|
|
||||||
short[] bits = new short[31];
|
|
||||||
for (short i = 0; i < 16; i++) {
|
|
||||||
bits[i] = (short)((a_lo >>> i) & 1);
|
|
||||||
}
|
|
||||||
for (short i = 0; i < 15; i++) {
|
|
||||||
bits[16 + i] = (short)((a_hi >>> i) & 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 旋转
|
|
||||||
short[] resBits = new short[31];
|
|
||||||
for (short i = 0; i < 31; i++) {
|
|
||||||
short j = (short)((i + k) % 31);
|
|
||||||
resBits[j] = bits[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拼回 lo, hi
|
|
||||||
short lo = 0;
|
|
||||||
for (short i = 0; i < 16; i++) {
|
|
||||||
lo = (short)(lo | (resBits[i] << i));
|
|
||||||
}
|
|
||||||
short hi = 0;
|
|
||||||
for (short i = 0; i < 15; i++) {
|
|
||||||
hi = (short)(hi | (resBits[16 + i] << i));
|
|
||||||
}
|
|
||||||
|
|
||||||
out[0] = lo;
|
|
||||||
out[1] = hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /** 32位旋转 */
|
|
||||||
// public static int rot32(int a, int k) {
|
|
||||||
// return (a << k) | (a >>> (32 - k));
|
|
||||||
// }
|
|
||||||
/** 32位循环左移: (a<<<k) */
|
|
||||||
public static void rot32(short a_lo, short a_hi, short k, short[] out /*len==2*/) {
|
|
||||||
k = (short)(k & 31); // 限制 0..31
|
|
||||||
if (k == 0) {
|
|
||||||
out[0] = a_lo;
|
|
||||||
out[1] = a_hi;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
short lo, hi;
|
|
||||||
|
|
||||||
if (k < 16) {
|
|
||||||
// 左移 k
|
|
||||||
lo = (short)(a_lo << k);
|
|
||||||
hi = (short)(a_hi << k);
|
|
||||||
|
|
||||||
// 把溢出部分拼接
|
|
||||||
lo |= (short)((a_hi & 0xFFFF) >>> (16 - k));
|
|
||||||
hi |= (short)((a_lo & 0xFFFF) >>> (16 - k));
|
|
||||||
} else {
|
|
||||||
short s = (short)(k - 16);
|
|
||||||
lo = (short)(a_hi << s);
|
|
||||||
hi = (short)(a_lo << s);
|
|
||||||
|
|
||||||
lo |= (short)((a_lo & 0xFFFF) >>> (16 - s));
|
|
||||||
hi |= (short)((a_hi & 0xFFFF) >>> (16 - s));
|
|
||||||
}
|
|
||||||
|
|
||||||
out[0] = lo;
|
|
||||||
out[1] = hi;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * L1函数
|
|
||||||
// */
|
|
||||||
// public static int L1(int x) {
|
|
||||||
// return x ^ rot32(x, 2) ^ rot32(x, 10) ^ rot32(x, 18) ^ rot32(x, 24);
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* L1函数: x ^ (x<<<2) ^ (x<<<10) ^ (x<<<18) ^ (x<<<24)
|
|
||||||
* 输入: x_lo, x_hi
|
|
||||||
* 输出: out[0]=lo, out[1]=hi
|
|
||||||
*/
|
|
||||||
public static void L1(short x_lo, short x_hi, short[] out /*len==2*/) {
|
|
||||||
short[] t = new short[2];
|
|
||||||
short[] acc = new short[2];
|
|
||||||
|
|
||||||
// acc = x
|
|
||||||
acc[0] = x_lo;
|
|
||||||
acc[1] = x_hi;
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 2)
|
|
||||||
rot32(x_lo, x_hi, (short)2, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 10)
|
|
||||||
rot32(x_lo, x_hi, (short)10, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 18)
|
|
||||||
rot32(x_lo, x_hi, (short)18, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 24)
|
|
||||||
rot32(x_lo, x_hi, (short)24, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
out[0] = acc[0];
|
|
||||||
out[1] = acc[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * L2函数
|
|
||||||
// */
|
|
||||||
// public static int L2(int x) {
|
|
||||||
// return x ^ rot32(x, 8) ^ rot32(x, 14) ^ rot32(x, 22) ^ rot32(x, 30);
|
|
||||||
// }
|
|
||||||
/**
|
|
||||||
* L2函数: x ^ (x<<<8) ^ (x<<<14) ^ (x<<<22) ^ (x<<<30)
|
|
||||||
* 输入: x_lo, x_hi
|
|
||||||
* 输出: out[0]=lo, out[1]=hi
|
|
||||||
*/
|
|
||||||
public static void L2(short x_lo, short x_hi, short[] out /*len==2*/) {
|
|
||||||
short[] t = new short[2];
|
|
||||||
short[] acc = new short[2];
|
|
||||||
|
|
||||||
// acc = x
|
|
||||||
acc[0] = x_lo;
|
|
||||||
acc[1] = x_hi;
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 8)
|
|
||||||
rot32(x_lo, x_hi, (short)8, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 14)
|
|
||||||
rot32(x_lo, x_hi, (short)14, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 22)
|
|
||||||
rot32(x_lo, x_hi, (short)22, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
// acc ^= rot32(x, 30)
|
|
||||||
rot32(x_lo, x_hi, (short)30, t);
|
|
||||||
acc[0] ^= t[0];
|
|
||||||
acc[1] ^= t[1];
|
|
||||||
|
|
||||||
out[0] = acc[0];
|
|
||||||
out[1] = acc[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /** 创建31位无符号整数 */
|
|
||||||
// public static int makeU31(int a, int b, int c, int d) {
|
|
||||||
// return (((a & 0xFF) << 23) |
|
|
||||||
// ((b & 0xFF) << 16) |
|
|
||||||
// ((c & 0xFF) << 8) |
|
|
||||||
// (d & 0xFF)) & 0x7FFFFFFF;
|
|
||||||
// }
|
|
||||||
/** 创建31位无符号整数,结果放到 out[0]=lo, out[1]=hi(15位) */
|
|
||||||
public static void makeU31(short a, short b, short c, short d, short[] out /*len==2*/) {
|
|
||||||
// 四个字节
|
|
||||||
short b0 = (short)(a & 0xFF); // 最高字节
|
|
||||||
short b1 = (short)(b & 0xFF);
|
|
||||||
short b2 = (short)(c & 0xFF);
|
|
||||||
short b3 = (short)(d & 0xFF); // 最低字节
|
|
||||||
|
|
||||||
// 拼成 32 位: b0<<24 | b1<<16 | b2<<8 | b3
|
|
||||||
// lo = 低16位
|
|
||||||
out[0] = (short)((b2 << 8) | b3);
|
|
||||||
|
|
||||||
// hi = 高15位(丢弃 bit31)
|
|
||||||
out[1] = (short)(((b0 & 0x7F) << 8) | b1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// /** 创建32位无符号整数 */
|
|
||||||
// public static int makeU32(int a, int b, int c, int d) {
|
|
||||||
// return ((a & 0xFF) << 24) |
|
|
||||||
// ((b & 0xFF) << 16) |
|
|
||||||
// ((c & 0xFF) << 8) |
|
|
||||||
// (d & 0xFF);
|
|
||||||
// }
|
|
||||||
/** 创建32位无符号整数,结果放到 out[0]=lo, out[1]=hi */
|
|
||||||
public static void makeU32(short a, short b, short c, short d, short[] out /*len==2*/) {
|
|
||||||
// 四个字节
|
|
||||||
short b0 = (short)(a & 0xFF); // 最高字节
|
|
||||||
short b1 = (short)(b & 0xFF);
|
|
||||||
short b2 = (short)(c & 0xFF);
|
|
||||||
short b3 = (short)(d & 0xFF); // 最低字节
|
|
||||||
|
|
||||||
// lo = 低16位
|
|
||||||
out[0] = (short)((b2 << 8) | b3);
|
|
||||||
|
|
||||||
// hi = 高16位
|
|
||||||
out[1] = (short)((b0 << 8) | b1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 提取IV */
|
|
||||||
public static void extractIv(byte[] input25Byte, byte[] output23Byte) {
|
|
||||||
if (input25Byte == null || output23Byte == null) return;
|
|
||||||
|
|
||||||
// 复制前17字节
|
|
||||||
Util.arrayCopyNonAtomic(input25Byte, (short)0, output23Byte, (short)0, (short)17);
|
|
||||||
|
|
||||||
|
|
||||||
// 处理剩余8字节
|
|
||||||
byte[] src = new byte[8];
|
|
||||||
for (short i = 0; i < 8; i++) {
|
|
||||||
src[i] = (byte) (input25Byte[17 + i] & 0x3F);
|
|
||||||
}
|
|
||||||
|
|
||||||
output23Byte[17] = (byte) ((src[0] << 2) | (src[1] >>> 4));
|
|
||||||
output23Byte[18] = (byte) (((src[1] & 0x0F) << 4) | (src[2] >>> 2));
|
|
||||||
output23Byte[19] = (byte) (((src[2] & 0x03) << 6) | src[3]);
|
|
||||||
output23Byte[20] = (byte) ((src[4] << 2) | (src[5] >>> 4));
|
|
||||||
output23Byte[21] = (byte) (((src[5] & 0x0F) << 4) | (src[6] >>> 2));
|
|
||||||
output23Byte[22] = (byte) (((src[6] & 0x03) << 6) | src[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 打印/*十六进制(调试用,TODO 生产/JC 环境可移除) *//*
|
|
||||||
public static void printHex(String label, byte[] data, int len) {
|
|
||||||
System.out.print(label + ": ");
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
System.out.printf("%02x ", data[i] & 0xFF);
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
135
README.md
135
README.md
@@ -11,6 +11,141 @@ sudo apt-get install scons
|
|||||||
sudo apt-get install build-essential
|
sudo apt-get install build-essential
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
0909 位置加密applet调用说明
|
||||||
|
|
||||||
|
1. E2 密钥存储接口
|
||||||
|
说明:
|
||||||
|
密钥长度为16或32B,加上密钥信息(4B)最多36B,按每个密钥40B存储在flash中。目前共分配了120B空间。(可存3个密钥)
|
||||||
|
遇相同(算法类型, 密钥ID, 密钥版本)密钥,覆盖存储;
|
||||||
|
新密钥存储在新空间;
|
||||||
|
密钥长度超长会报错,空间满会报错。
|
||||||
|
返回A1+5字节密文+9000
|
||||||
|
|
||||||
|
样例1
|
||||||
|
存储一个长度16,算法A1,id01,version02的Key[1122..FF00]
|
||||||
|
80 E2 00 01 14
|
||||||
|
13 A1 01 02 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00
|
||||||
|
|
||||||
|
/send 80E200011413A10102112233445566778899AABBCCDDEEFF00
|
||||||
|
->
|
||||||
|
90 00
|
||||||
|
|
||||||
|
|
||||||
|
样例2
|
||||||
|
存储一个长度32,算法A2,id02,version02的Key[0102..1F20]
|
||||||
|
80 E2 00 02 24
|
||||||
|
23 A2 02 02
|
||||||
|
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
|
||||||
|
11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
|
||||||
|
|
||||||
|
/send 80E200022423A202020102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
|
||||||
|
->
|
||||||
|
90 00
|
||||||
|
|
||||||
|
|
||||||
|
样例3
|
||||||
|
存储一个长度FF,算法A2,id02,version02的Key[0102..1F20]
|
||||||
|
80 E2 00 02 24
|
||||||
|
FF A2 02 02
|
||||||
|
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
|
||||||
|
11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
|
||||||
|
/send 80E2000224FFA202020102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
|
||||||
|
->
|
||||||
|
69 84 (超长 FF)
|
||||||
|
|
||||||
|
|
||||||
|
样例4
|
||||||
|
存储一个长度32,算法A2,id01,version02的Key[0102..1F20]
|
||||||
|
80 E2 00 02 24
|
||||||
|
23 A2 01 02
|
||||||
|
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
|
||||||
|
11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
|
||||||
|
|
||||||
|
/send 80E200022423A202020102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20
|
||||||
|
->
|
||||||
|
90 00
|
||||||
|
|
||||||
|
样例4
|
||||||
|
存储一个长度16,算法A3,id02,version02的Key[0102..0F10],执行后空间满 120B
|
||||||
|
80 E2 00 02 14
|
||||||
|
13 A3 02 02
|
||||||
|
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
|
||||||
|
|
||||||
|
/send 80E200021413A302020102030405060708090A0B0C0D0E0F10
|
||||||
|
->
|
||||||
|
90 00
|
||||||
|
|
||||||
|
样例5
|
||||||
|
存储一个长度16,算法A3,id09,version02的Key[0102..0F10]
|
||||||
|
80 E2 00 02 14
|
||||||
|
13 A3 09 02
|
||||||
|
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
|
||||||
|
|
||||||
|
/send 80E200021413A309020102030405060708090A0B0C0D0E0F10
|
||||||
|
->
|
||||||
|
6A 84 空间满
|
||||||
|
|
||||||
|
|
||||||
|
样例6
|
||||||
|
存储一个长度16,算法A2,id02,version02的Key[0102..0F10](覆盖样例3空间)
|
||||||
|
80 E2 00 02 14
|
||||||
|
13 A2 02 02
|
||||||
|
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
|
||||||
|
|
||||||
|
/send 80E200021413A202020102030405060708090A0B0C0D0E0F10
|
||||||
|
->
|
||||||
|
90 00
|
||||||
|
|
||||||
|
--------
|
||||||
|
|
||||||
|
|
||||||
|
2. CA 位置加密
|
||||||
|
数据为1字节随机数,6字节STMSI,5字节数据
|
||||||
|
目前随机数和STMSI未使用,此接口用固定Key IV,对数据进行Zuc256加密,返回加密后数据。
|
||||||
|
|
||||||
|
// Key: 32字节
|
||||||
|
private static final byte[] KEY32 = {
|
||||||
|
(byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,(byte)0x37,
|
||||||
|
(byte)0x38,(byte)0x39,(byte)0x61,(byte)0x62,(byte)0x63,(byte)0x64,(byte)0x65,(byte)0x66,
|
||||||
|
(byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,(byte)0x37,
|
||||||
|
(byte)0x38,(byte)0x39,(byte)0x61,(byte)0x62,(byte)0x63,(byte)0x64,(byte)0x65,(byte)0x66
|
||||||
|
};
|
||||||
|
// IV: 25字节
|
||||||
|
private static final byte[] IV25 = {
|
||||||
|
(byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,(byte)0x37,
|
||||||
|
(byte)0x38,(byte)0x39,(byte)0x61,(byte)0x62,(byte)0x63,(byte)0x64,(byte)0x65,(byte)0x66,
|
||||||
|
(byte)0x67,(byte)0x30,(byte)0x31,(byte)0x32,(byte)0x33,(byte)0x34,(byte)0x35,(byte)0x36,
|
||||||
|
(byte)0x37
|
||||||
|
};
|
||||||
|
|
||||||
|
样例1
|
||||||
|
80 CA 00 00 0E
|
||||||
|
A1 0C 00 11 22 33 44 55 66 AA BB CC DD EE
|
||||||
|
|
||||||
|
/send 80CA00000EA10C00112233445566AABBCCDDEE
|
||||||
|
|
||||||
|
->
|
||||||
|
A1 06 01 9C 00 B3 15 05 90 00
|
||||||
|
|
||||||
|
|
||||||
|
样例2
|
||||||
|
80 CA 00 00 0E
|
||||||
|
A1 0C 00 11 22 33 44 55 66 FF 00 FF 00 FF
|
||||||
|
|
||||||
|
/send 80CA00000EA10C00112233445566FF00FF00FF
|
||||||
|
|
||||||
|
->
|
||||||
|
A1 06 01 C9 BB 80 C8 14 90 00
|
||||||
|
|
||||||
|
样例3
|
||||||
|
80 CA 00 00 0E
|
||||||
|
A1 0C 00 11 22 33 44 55 66 31 32 33 34 35
|
||||||
|
|
||||||
|
/send 80CA00000EA10C001122334455663132333435
|
||||||
|
|
||||||
|
->
|
||||||
|
A1 06 01 07 89 4C FC DE 90 00
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
1638
Src/com/cscn/Method.java
Normal file
1638
Src/com/cscn/Method.java
Normal file
File diff suppressed because it is too large
Load Diff
22
Src/com/cscn/RandomGenerator.java
Normal file
22
Src/com/cscn/RandomGenerator.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//package com.cscn;
|
||||||
|
//
|
||||||
|
//import javacard.security.RandomData;
|
||||||
|
//
|
||||||
|
//public class RandomGenerator {
|
||||||
|
// private final RandomData random;
|
||||||
|
//
|
||||||
|
// //构造函数
|
||||||
|
// public RandomGenerator()
|
||||||
|
// {
|
||||||
|
// //类当中有getInstance的都要先调用这个函数获取对象实例才能使用其他方法,不然6F00
|
||||||
|
// random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //产生length长度的随机数并返回
|
||||||
|
// public final byte[] GenrateSecureRand(short length, byte[] out)
|
||||||
|
// {
|
||||||
|
// //生成4bit的随机数
|
||||||
|
// random.generateData(out, (short)0, (short)length);
|
||||||
|
// return out;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
96
Src/com/cscn/XwSecurity.java
Normal file
96
Src/com/cscn/XwSecurity.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package com.cscn;
|
||||||
|
|
||||||
|
import javacard.framework.APDU;
|
||||||
|
import javacard.framework.Applet;
|
||||||
|
import javacard.framework.ISO7816;
|
||||||
|
import javacard.framework.ISOException;
|
||||||
|
//import javacard.security.RandomData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuww
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XwSecurity extends Applet {
|
||||||
|
//todo test
|
||||||
|
// public static final byte INS_PROCESS_DATA_TEST = (byte)0xE3;
|
||||||
|
|
||||||
|
public static final byte INS_LOCATION_ENCRYPT = (byte)0xCA;
|
||||||
|
|
||||||
|
public static final byte INS_STORE_KEY = (byte)0xE2;
|
||||||
|
|
||||||
|
// public static final byte INS_INITIAL_UPDATE = (byte)0x50;
|
||||||
|
//
|
||||||
|
// public static final byte INS_EXTERNAL_AUTH = (byte)0x82;
|
||||||
|
|
||||||
|
private Method method;
|
||||||
|
|
||||||
|
byte[] key_store_byte;
|
||||||
|
|
||||||
|
public XwSecurity(byte[] bArray, short bOffset, byte bLength) {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
method = new Method();//rng); //todo new?
|
||||||
|
// key store -> flash
|
||||||
|
key_store_byte = new byte[120];
|
||||||
|
register(bArray, (short)(bOffset + 1), bArray[bOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void install(byte[] bArray, short bOffset, byte bLength)
|
||||||
|
{
|
||||||
|
//todo new?
|
||||||
|
// GP-compliant JavaCard applet registration
|
||||||
|
new XwSecurity(bArray, bOffset, bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(APDU apdu)
|
||||||
|
{
|
||||||
|
// Good practice: Return 9000 on SELECT
|
||||||
|
if(selectingApplet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] buf = apdu.getBuffer();
|
||||||
|
short off = ISO7816.OFFSET_CDATA;
|
||||||
|
short len = apdu.setIncomingAndReceive();
|
||||||
|
|
||||||
|
switch (buf[ISO7816.OFFSET_INS])
|
||||||
|
{
|
||||||
|
// case INS_INITIAL_UPDATE:
|
||||||
|
// SecureChannel sc = GPSystem.getSecureChannel();
|
||||||
|
// sc.processSecurity(apdu);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case INS_EXTERNAL_AUTH:
|
||||||
|
// sc = GPSystem.getSecureChannel();
|
||||||
|
// sc.processSecurity(apdu);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
|
||||||
|
// //todo test
|
||||||
|
// case INS_PROCESS_DATA_TEST:
|
||||||
|
// method.testZuc256(apdu);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
|
||||||
|
case INS_LOCATION_ENCRYPT:
|
||||||
|
len = method.locationEncryptZuc(buf, off, len, key_store_byte);
|
||||||
|
apdu.setOutgoingAndSend(off, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INS_STORE_KEY:
|
||||||
|
len = method.updateKey(buf, off, len, key_store_byte);
|
||||||
|
apdu.setOutgoingAndSend(off, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// good practice: If you don't know the INStruction, say so:
|
||||||
|
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
96
Src/com/cscn/Zuc256Tables.java
Normal file
96
Src/com/cscn/Zuc256Tables.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package com.cscn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常量表:S0/S1 与 ZUC256_D。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class Zuc256Tables {
|
||||||
|
|
||||||
|
private Zuc256Tables() {}
|
||||||
|
|
||||||
|
// S盒:S0, S1
|
||||||
|
public static final short[] S0 = {
|
||||||
|
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
|
||||||
|
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
|
||||||
|
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
|
||||||
|
0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
|
||||||
|
0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
|
||||||
|
0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
|
||||||
|
0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
|
||||||
|
0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
|
||||||
|
0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
|
||||||
|
0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
|
||||||
|
0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
|
||||||
|
0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
|
||||||
|
0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
|
||||||
|
0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
|
||||||
|
0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
|
||||||
|
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final short[] S1 = {
|
||||||
|
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
|
||||||
|
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
|
||||||
|
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
|
||||||
|
0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
|
||||||
|
0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
|
||||||
|
0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
|
||||||
|
0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
|
||||||
|
0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
|
||||||
|
0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
|
||||||
|
0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
|
||||||
|
0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
|
||||||
|
0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
|
||||||
|
0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
|
||||||
|
0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
|
||||||
|
0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
|
||||||
|
0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2
|
||||||
|
};
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 常量数组 D(16bit short二维数组适配)
|
||||||
|
// */
|
||||||
|
// public static final short[][] ZUC256_D = {
|
||||||
|
// {0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
// {0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
// {0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
// {0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30}
|
||||||
|
// };
|
||||||
|
public static final short D_COLS = 16;
|
||||||
|
/**
|
||||||
|
* 常量数组 D(16bit short二维数组适配)
|
||||||
|
*/
|
||||||
|
public static final short[] ZUC256_D_FLAT = {
|
||||||
|
// row 0
|
||||||
|
0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30,
|
||||||
|
|
||||||
|
// row 1
|
||||||
|
0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30,
|
||||||
|
|
||||||
|
// row 2
|
||||||
|
0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30,
|
||||||
|
|
||||||
|
// row 3
|
||||||
|
0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** 读取 D[row][col],返回无符号值 0..255 */
|
||||||
|
public static short getD(short row, short col) {
|
||||||
|
// idx = row * 16 + col
|
||||||
|
short idx = (short)(row * D_COLS + col);
|
||||||
|
return (short)(ZUC256_D_FLAT[idx] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取一行 (返回一段16个short) */
|
||||||
|
public static void getDRow(short row, short[] out, short outOff) {
|
||||||
|
short base = (short)(row * D_COLS);
|
||||||
|
for (short i = 0; i < D_COLS; i++) {
|
||||||
|
out[(short)(outOff + i)] = ZUC256_D_FLAT[(short)(base + i)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
build_tools/Bat/Delivery/cscn.cap
Normal file
BIN
build_tools/Bat/Delivery/cscn.cap
Normal file
Binary file not shown.
BIN
build_tools/Bat/Delivery/cscn.exp
Normal file
BIN
build_tools/Bat/Delivery/cscn.exp
Normal file
Binary file not shown.
@@ -47,7 +47,7 @@ ECHO **********************************************
|
|||||||
ECHO *** Convert Java Card Assembly File ***
|
ECHO *** Convert Java Card Assembly File ***
|
||||||
ECHO **********************************************
|
ECHO **********************************************
|
||||||
|
|
||||||
CALL converter -nowarn -i -classdir .\bin -exportpath %EXPORT_DIR% -out EXP CAP -applet 0xA0:0x00:0x00:0x03:0x00:0x73:0x74:0x61:0x72:0x2E:0x61:0x70:0x70 com.cscn.XwSecurity com.cscn 0xA0:0x00:0x00:0x03:0x00:0x73:0x74:0x61:0x72:0x2E:0x70:0x6B:0x67 1.0
|
CALL converter -verbose -nowarn -i -classdir .\bin -exportpath %EXPORT_DIR% -out EXP CAP -applet 0xA0:0x00:0x00:0x03:0x00:0x73:0x74:0x61:0x72:0x2E:0x61:0x70:0x70 com.cscn.XwSecurity com.cscn 0xA0:0x00:0x00:0x03:0x00:0x73:0x74:0x61:0x72:0x2E:0x70:0x6B:0x67 1.0
|
||||||
|
|
||||||
ECHO **********************************************
|
ECHO **********************************************
|
||||||
ECHO *** Copy Exp and Cap File ***
|
ECHO *** Copy Exp and Cap File ***
|
||||||
1586
build_tools/Project/Src/Method.java
Normal file
1586
build_tools/Project/Src/Method.java
Normal file
File diff suppressed because it is too large
Load Diff
99
build_tools/Project/Src/XwSecurity.java
Normal file
99
build_tools/Project/Src/XwSecurity.java
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package com.cscn;
|
||||||
|
|
||||||
|
import javacard.framework.APDU;
|
||||||
|
import javacard.framework.Applet;
|
||||||
|
import javacard.framework.ISO7816;
|
||||||
|
import javacard.framework.ISOException;
|
||||||
|
import org.globalplatform.GPSystem;
|
||||||
|
import org.globalplatform.SecureChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuww
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XwSecurity extends Applet {
|
||||||
|
|
||||||
|
//todo test
|
||||||
|
public static final byte INS_PROCESS_DATA_TEST = (byte)0xE3;
|
||||||
|
|
||||||
|
public static final byte INS_LOCATION_ENCRYPT = (byte)0xCA;
|
||||||
|
|
||||||
|
public static final byte INS_STORE_KEY = (byte)0xE2;
|
||||||
|
|
||||||
|
// public static final byte INS_INITIAL_UPDATE = (byte)0x50;
|
||||||
|
//
|
||||||
|
// public static final byte INS_EXTERNAL_AUTH = (byte)0x82;
|
||||||
|
|
||||||
|
private Method method;
|
||||||
|
|
||||||
|
byte[] key_store_byte;
|
||||||
|
|
||||||
|
public XwSecurity(byte[] bArray, short bOffset, byte bLength) {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
method = new Method(); //todo new?
|
||||||
|
// key store -> flash
|
||||||
|
key_store_byte = new byte[120];
|
||||||
|
|
||||||
|
register(bArray, (short)(bOffset + 1), bArray[bOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void install(byte[] bArray, short bOffset, byte bLength)
|
||||||
|
{
|
||||||
|
//todo new?
|
||||||
|
// GP-compliant JavaCard applet registration
|
||||||
|
new XwSecurity(bArray, bOffset, bLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(APDU apdu)
|
||||||
|
{
|
||||||
|
// Good practice: Return 9000 on SELECT
|
||||||
|
if(selectingApplet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(method == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] buf = apdu.getBuffer();
|
||||||
|
short off = ISO7816.OFFSET_CDATA;
|
||||||
|
short len = apdu.setIncomingAndReceive();
|
||||||
|
|
||||||
|
switch (buf[ISO7816.OFFSET_INS])
|
||||||
|
{
|
||||||
|
// case INS_INITIAL_UPDATE:
|
||||||
|
// SecureChannel sc = GPSystem.getSecureChannel();
|
||||||
|
// sc.processSecurity(apdu);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case INS_EXTERNAL_AUTH:
|
||||||
|
// sc = GPSystem.getSecureChannel();
|
||||||
|
// sc.processSecurity(apdu);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
|
||||||
|
//todo test
|
||||||
|
case INS_PROCESS_DATA_TEST:
|
||||||
|
method.testZuc256(apdu);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case INS_LOCATION_ENCRYPT:
|
||||||
|
len = method.locationEncryptZuc(buf, off, len, key_store_byte);
|
||||||
|
apdu.setOutgoingAndSend(off, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INS_STORE_KEY:
|
||||||
|
len = method.updateKey(buf, off, len, key_store_byte);
|
||||||
|
apdu.setOutgoingAndSend(off, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// good practice: If you don't know the INStruction, say so:
|
||||||
|
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
595
build_tools/Project/Src/Zuc256Core.java
Normal file
595
build_tools/Project/Src/Zuc256Core.java
Normal file
@@ -0,0 +1,595 @@
|
|||||||
|
//package com.cscn;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//import javacard.framework.JCSystem;
|
||||||
|
//
|
||||||
|
//import static com.cscn.Zuc256Util.L1;
|
||||||
|
//import static com.cscn.Zuc256Util.L2;
|
||||||
|
//import static com.cscn.Zuc256Util.add31;
|
||||||
|
//import static com.cscn.Zuc256Util.add32;
|
||||||
|
//import static com.cscn.Zuc256Util.add64;
|
||||||
|
//import static com.cscn.Zuc256Util.and64_7FFFFFFF_to32;
|
||||||
|
//import static com.cscn.Zuc256Util.create_64b_from_32b;
|
||||||
|
//import static com.cscn.Zuc256Util.makeU31;
|
||||||
|
//import static com.cscn.Zuc256Util.makeU32;
|
||||||
|
//import static com.cscn.Zuc256Util.rot31;
|
||||||
|
//import static com.cscn.Zuc256Util.shr32u1;
|
||||||
|
//import static com.cscn.Zuc256Util.shr64u_31;
|
||||||
|
//import static com.cscn.Zuc256Util.xor32;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * ZUC-256 核心:状态初始化、密钥字生成、密钥流生成。
|
||||||
|
// */
|
||||||
|
//public class Zuc256Core {
|
||||||
|
//
|
||||||
|
// private Zuc256Core() {}
|
||||||
|
//
|
||||||
|
// /** 初始化状态(Key + IV) */
|
||||||
|
// public static void initState(Zuc256State state, byte[] key32, byte[] iv) {
|
||||||
|
// zuc256SetMacKey(state, key32, iv, (short)0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /** 生成单个密钥字 */
|
||||||
|
// public static void zuc256GenerateKeyword(Zuc256State state, short[] out) {
|
||||||
|
//// int[] LFSR = state.LFSR;
|
||||||
|
//// int R1 = state.R1;
|
||||||
|
//// int R2 = state.R2;
|
||||||
|
//// int X0, X1, X2, X3;
|
||||||
|
//// int W1, W2, U, V;
|
||||||
|
//// int Z;
|
||||||
|
//
|
||||||
|
// short[] LFSR_hi = state.LFSR_hi;
|
||||||
|
// short[] LFSR_lo = state.LFSR_lo;
|
||||||
|
//
|
||||||
|
// // 工作寄存器(32位值的临时 out32 缓冲,全用short[2])[lo, hi]
|
||||||
|
// short[] X0 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] X1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] X2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] X3 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// short[] R1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] R2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] W1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] W2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] U = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] V = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] Z = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] TMP0 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] TMP1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] TMP2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // 载入 R1,R2
|
||||||
|
// R1[0] = state.R1_lo;
|
||||||
|
// R1[1] = state.R1_hi;
|
||||||
|
// R2[0] = state.R2_lo;
|
||||||
|
// R2[1] = state.R2_hi;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // BitReconstruction4
|
||||||
|
// short c15 = (short)((LFSR_lo[15] & (short)0x8000) >>> 15); // 左移产生的进位
|
||||||
|
// X0[1] = (short)(((LFSR_hi[15] & (short)0x7FFF) << 1) | (short)(c15 & 0x0001)); // hi
|
||||||
|
// X0[0] = LFSR_lo[14]; // lo
|
||||||
|
//
|
||||||
|
// // X1 = ((L11 & 0xFFFF) << 16) | (L9 >>> 15)
|
||||||
|
// X1[1] = LFSR_lo[11];
|
||||||
|
// X1[0] = (short)((((LFSR_lo[9] & (short)0x8000) >>> 15) & 0X0001) | (LFSR_hi[9] << 1));
|
||||||
|
//
|
||||||
|
// // X2 = ((L7 & 0xFFFF) << 16) | (L5 >>> 15)
|
||||||
|
// X2[1] = LFSR_lo[7];
|
||||||
|
// X2[0] = (short)((((LFSR_lo[5] & (short)0x8000) >>> 15) & 0X0001) | (LFSR_hi[5] << 1));
|
||||||
|
//
|
||||||
|
// // X3 = ((L2 & 0xFFFF) << 16) | (L0 >>> 15)
|
||||||
|
// X3[1] = LFSR_lo[2];
|
||||||
|
// X3[0] = (short)((((LFSR_lo[0] & (short)0x8000) >>> 15) & 0X0001) | (LFSR_hi[0] << 1));
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // ---- 输入:X0,X1,X2,X3,R1,R2 均为 short[2]; 输出:Z,W1,W2,U,V ----
|
||||||
|
//
|
||||||
|
// // Z = X3 ^ ((X0 ^ R1) + R2)
|
||||||
|
// xor32(X0[0], X0[1], R1[0], R1[1], TMP0); // TMP0 = X0 ^ R1
|
||||||
|
// add32(TMP0[0], TMP0[1], R2[0], R2[1], TMP1); // TMP1 = TMP0 + R2
|
||||||
|
// xor32(X3[0], X3[1], TMP1[0], TMP1[1], Z); // Z = X3 ^ TMP1
|
||||||
|
//
|
||||||
|
// // F_(X1, X2)
|
||||||
|
// // W1 = R1 + X1
|
||||||
|
// add32(R1[0], R1[1], X1[0], X1[1], W1);
|
||||||
|
//
|
||||||
|
// // W2 = R2 ^ X2
|
||||||
|
// xor32(R2[0], R2[1], X2[0], X2[1], W2);
|
||||||
|
//
|
||||||
|
// // U = L1((W1 << 16) | (W2 >>> 16))
|
||||||
|
// // (W1<<16): lo=0, hi=W1_lo
|
||||||
|
// // (W2>>>16): lo=W2_hi, hi=0
|
||||||
|
// // OR 结果: lo=W2_hi, hi=W1_lo
|
||||||
|
// L1(W2[1], W1[0], U);
|
||||||
|
//
|
||||||
|
// // V = L2((W2 << 16) | (W1 >>> 16))
|
||||||
|
// // (W2<<16): lo=0, hi=W2_lo
|
||||||
|
// // (W1>>>16): lo=W1_hi, hi=0
|
||||||
|
// // OR 结果: lo=W1_hi, hi=W2_lo
|
||||||
|
// L2(W1[1], W2[0], V);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[(U >>> 16) & 0xFF],
|
||||||
|
//// Zuc256Tables.S0[(U >>> 8) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[U & 0xFF]);
|
||||||
|
// makeU32(
|
||||||
|
// (short)(Zuc256Tables.S0[((U[1] >>> 8) & 0xFF)] & 0xFF), // (U >>> 24) & 0xFF
|
||||||
|
// (short)(Zuc256Tables.S1[(U[1] & 0xFF)] & 0xFF), // (U >>> 16) & 0xFF
|
||||||
|
// (short)(Zuc256Tables.S0[((U[0] >>> 8) & 0xFF)] & 0xFF), // (U >>> 8) & 0xFF
|
||||||
|
// (short)(Zuc256Tables.S1[(U[0] & 0xFF)] & 0xFF), // (U >>> 0) & 0xFF
|
||||||
|
// R1);
|
||||||
|
//
|
||||||
|
//// R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[(V >>> 16) & 0xFF],
|
||||||
|
//// Zuc256Tables.S0[(V >>> 8) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[V & 0xFF]);
|
||||||
|
// makeU32(
|
||||||
|
// (short)(Zuc256Tables.S0[((V[1] >>> 8) & 0xFF)] & 0xFF), // (V >>> 24) & 0xFF
|
||||||
|
// (short)(Zuc256Tables.S1[(V[1] & 0xFF)] & 0xFF), // (V >>> 16) & 0xFF
|
||||||
|
// (short)(Zuc256Tables.S0[((V[0] >>> 8) & 0xFF)] & 0xFF), // (V >>> 8) & 0xFF
|
||||||
|
// (short)(Zuc256Tables.S1[(V[0] & 0xFF)] & 0xFF), // (V >>> 0) & 0xFF
|
||||||
|
// R2);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// // LFSRWithWorkMode
|
||||||
|
//// long a = LFSR[0];
|
||||||
|
//// a += (long)LFSR[0] << 8;
|
||||||
|
//// a += (long)LFSR[4] << 20;
|
||||||
|
//// a += (long)LFSR[10] << 21;
|
||||||
|
//// a += (long)LFSR[13] << 17;
|
||||||
|
//// a += (long)LFSR[15] << 15;
|
||||||
|
// // ---- 先准备累加器 A (64位) ----
|
||||||
|
// short[] A = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); // 64位累加器,初始全0
|
||||||
|
// A[0] = 0; A[1] = 0; A[2] = 0; A[3] = 0;
|
||||||
|
//
|
||||||
|
// // 临时缓冲
|
||||||
|
// short[] tmp32 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);; // 保存一个32位数 (lo,hi)
|
||||||
|
// short[] tmp64 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);; // 保存移位后的64位数
|
||||||
|
//
|
||||||
|
// // a = LFSR[0]
|
||||||
|
// tmp32[0] = state.LFSR_lo[0];
|
||||||
|
// tmp32[1] = state.LFSR_hi[0];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)0);
|
||||||
|
// add64(A, tmp64);
|
||||||
|
//
|
||||||
|
// // a += (LFSR[0] << 8)
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)8);
|
||||||
|
// add64(A, tmp64);
|
||||||
|
//
|
||||||
|
// // a += (LFSR[4] << 20)
|
||||||
|
// tmp32[0] = state.LFSR_lo[4];
|
||||||
|
// tmp32[1] = state.LFSR_hi[4];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)20);
|
||||||
|
// add64(A, tmp64);
|
||||||
|
//
|
||||||
|
// // a += (LFSR[10] << 21)
|
||||||
|
// tmp32[0] = state.LFSR_lo[10];
|
||||||
|
// tmp32[1] = state.LFSR_hi[10];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)21);
|
||||||
|
// add64(A, tmp64);
|
||||||
|
//
|
||||||
|
// // a += (LFSR[13] << 17)
|
||||||
|
// tmp32[0] = state.LFSR_lo[13];
|
||||||
|
// tmp32[1] = state.LFSR_hi[13];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)17);
|
||||||
|
// add64(A, tmp64);
|
||||||
|
//
|
||||||
|
// // a += (LFSR[15] << 15)
|
||||||
|
// tmp32[0] = state.LFSR_lo[15];
|
||||||
|
// tmp32[1] = state.LFSR_hi[15];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)15);
|
||||||
|
// add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a = (a & 0x7FFFFFFF) + (a >>> 31);
|
||||||
|
// // ---- 第一次折叠:a = (a & 0x7FFFFFFF) + (a >>> 31) ----
|
||||||
|
// short[] low31 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] r31 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// and64_7FFFFFFF_to32(A, low31); // low31 = A & 0x7FFFFFFF
|
||||||
|
// shr64u_31(A, r31); // r31 = A >>> 31
|
||||||
|
//
|
||||||
|
// A[0]=0; A[1]=0; A[2]=0; A[3]=0;
|
||||||
|
// add64(A, low31);
|
||||||
|
// add64(A, r31);
|
||||||
|
//// int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
|
||||||
|
// // ---- 第二次折叠,得到 v(32位)----
|
||||||
|
// short[] low31b = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] r31b = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] v64 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// and64_7FFFFFFF_to32(A, low31b);
|
||||||
|
// shr64u_31(A, r31b);
|
||||||
|
//
|
||||||
|
// v64[0]=0; v64[1]=0; v64[2]=0; v64[3]=0;
|
||||||
|
// add64(v64, low31b);
|
||||||
|
// add64(v64, r31b);
|
||||||
|
//
|
||||||
|
// // v = 32位,取 v64 的低两段
|
||||||
|
// short v_lo = v64[0];
|
||||||
|
// short v_hi = (short)(v64[1] & 0x7FFF); // 只保留31位
|
||||||
|
//
|
||||||
|
//// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||||
|
// // LFSR_lo 向左移
|
||||||
|
// for (short i = 0; i < (short)15; i++) {
|
||||||
|
// state.LFSR_lo[i] = state.LFSR_lo[(short)(i + 1)];
|
||||||
|
// }
|
||||||
|
// // LFSR_hi 向左移
|
||||||
|
// for (short i = 0; i < (short)15; i++) {
|
||||||
|
// state.LFSR_hi[i] = state.LFSR_hi[(short)(i + 1)];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// LFSR[15] = v;
|
||||||
|
// // ---- 写回 LFSR[15] ----
|
||||||
|
// state.LFSR_lo[15] = v_lo;
|
||||||
|
// state.LFSR_hi[15] = v_hi;
|
||||||
|
//
|
||||||
|
//// state.R1 = R1;
|
||||||
|
//// state.R2 = R2;
|
||||||
|
// state.R1_lo = R1[0];
|
||||||
|
// state.R1_hi = R1[1];
|
||||||
|
//
|
||||||
|
// state.R2_lo = R2[0];
|
||||||
|
// state.R2_hi = R2[1];
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// return Z;
|
||||||
|
// out[0] = Z[0];
|
||||||
|
// out[1] = Z[1];
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 生成指定长度的密钥流
|
||||||
|
// public static void zuc256GenerateKeystream(Zuc256State state,
|
||||||
|
// short nwords,
|
||||||
|
// short[] keystream_hi,
|
||||||
|
// short[] keystream_lo) {
|
||||||
|
// // 临时存放一个 32 位关键字
|
||||||
|
// short[] tmp = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// for (short i = 0; i < nwords; i++) {
|
||||||
|
// // 生成一个关键字 -> tmp[0]=lo, tmp[1]=hi
|
||||||
|
// zuc256GenerateKeyword(state, tmp);
|
||||||
|
// // 存入输出数组
|
||||||
|
// keystream_lo[i] = tmp[0];
|
||||||
|
// keystream_hi[i] = tmp[1];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 初始化MAC密钥
|
||||||
|
// private static void zuc256SetMacKey(Zuc256State state, byte[] K, byte[] IV, short macbits) {
|
||||||
|
// short[] D = JCSystem.makeTransientShortArray(Zuc256Tables.D_COLS, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] TMP = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] X0 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] X1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] X2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] R1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] R2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] W = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] W1 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] W2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] U = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] V = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] T = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] T2 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// int IV17 = (IV[17] & 0xFF) >> 2;
|
||||||
|
//// int IV18 = ((IV[17] & 0x03) << 4) | ((IV[18] & 0xFF) >> 4);
|
||||||
|
//// int IV19 = ((IV[18] & 0x0F) << 2) | ((IV[19] & 0xFF) >> 6);
|
||||||
|
//// int IV20 = IV[19] & 0x3F;
|
||||||
|
//// int IV21 = (IV[20] & 0xFF) >> 2;
|
||||||
|
//// int IV22 = ((IV[20] & 0x03) << 4) | ((IV[21] & 0xFF) >> 4);
|
||||||
|
//// int IV23 = ((IV[21] & 0x0F) << 2) | ((IV[22] & 0xFF) >> 6);
|
||||||
|
//// int IV24 = IV[22] & 0x3F;
|
||||||
|
// // IV 拆分
|
||||||
|
// short IV17 = (short)((IV[17] & 0xFF) >>> 2);
|
||||||
|
// short IV18 = (short)(((IV[17] & 0x03) << 4) | ((IV[18] & 0xFF) >>> 4));
|
||||||
|
// short IV19 = (short)(((IV[18] & 0x0F) << 2) | ((IV[19] & 0xFF) >>> 6));
|
||||||
|
// short IV20 = (short)(IV[19] & 0x3F);
|
||||||
|
// short IV21 = (short)((IV[20] & 0xFF) >>> 2);
|
||||||
|
// short IV22 = (short)(((IV[20] & 0x03) << 4) | ((IV[21] & 0xFF) >>> 4));
|
||||||
|
// short IV23 = (short)(((IV[21] & 0x0F) << 2) | ((IV[22] & 0xFF) >>> 6));
|
||||||
|
// short IV24 = (short)(IV[22] & 0x3F);
|
||||||
|
//
|
||||||
|
//// D = (macbits / 32 < 3) ? Zuc256Tables.ZUC256_D[macbits / 32] : Zuc256Tables.ZUC256_D[3];
|
||||||
|
// short row = (short)((macbits / 32) < 3 ? (macbits / 32) : 3);
|
||||||
|
// Zuc256Tables.getDRow(row, D, (short)0);
|
||||||
|
// Zuc256Tables.getDRow(row, D, (short)0);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// short[] tmp = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); // 临时存储 makeU31 输出 (lo,hi)
|
||||||
|
//
|
||||||
|
// // 逐项装载 LFSR
|
||||||
|
//// LFSR[0] = makeU31(K[0] & 0xFF, D[0], K[21] & 0xFF, K[16] & 0xFF);
|
||||||
|
// makeU31((short)(K[0] & 0xFF), (short)D[0], (short)(K[21] & 0xFF), (short)(K[16] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[0] = tmp[0]; state.LFSR_hi[0] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[1] = makeU31(K[1] & 0xFF, D[1], K[22] & 0xFF, K[17] & 0xFF);
|
||||||
|
// makeU31((short)(K[1] & 0xFF), (short)D[1], (short)(K[22] & 0xFF), (short)(K[17] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[1] = tmp[0]; state.LFSR_hi[1] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[2] = makeU31(K[2] & 0xFF, D[2], K[23] & 0xFF, K[18] & 0xFF);
|
||||||
|
// makeU31((short)(K[2] & 0xFF), (short)D[2], (short)(K[23] & 0xFF), (short)(K[18] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[2] = tmp[0]; state.LFSR_hi[2] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[3] = makeU31(K[3] & 0xFF, D[3], K[24] & 0xFF, K[19] & 0xFF);
|
||||||
|
// makeU31((short)(K[3] & 0xFF), (short)D[3], (short)(K[24] & 0xFF), (short)(K[19] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[3] = tmp[0]; state.LFSR_hi[3] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[4] = makeU31(K[4] & 0xFF, D[4], K[25] & 0xFF, K[20] & 0xFF);
|
||||||
|
// makeU31((short)(K[4] & 0xFF), (short)D[4], (short)(K[25] & 0xFF), (short)(K[20] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[4] = tmp[0]; state.LFSR_hi[4] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[5] = makeU31(IV[0] & 0xFF, (D[5] | IV17), K[5] & 0xFF, K[26] & 0xFF);
|
||||||
|
// makeU31((short)(IV[0] & 0xFF), (short)(D[5] | IV17), (short)(K[5] & 0xFF), (short)(K[26] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[5] = tmp[0]; state.LFSR_hi[5] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[6] = makeU31(IV[1] & 0xFF, (D[6] | IV18), K[6] & 0xFF, K[27] & 0xFF);
|
||||||
|
// makeU31((short)(IV[1] & 0xFF), (short)(D[6] | IV18), (short)(K[6] & 0xFF), (short)(K[27] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[6] = tmp[0]; state.LFSR_hi[6] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[7] = makeU31(IV[10] & 0xFF, (D[7] | IV19), K[7] & 0xFF, IV[2] & 0xFF);
|
||||||
|
// makeU31((short)(IV[10] & 0xFF), (short)(D[7] | IV19), (short)(K[7] & 0xFF), (short)(IV[2] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[7] = tmp[0]; state.LFSR_hi[7] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[8] = makeU31(K[8] & 0xFF, (D[8] | IV20), IV[3] & 0xFF, IV[11] & 0xFF);
|
||||||
|
// makeU31((short)(K[8] & 0xFF), (short)(D[8] | IV20), (short)(IV[3] & 0xFF), (short)(IV[11] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[8] = tmp[0]; state.LFSR_hi[8] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[9] = makeU31(K[9] & 0xFF, (D[9] | IV21), IV[12] & 0xFF, IV[4] & 0xFF);
|
||||||
|
// makeU31((short)(K[9] & 0xFF), (short)(D[9] | IV21), (short)(IV[12] & 0xFF), (short)(IV[4] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[9] = tmp[0]; state.LFSR_hi[9] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[10] = makeU31(IV[5] & 0xFF, (D[10] | IV22), K[10] & 0xFF, K[28] & 0xFF);
|
||||||
|
// makeU31((short)(IV[5] & 0xFF), (short)(D[10] | IV22), (short)(K[10] & 0xFF), (short)(K[28] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[10] = tmp[0]; state.LFSR_hi[10] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[11] = makeU31(K[11] & 0xFF, (D[11] | IV23), IV[6] & 0xFF, IV[13] & 0xFF);
|
||||||
|
// makeU31((short)(K[11] & 0xFF), (short)(D[11] | IV23), (short)(IV[6] & 0xFF), (short)(IV[13] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[11] = tmp[0]; state.LFSR_hi[11] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[12] = makeU31(K[12] & 0xFF, (D[12] | IV24), IV[7] & 0xFF, IV[14] & 0xFF);
|
||||||
|
// makeU31((short)(K[12] & 0xFF), (short)(D[12] | IV24), (short)(IV[7] & 0xFF), (short)(IV[14] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[12] = tmp[0]; state.LFSR_hi[12] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[13] = makeU31(K[13] & 0xFF, D[13], IV[15] & 0xFF, IV[8] & 0xFF);
|
||||||
|
// makeU31((short)(K[13] & 0xFF), (short)D[13], (short)(IV[15] & 0xFF), (short)(IV[8] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[13] = tmp[0]; state.LFSR_hi[13] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[14] = makeU31(K[14] & 0xFF, (D[14] | (K[31] >>> 4)), IV[16] & 0xFF, IV[9] & 0xFF);
|
||||||
|
// makeU31((short)(K[14] & 0xFF), (short)(D[14] | ((K[31] & 0xFF) >>> 4)), (short)(IV[16] & 0xFF), (short)(IV[9] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[14] = tmp[0]; state.LFSR_hi[14] = tmp[1];
|
||||||
|
//
|
||||||
|
//// LFSR[15] = makeU31(K[15] & 0xFF, (D[15] | (K[31] & 0x0F)), K[30] & 0xFF, K[29] & 0xFF);
|
||||||
|
// makeU31((short)(K[15] & 0xFF), (short)(D[15] | (K[31] & 0x0F)), (short)(K[30] & 0xFF), (short)(K[29] & 0xFF), tmp);
|
||||||
|
// state.LFSR_lo[15] = tmp[0]; state.LFSR_hi[15] = tmp[1];
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// short c15_2 = 0;
|
||||||
|
// for (short i = 0; i < 32; i++) {
|
||||||
|
// // BitReconstruction3
|
||||||
|
//// X0 = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
|
||||||
|
// // X0 = ((L15 & 0x7FFF8000)<<1) | (L14 & 0xFFFF)
|
||||||
|
// c15_2 = (short)((state.LFSR_lo[15] & (short)0x8000) >>> 15);
|
||||||
|
// X0[1] = (short)(((state.LFSR_hi[15] & (short)0x7FFF) << 1) | (short)(c15_2 & 0x0001));
|
||||||
|
// X0[0] = state.LFSR_lo[14];
|
||||||
|
//
|
||||||
|
//// X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
|
||||||
|
// // X1 = ((L11 & 0xFFFF)<<16) | (L9>>>15)
|
||||||
|
// X1[1] = state.LFSR_lo[11];
|
||||||
|
// X1[0] = (short)((((state.LFSR_lo[9] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[9] << 1));
|
||||||
|
//
|
||||||
|
//// X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
|
||||||
|
// // X2 = ((L7 & 0xFFFF)<<16) | (L5>>>15)
|
||||||
|
// X2[1] = state.LFSR_lo[7];
|
||||||
|
// X2[0] = (short)((((state.LFSR_lo[5] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[5] << 1));
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // F(X0, X1, X2)
|
||||||
|
// // W = (X0 ^ R1) + R2
|
||||||
|
// xor32(X0[0], X0[1], R1[0], R1[1], TMP);
|
||||||
|
// add32(TMP[0], TMP[1], R2[0], R2[1], W);
|
||||||
|
//
|
||||||
|
// // W1 = R1 + X1
|
||||||
|
// add32(R1[0], R1[1], X1[0], X1[1], W1);
|
||||||
|
//
|
||||||
|
// // W2 = R2 ^ X2
|
||||||
|
// xor32(R2[0], R2[1], X2[0], X2[1], W2);
|
||||||
|
//
|
||||||
|
// // U = L1((W1<<16) | (W2>>>16))
|
||||||
|
// L1(W2[1], W1[0], U);
|
||||||
|
//
|
||||||
|
// // V = L2((W2<<16) | (W1>>>16))
|
||||||
|
// L2(W1[1], W2[0], V);
|
||||||
|
//
|
||||||
|
//// R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[(U >>> 16) & 0xFF],
|
||||||
|
//// Zuc256Tables.S0[(U >>> 8) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[U & 0xFF]);
|
||||||
|
////
|
||||||
|
//// R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[(V >>> 16) & 0xFF],
|
||||||
|
//// Zuc256Tables.S0[(V >>> 8) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[V & 0xFF]);
|
||||||
|
// // 更新 R1,R2
|
||||||
|
// makeU32(
|
||||||
|
// (short)(Zuc256Tables.S0[((U[1] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(U[1] & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S0[((U[0] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(U[0] & 0xFF)] & 0xFF),
|
||||||
|
// R1);
|
||||||
|
//
|
||||||
|
// makeU32(
|
||||||
|
// (short)(Zuc256Tables.S0[((V[1] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(V[1] & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S0[((V[0] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(V[0] & 0xFF)] & 0xFF),
|
||||||
|
// R2);
|
||||||
|
//
|
||||||
|
// // LFSRWithInitialisationMode(W >> 1)
|
||||||
|
//// int v = LFSR[0];
|
||||||
|
// V[0] = state.LFSR_lo[0];
|
||||||
|
// V[1] = state.LFSR_hi[0];
|
||||||
|
//
|
||||||
|
// // v = add31(v, rot31(state.LFSR[0], 8))
|
||||||
|
// rot31(state.LFSR_lo[0], state.LFSR_hi[0], (short)8, T);
|
||||||
|
// add31(V[0], V[1], T[0], T[1], V);
|
||||||
|
//
|
||||||
|
//// v = add31(v, rot31(state.LFSR[4], 20));
|
||||||
|
// rot31(state.LFSR_lo[4], state.LFSR_hi[4], (short)20, T);
|
||||||
|
// add31(V[0], V[1], T[0], T[1], V);
|
||||||
|
//
|
||||||
|
//// v = add31(v, rot31(state.LFSR[10], 21));
|
||||||
|
// rot31(state.LFSR_lo[10], state.LFSR_hi[10], (short)21, T);
|
||||||
|
// add31(V[0], V[1], T[0], T[1], V);
|
||||||
|
//
|
||||||
|
//// v = add31(v, rot31(state.LFSR[13], 17));
|
||||||
|
// rot31(state.LFSR_lo[13], state.LFSR_hi[13], (short)17, T);
|
||||||
|
// add31(V[0], V[1], T[0], T[1], V);
|
||||||
|
//
|
||||||
|
//// v = add31(v, rot31(state.LFSR[15], 15));
|
||||||
|
// rot31(state.LFSR_lo[15], state.LFSR_hi[15], (short)15, T);
|
||||||
|
// add31(V[0], V[1], T[0], T[1], V);
|
||||||
|
//
|
||||||
|
//// v = add31(v, W >>> 1);
|
||||||
|
// shr32u1(W[0], W[1], T2); // T2[0]=lo, T2[1]=hi(无符号>>>1)
|
||||||
|
// T2[1] = (short)(T2[1] & (short)0xFFFF); // 只保留31位
|
||||||
|
// add31(V[0], V[1], T2[0], T2[1], V);
|
||||||
|
//
|
||||||
|
// // System.arraycopy(state.LFSR, 1, state.LFSR, 0, 15)
|
||||||
|
//// 相当于 System.arraycopy(state.LFSR_lo, 1, state.LFSR_lo, 0, 15);
|
||||||
|
// for (short j = 0; j < (short)15; j++) {
|
||||||
|
// state.LFSR_lo[j] = state.LFSR_lo[(short)(j + 1)];
|
||||||
|
// }
|
||||||
|
//// 相当于 System.arraycopy(state.LFSR_hi, 1, state.LFSR_hi, 0, 15);
|
||||||
|
// for (short j = 0; j < (short)15; j++) {
|
||||||
|
// state.LFSR_hi[j] = state.LFSR_hi[(short)(j + 1)];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// state.LFSR[15] = v;
|
||||||
|
// state.LFSR_lo[15] = V[0];
|
||||||
|
// state.LFSR_hi[15] = (short)(V[1] & 0x7FFF);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // BitReconstruction2
|
||||||
|
//// X1 = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >>> 15);
|
||||||
|
// X1[1] = state.LFSR_lo[11];
|
||||||
|
// X1[0] = (short)((((state.LFSR_lo[9] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[9] << 1));
|
||||||
|
//
|
||||||
|
//// X2 = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >>> 15);
|
||||||
|
// X2[1] = state.LFSR_lo[7];
|
||||||
|
// X2[0] = (short)((((state.LFSR_lo[5] & (short)0x8000) >>> 15) & 0X0001) | (state.LFSR_hi[5] << 1));
|
||||||
|
//
|
||||||
|
// // F_(X1, X2)
|
||||||
|
//// W1 = R1 + X1;
|
||||||
|
// add32(R1[0], R1[1], X1[0], X1[1], W1); // W1 = R1 + X1
|
||||||
|
//// W2 = R2 ^ X2;
|
||||||
|
// xor32(R2[0], R2[1], X2[0], X2[1], W2); // W2 = R2 ^ X2
|
||||||
|
//
|
||||||
|
//// U = L1((W1 << 16) | (W2 >>> 16));
|
||||||
|
// // U = L1((W1<<16)|(W2>>>16)) → lo=W2_hi, hi=W1_lo
|
||||||
|
// L1(W2[1], W1[0], U);
|
||||||
|
//
|
||||||
|
//// V = L2((W2 << 16) | (W1 >>> 16));
|
||||||
|
// // V = L2((W2<<16)|(W1>>>16)) → lo=W1_hi, hi=W2_lo
|
||||||
|
// L2(W1[1], W2[0], V);
|
||||||
|
//
|
||||||
|
//// R1 = makeU32(Zuc256Tables.S0[(U >>> 24) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[(U >>> 16) & 0xFF],
|
||||||
|
//// Zuc256Tables.S0[(U >>> 8) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[U & 0xFF]);
|
||||||
|
// makeU32(
|
||||||
|
// (short)(Zuc256Tables.S0[((U[1] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(U[1] & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S0[((U[0] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(U[0] & 0xFF)] & 0xFF),
|
||||||
|
// R1);
|
||||||
|
//
|
||||||
|
//// R2 = makeU32(Zuc256Tables.S0[(V >>> 24) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[(V >>> 16) & 0xFF],
|
||||||
|
//// Zuc256Tables.S0[(V >>> 8) & 0xFF],
|
||||||
|
//// Zuc256Tables.S1[V & 0xFF]);
|
||||||
|
// makeU32(
|
||||||
|
// (short)(Zuc256Tables.S0[((V[1] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(V[1] & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S0[((V[0] >>> 8) & 0xFF)] & 0xFF),
|
||||||
|
// (short)(Zuc256Tables.S1[(V[0] & 0xFF)] & 0xFF),
|
||||||
|
// R2);
|
||||||
|
//
|
||||||
|
// // ---- LFSRWithWorkMode ----
|
||||||
|
// short[] A = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);; // 64位累加器
|
||||||
|
// short[] tmp32 = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);;
|
||||||
|
// short[] tmp64 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);;
|
||||||
|
//
|
||||||
|
// // LFSRWithWorkMode
|
||||||
|
//// long a = LFSR[0];
|
||||||
|
// tmp32[0] = state.LFSR_lo[0];
|
||||||
|
// tmp32[1] = state.LFSR_hi[0];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)0); add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a += (long)LFSR[0] << 8;
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)8); add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a += (long)LFSR[4] << 20;
|
||||||
|
// tmp32[0] = state.LFSR_lo[4]; tmp32[1] = state.LFSR_hi[4];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)20); add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a += (long)LFSR[10] << 21;
|
||||||
|
// tmp32[0] = state.LFSR_lo[10]; tmp32[1] = state.LFSR_hi[10];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)21); add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a += (long)LFSR[13] << 17;
|
||||||
|
// tmp32[0] = state.LFSR_lo[13]; tmp32[1] = state.LFSR_hi[13];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)17); add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a += (long)LFSR[15] << 15;
|
||||||
|
// tmp32[0] = state.LFSR_lo[15]; tmp32[1] = state.LFSR_hi[15];
|
||||||
|
// create_64b_from_32b(tmp64, tmp32, (short)15); add64(A, tmp64);
|
||||||
|
//
|
||||||
|
//// a = (a & 0x7FFFFFFF) + (a >>> 31);
|
||||||
|
// short[] low31 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);;
|
||||||
|
// short[] r31 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);;
|
||||||
|
// and64_7FFFFFFF_to32(A, low31);
|
||||||
|
// shr64u_31(A, r31);
|
||||||
|
//
|
||||||
|
// short[] v64 = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);;
|
||||||
|
// add64(v64, low31);
|
||||||
|
// add64(v64, r31);
|
||||||
|
//
|
||||||
|
//// int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
|
||||||
|
// and64_7FFFFFFF_to32(v64, low31);
|
||||||
|
// shr64u_31(v64, r31);
|
||||||
|
// short[] vv = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);;
|
||||||
|
// add64(vv, low31);
|
||||||
|
// add64(vv, r31);
|
||||||
|
//
|
||||||
|
// short v_lo = vv[0];
|
||||||
|
// short v_hi = (short)(vv[1] & 0x7FFF);
|
||||||
|
//
|
||||||
|
//// LFSR左移
|
||||||
|
//// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||||
|
// // LFSR_lo 向左移
|
||||||
|
// for (short i = 0; i < (short)15; i++) {
|
||||||
|
// state.LFSR_lo[i] = state.LFSR_lo[(short)(i + 1)];
|
||||||
|
// }
|
||||||
|
// // LFSR_hi 向左移
|
||||||
|
// for (short i = 0; i < (short)15; i++) {
|
||||||
|
// state.LFSR_hi[i] = state.LFSR_hi[(short)(i + 1)];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//// LFSR[15] = v;
|
||||||
|
// state.LFSR_lo[15] = v_lo;
|
||||||
|
// state.LFSR_hi[15] = v_hi;
|
||||||
|
//
|
||||||
|
// state.R1_lo = R1[0]; state.R1_hi = R1[1];
|
||||||
|
// state.R2_lo = R2[0]; state.R2_hi = R2[1];
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
214
build_tools/Project/Src/Zuc256EncryptCtx.java
Normal file
214
build_tools/Project/Src/Zuc256EncryptCtx.java
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
//package com.cscn;
|
||||||
|
//
|
||||||
|
//import javacard.framework.JCSystem;
|
||||||
|
//import javacard.framework.Util;
|
||||||
|
//
|
||||||
|
//import static com.cscn.Zuc256Core.zuc256GenerateKeystream;
|
||||||
|
//import static com.cscn.Zuc256Core.zuc256GenerateKeyword;
|
||||||
|
//import static com.cscn.Zuc256Util.getU32;
|
||||||
|
//import static com.cscn.Zuc256Util.putU32;
|
||||||
|
//import static com.cscn.Zuc256Util.xor32;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * 加密上下文类
|
||||||
|
// */
|
||||||
|
//public final class Zuc256EncryptCtx {
|
||||||
|
// Zuc256State state;
|
||||||
|
// byte[] buf;
|
||||||
|
// short buflen;
|
||||||
|
//
|
||||||
|
// public Zuc256EncryptCtx(Zuc256State state, byte[] buf){
|
||||||
|
// this.state = state;
|
||||||
|
// this.buf = buf;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public Zuc256EncryptCtx(Zuc256State state){
|
||||||
|
// this.state = state;
|
||||||
|
// this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public Zuc256EncryptCtx(){
|
||||||
|
// this.state = new Zuc256State(); //todo how to put in ram?
|
||||||
|
// this.buf = JCSystem.makeTransientByteArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 初始化加密上下文
|
||||||
|
// public void initZuc256EncryptCtx(byte[] key32, byte[] iv) {
|
||||||
|
//// Arrays.fill(this.buf, (byte) 0);
|
||||||
|
// for (short i = 0; i < (short)this.buf.length; i++) {
|
||||||
|
// this.buf[i] = (byte)0;
|
||||||
|
// }
|
||||||
|
// this.buflen = 0;
|
||||||
|
// Zuc256Core.initState(this.state, key32, iv);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 分阶段处理加密数据
|
||||||
|
// public void updateZuc256EncryptCtx(byte[] in, short inlen, byte[] out) {
|
||||||
|
// if (in == null || out == null || inlen == 0) return;
|
||||||
|
//
|
||||||
|
// short inPos = 0; // 输入偏移
|
||||||
|
// short outPos = 0; // 输出偏移
|
||||||
|
//
|
||||||
|
// // 处理缓冲区中剩余的非4字节数据
|
||||||
|
// if (this.buflen > 0) {
|
||||||
|
//// int need = 4 - this.buflen;
|
||||||
|
// short need = (short)(4 - this.buflen);
|
||||||
|
//// int copy = Math.min(inlen, need);
|
||||||
|
// short copy = (short)((inlen < need) ? inlen : need);
|
||||||
|
//
|
||||||
|
// // 替代 System.arraycopy(in, 0, this.buf, this.buflen, copy);
|
||||||
|
// Util.arrayCopyNonAtomic(in, (short)0, this.buf, this.buflen, copy);
|
||||||
|
//
|
||||||
|
// this.buflen += copy;
|
||||||
|
//
|
||||||
|
// // 调整输入指针和长度
|
||||||
|
//// byte[] newIn = new byte[inlen - copy];
|
||||||
|
//// if (inlen - copy > 0) {
|
||||||
|
//// System.arraycopy(in, copy, newIn, 0, inlen - copy);
|
||||||
|
//// }
|
||||||
|
//// in = newIn;
|
||||||
|
//// inlen -= copy;
|
||||||
|
// // 推进输入指针与剩余长度
|
||||||
|
// inPos += copy;
|
||||||
|
// inlen -= copy;
|
||||||
|
//
|
||||||
|
// // 缓冲区已满,处理一个完整的4字节块
|
||||||
|
// if (this.buflen == 4) {
|
||||||
|
//// int keystream = zuc256GenerateKeyword(this.state);
|
||||||
|
// short[] ks = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// zuc256GenerateKeyword(this.state, ks); // ks[0]=lo, ks[1]=hi
|
||||||
|
//
|
||||||
|
//// int plain = getU32(this.buf, 0);
|
||||||
|
// // 取出 4 字节明文 → plain[0]=lo, plain[1]=hi
|
||||||
|
// short[] plain = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// getU32(this.buf, (short)0, plain);
|
||||||
|
//
|
||||||
|
//// putU32(out, 0, plain ^ keystream);
|
||||||
|
// // plain ^ ks → res
|
||||||
|
// short[] res = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// xor32(plain[0], plain[1], ks[0], ks[1], res);
|
||||||
|
// // 写回 out 的前4字节
|
||||||
|
// putU32(out, (short)0, res[0], res[1]);
|
||||||
|
//
|
||||||
|
// this.buflen = 0;
|
||||||
|
//// Arrays.fill(this.buf, (byte) 0);
|
||||||
|
// for (short i = 0; i < (short)this.buf.length; i++) {
|
||||||
|
// this.buf[i] = (byte)0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 调整输出指针
|
||||||
|
//// byte[] newOut = new byte[out.length - 4];
|
||||||
|
//// if (out.length - 4 > 0) {
|
||||||
|
//// System.arraycopy(out, 4, newOut, 0, out.length - 4);
|
||||||
|
//// }
|
||||||
|
//// out = newOut;
|
||||||
|
// // 这里C实现就是直接指针+4的。JavaSE实现搞这个new干嘛。。
|
||||||
|
// outPos += 4;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 处理完整的4字节块
|
||||||
|
//// int fullBlocks = inlen / 4;
|
||||||
|
// short fullBlocks = (short) (inlen / 4);
|
||||||
|
// if (fullBlocks > 0) {
|
||||||
|
//// int[] keystream = new int[fullBlocks];
|
||||||
|
// short[] ks_hi = JCSystem.makeTransientShortArray(fullBlocks, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] ks_lo = JCSystem.makeTransientShortArray(fullBlocks, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
//// zuc256GenerateKeystream(this.state, fullBlocks, keystream);
|
||||||
|
// zuc256GenerateKeystream(this.state, fullBlocks, ks_hi, ks_lo);
|
||||||
|
//
|
||||||
|
// // 临时:装一个32位字
|
||||||
|
// short[] word = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // 逐块异或加密
|
||||||
|
// for (short i = 0; i < fullBlocks; i++) {
|
||||||
|
//// int plain = getU32(in, i * 4);
|
||||||
|
// short off = (short) (i << 2); // i*4
|
||||||
|
// // 读明文
|
||||||
|
// getU32(in, (short)(inPos+off), word); // word[0]=lo, word[1]=hi
|
||||||
|
//
|
||||||
|
//// putU32(out, i * 4, plain ^ keystream[i]);
|
||||||
|
// // XOR keystream
|
||||||
|
// word[0] = (short)(word[0] ^ ks_lo[i]);
|
||||||
|
// word[1] = (short)(word[1] ^ ks_hi[i]);
|
||||||
|
// // 写密文
|
||||||
|
// putU32(out, (short) (outPos+off), word[0], word[1]);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 调整输入指针和长度
|
||||||
|
//// int processed = fullBlocks * 4;
|
||||||
|
// short processed = (short)(fullBlocks * 4);
|
||||||
|
//
|
||||||
|
//// byte[] newIn = new byte[inlen - processed];
|
||||||
|
//// if (inlen - processed > 0) {
|
||||||
|
//// System.arraycopy(in, processed, newIn, 0, inlen - processed);
|
||||||
|
//// }
|
||||||
|
//// in = newIn;
|
||||||
|
//// inlen -= processed;
|
||||||
|
// // 推进输入/输出指针与剩余长度
|
||||||
|
// inPos += processed;
|
||||||
|
// inlen -= processed;
|
||||||
|
// outPos += processed;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 缓存剩余不足4字节的数据
|
||||||
|
// if (inlen > 0) {
|
||||||
|
// // 等价于 System.arraycopy(in, 0, this.buf, 0, inlen);
|
||||||
|
// Util.arrayCopyNonAtomic(in, (short)inPos, this.buf, (short)0, inlen);
|
||||||
|
//
|
||||||
|
// this.buflen = inlen;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 完成加密处理
|
||||||
|
// public void finishZuc256EncryptCtx(byte[] out) {
|
||||||
|
// if (out == null) return;
|
||||||
|
//
|
||||||
|
// // 处理缓冲区中剩余的不足4字节数据
|
||||||
|
// if (this.buflen > 0) {
|
||||||
|
//// int keystream = zuc256GenerateKeyword(this.state);
|
||||||
|
// // 生成一个 32-bit 密钥字:ks[0]=lo16, ks[1]=hi16
|
||||||
|
// short[] ks = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// zuc256GenerateKeyword(this.state, ks);
|
||||||
|
//
|
||||||
|
//// byte[] keystreamBytes = new byte[4];
|
||||||
|
//// putU32(keystreamBytes, 0, keystream);
|
||||||
|
// byte[] keystreamBytes = JCSystem.makeTransientByteArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// putU32(keystreamBytes, (short)0, ks[0], ks[1]);
|
||||||
|
//
|
||||||
|
// // 逐字节异或
|
||||||
|
// short outOffset = (short)(out.length - this.buflen);
|
||||||
|
// for (short i = 0; i < this.buflen; i++) {
|
||||||
|
// out[(short)(i+outOffset)] = (byte) (this.buf[i] ^ keystreamBytes[i]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 清理上下文
|
||||||
|
//// Arrays.fill(this.buf, (byte) 0);
|
||||||
|
// for(short i=0; i<4; i++) {
|
||||||
|
// this.buf[i] = (byte)0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// this.buflen = 0;
|
||||||
|
//
|
||||||
|
//// Arrays.fill(this.state.LFSR, 0);
|
||||||
|
// // LFSR 全部清零(高低位数组各 16 个元素)
|
||||||
|
// for (short i = 0; i < 16; i++) {
|
||||||
|
// this.state.LFSR_lo[i] = 0;
|
||||||
|
// this.state.LFSR_hi[i] = 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// this.state.R1 = 0;
|
||||||
|
//// this.state.R2 = 0;
|
||||||
|
//// R1、R2 清零
|
||||||
|
// this.state.R1_lo = 0;
|
||||||
|
// this.state.R1_hi = 0;
|
||||||
|
// this.state.R2_lo = 0;
|
||||||
|
// this.state.R2_hi = 0;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
32
build_tools/Project/Src/Zuc256MacCtx.java
Normal file
32
build_tools/Project/Src/Zuc256MacCtx.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//package com.cscn;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * MAC上下文类(JavaCard版,int 拆分为两个 short)
|
||||||
|
// */
|
||||||
|
//public final class Zuc256MacCtx {
|
||||||
|
// // LFSR: 原本 int[16],拆成 hi/lo 各 16 short
|
||||||
|
// short[] LFSR_hi = JCSystem.makeTransientShortArray((short)16, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// //todo -> ram
|
||||||
|
// short[] LFSR_lo = JCSystem.makeTransientShortArray((short)16, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // R1、R2: 原本 int,拆成 hi/lo
|
||||||
|
// short R1_hi;
|
||||||
|
// short R1_lo;
|
||||||
|
// short R2_hi;
|
||||||
|
// short R2_lo;
|
||||||
|
//
|
||||||
|
// // 缓冲区
|
||||||
|
// byte[] buf = JCSystem.makeTransientByteArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short buflen;
|
||||||
|
//
|
||||||
|
// // T: 原本 int[4],拆成 hi/lo
|
||||||
|
// short[] T_hi = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] T_lo = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // K0: 原本 int[4],拆成 hi/lo
|
||||||
|
// short[] K0_hi = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] K0_lo = JCSystem.makeTransientShortArray((short)4, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // macbits: 原本 int,改成 short 足够
|
||||||
|
// short macbits;
|
||||||
|
//}
|
||||||
25
build_tools/Project/Src/Zuc256State.java
Normal file
25
build_tools/Project/Src/Zuc256State.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//package com.cscn;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * ZUC状态类(JavaCard版,int 拆为 hi/lo short)
|
||||||
|
// */
|
||||||
|
//public class Zuc256State {
|
||||||
|
// // LFSR: 原 int[16] -> hi/lo 各 16
|
||||||
|
// public short[] LFSR_hi;
|
||||||
|
// public short[] LFSR_lo;
|
||||||
|
//
|
||||||
|
// // R1, R2: 原 int -> hi/lo
|
||||||
|
// public short R1_hi;
|
||||||
|
// public short R1_lo;
|
||||||
|
// public short R2_hi;
|
||||||
|
// public short R2_lo;
|
||||||
|
//
|
||||||
|
// public Zuc256State() {
|
||||||
|
// this.LFSR_hi = JCSystem.makeTransientShortArray((short)16, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// this.LFSR_lo = JCSystem.makeTransientShortArray((short)16, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// }
|
||||||
|
// public Zuc256State(short[] LSFR_HIGH, short[] LSFR_LOW) {
|
||||||
|
// this.LFSR_hi = LSFR_HIGH;
|
||||||
|
// this.LFSR_lo = LSFR_LOW;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
98
build_tools/Project/Src/Zuc256Tables.java
Normal file
98
build_tools/Project/Src/Zuc256Tables.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package com.cscn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常量表:S0/S1 与 ZUC256_D。
|
||||||
|
* 注意:JavaCard 目标环境建议将表定义为 static final 数组,按 int/short 存放。
|
||||||
|
* 适配说明:已将 32bit int 数组改为 16bit short 数组,符合JavaCard 16bit能力要求
|
||||||
|
*/
|
||||||
|
public final class Zuc256Tables {
|
||||||
|
|
||||||
|
// 私有构造函数:防止类被实例化
|
||||||
|
private Zuc256Tables() {}
|
||||||
|
|
||||||
|
// S盒:S0, S1
|
||||||
|
public static final short[] S0 = {
|
||||||
|
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
|
||||||
|
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
|
||||||
|
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
|
||||||
|
0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
|
||||||
|
0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
|
||||||
|
0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
|
||||||
|
0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
|
||||||
|
0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
|
||||||
|
0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
|
||||||
|
0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
|
||||||
|
0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
|
||||||
|
0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
|
||||||
|
0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
|
||||||
|
0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
|
||||||
|
0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
|
||||||
|
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final short[] S1 = {
|
||||||
|
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
|
||||||
|
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
|
||||||
|
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
|
||||||
|
0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
|
||||||
|
0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
|
||||||
|
0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
|
||||||
|
0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
|
||||||
|
0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
|
||||||
|
0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
|
||||||
|
0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
|
||||||
|
0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
|
||||||
|
0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
|
||||||
|
0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
|
||||||
|
0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
|
||||||
|
0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
|
||||||
|
0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2
|
||||||
|
};
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 常量数组 D(16bit short二维数组适配)
|
||||||
|
// */
|
||||||
|
// public static final short[][] ZUC256_D = {
|
||||||
|
// {0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
// {0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
// {0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30},
|
||||||
|
// {0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30}
|
||||||
|
// };
|
||||||
|
public static final short D_COLS = 16;
|
||||||
|
/**
|
||||||
|
* 常量数组 D(16bit short二维数组适配)
|
||||||
|
*/
|
||||||
|
public static final short[] ZUC256_D_FLAT = {
|
||||||
|
// row 0
|
||||||
|
0x22,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30,
|
||||||
|
|
||||||
|
// row 1
|
||||||
|
0x22,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30,
|
||||||
|
|
||||||
|
// row 2
|
||||||
|
0x23,0x2F,0x24,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30,
|
||||||
|
|
||||||
|
// row 3
|
||||||
|
0x23,0x2F,0x25,0x2A,0x6D,0x40,0x40,0x40,
|
||||||
|
0x40,0x40,0x40,0x40,0x40,0x52,0x10,0x30
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** 读取 D[row][col],返回无符号值 0..255 */
|
||||||
|
public static short getD(short row, short col) {
|
||||||
|
// idx = row * 16 + col
|
||||||
|
short idx = (short)(row * D_COLS + col);
|
||||||
|
return (short)(ZUC256_D_FLAT[idx] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取一行 (返回一段16个short) */
|
||||||
|
public static void getDRow(short row, short[] out, short outOff) {
|
||||||
|
short base = (short)(row * D_COLS);
|
||||||
|
for (short i = 0; i < D_COLS; i++) {
|
||||||
|
out[(short)(outOff + i)] = ZUC256_D_FLAT[(short)(base + i)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
497
build_tools/Project/Src/Zuc256Util.java
Normal file
497
build_tools/Project/Src/Zuc256Util.java
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
//package com.cscn;
|
||||||
|
//
|
||||||
|
//import javacard.framework.Util;
|
||||||
|
//import javacard.framework.JCSystem;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * 辅助工具:装载/存储、位运算、线性变换、打印等。
|
||||||
|
// */
|
||||||
|
//public final class Zuc256Util {
|
||||||
|
//
|
||||||
|
// private Zuc256Util() {}
|
||||||
|
//
|
||||||
|
//// /** 辅助方法:将字节数组转换为32位整数 */
|
||||||
|
//// public static int getU32(byte[] p, int offset) {
|
||||||
|
//// return ((p[offset] & 0xFF) << 24) |
|
||||||
|
//// ((p[offset + 1] & 0xFF) << 16) |
|
||||||
|
//// ((p[offset + 2] & 0xFF) << 8) |
|
||||||
|
//// (p[offset + 3] & 0xFF);
|
||||||
|
//// }
|
||||||
|
// /** 辅助方法:从字节数组取出 32 位整数,存放到 short[2] (lo, hi) */
|
||||||
|
// public static void getU32(byte[] p, short offset, short[] out32 /* len=2 */) {
|
||||||
|
// out32[0] = (short) (((p[(short)(offset + 2)] & 0xFF) << 8) | (p[(short)(offset + 3)] & 0xFF)); //低16位
|
||||||
|
// out32[1] = (short) (((p[offset] & 0xFF) << 8) | (p[(short)(offset + 1)] & 0xFF)); //高16位
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /** 辅助方法:将32位整数转换为字节数组 */
|
||||||
|
//// public static void putU32(byte[] p, int offset, int v) {
|
||||||
|
//// p[offset] = (byte) (v >> 24);
|
||||||
|
//// p[offset + 1] = (byte) (v >> 16);
|
||||||
|
//// p[offset + 2] = (byte) (v >> 8);
|
||||||
|
//// p[offset + 3] = (byte) v;
|
||||||
|
//// }
|
||||||
|
// /** 辅助方法:将32位整数(vlo=低16位, vhi=高16位)写入字节数组 */
|
||||||
|
// public static void putU32(byte[] p, short offset, short vlo, short vhi) {
|
||||||
|
// // 写高16位
|
||||||
|
// p[offset] = (byte) ((vhi >> 8) & 0xFF);
|
||||||
|
// p[(short)(offset + 1)] = (byte) (vhi & 0xFF);
|
||||||
|
//
|
||||||
|
// // 写低16位
|
||||||
|
// p[(short)(offset + 2)] = (byte) ((vlo >> 8) & 0xFF);
|
||||||
|
// p[(short)(offset + 3)] = (byte) (vlo & 0xFF);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // === 31/32 位运算 ===
|
||||||
|
//
|
||||||
|
//// /** 31位加法 */
|
||||||
|
//// public static int add31(int a, int b) {
|
||||||
|
//// long sum = (long)a + b;
|
||||||
|
//// return (int) ((sum & 0x7FFFFFFF) + (sum >> 31));
|
||||||
|
//// }
|
||||||
|
// /** 31位加法: (a+b) mod (2^31 - 1)
|
||||||
|
// * 输入: a_lo=低16位, a_hi=高15位
|
||||||
|
// * b_lo=低16位, b_hi=高15位
|
||||||
|
// * 输出: out[0]=lo, out[1]=hi
|
||||||
|
// */
|
||||||
|
// public static void add31(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /* len==2 */) {
|
||||||
|
// // ---- 低16位相加 ----
|
||||||
|
// short lo = (short)(a_lo + b_lo);
|
||||||
|
// short carry = (short)(
|
||||||
|
// ( ( (short)( (a_lo & b_lo) | ((a_lo | b_lo) & (short)~lo) ) ) & (short)0x8000 ) != 0
|
||||||
|
// ? 1 : 0
|
||||||
|
// );
|
||||||
|
// // ---- 高15位相加 + 进位 ----
|
||||||
|
// short hi_raw = (short)((short)((a_hi & 0x7FFF) + (b_hi & 0x7FFF)) + carry);
|
||||||
|
//
|
||||||
|
// // 提取第31位(hi_raw bit15)
|
||||||
|
// short topbit = (short)((hi_raw >>> 15) & 1);
|
||||||
|
// short hi = (short)(hi_raw & 0x7FFF); // 保留15位
|
||||||
|
//
|
||||||
|
// // ---- 若第31位=1,再+1 ----
|
||||||
|
// if (topbit == 1) {
|
||||||
|
// short lo2 = (short)(lo + 1);
|
||||||
|
// short c2 = (short)((lo2 == 0) ? 1 : 0); // lo溢出时进位
|
||||||
|
// lo = lo2;
|
||||||
|
// hi = (short)((hi + c2) & 0x7FFF);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// out[0] = lo;
|
||||||
|
// out[1] = hi;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /** 31位旋转 */
|
||||||
|
//// public static int rot31(int a, int k) {
|
||||||
|
//// return ((a << k) | (a >>> (31 - k))) & 0x7FFFFFFF;
|
||||||
|
//// }
|
||||||
|
// /** 31位循环左移: (a <<< k) mod (2^31 -1)
|
||||||
|
// * 输入: a_lo=低16位, a_hi=高15位
|
||||||
|
// * 输出: out[0]=lo, out[1]=hi
|
||||||
|
// */
|
||||||
|
// public static void rot31(short a_lo, short a_hi, short k, short[] out /* len==2 */) {
|
||||||
|
// k = (short)(k % 31); // 限制在 0..30
|
||||||
|
// if (k == 0) {
|
||||||
|
// out[0] = a_lo;
|
||||||
|
// out[1] = (short)(a_hi & 0x7FFF);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 拆成 31 位数组 [bit0..bit30]
|
||||||
|
// short[] bits = JCSystem.makeTransientShortArray((short)31, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// for (short i = 0; i < 16; i++) {
|
||||||
|
// bits[i] = (short)((a_lo >>> i) & 1);
|
||||||
|
// }
|
||||||
|
// for (short i = 0; i < 15; i++) {
|
||||||
|
// bits[(short)(16 + i)] = (short)((a_hi >>> i) & 1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 旋转
|
||||||
|
// short[] resBits = JCSystem.makeTransientShortArray((short)31, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// for (short i = 0; i < 31; i++) {
|
||||||
|
// short j = (short)((i + k) % 31);
|
||||||
|
// resBits[j] = bits[i];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 拼回 lo, hi
|
||||||
|
// short lo = 0;
|
||||||
|
// for (short i = 0; i < 16; i++) {
|
||||||
|
// lo = (short)(lo | (resBits[i] << i));
|
||||||
|
// }
|
||||||
|
// short hi = 0;
|
||||||
|
// for (short i = 0; i < 15; i++) {
|
||||||
|
// hi = (short)(hi | (resBits[(short)(16 + i)] << i));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// out[0] = lo;
|
||||||
|
// out[1] = hi;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /** 32位旋转 */
|
||||||
|
//// public static int rot32(int a, int k) {
|
||||||
|
//// return (a << k) | (a >>> (32 - k));
|
||||||
|
//// }
|
||||||
|
// /** 32位循环左移: (a<<<k) */
|
||||||
|
// public static void rot32(short a_lo, short a_hi, short k, short[] out /*len==2*/) {
|
||||||
|
// k = (short)(k & 31); // 0..31
|
||||||
|
// short lo = a_lo, hi = a_hi, nw_hi, nw_lo;
|
||||||
|
// while (k > 0) {
|
||||||
|
// // 先做 1 位循环左移
|
||||||
|
// // 注意:short 在 >>> 时会先提升为 int,所以下面都再用 &1 取最低位,避免符号扩展影响
|
||||||
|
// nw_hi = (short)((hi << 1) | ((lo >>> 15) & 1));
|
||||||
|
// nw_lo = (short)((lo << 1) | ((hi >>> 15) & 1));
|
||||||
|
// hi = nw_hi;
|
||||||
|
// lo = nw_lo;
|
||||||
|
// k--;
|
||||||
|
// }
|
||||||
|
// out[0] = lo; // 低16位
|
||||||
|
// out[1] = hi; // 高16位
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /**
|
||||||
|
//// * L1函数
|
||||||
|
//// */
|
||||||
|
//// public static int L1(int x) {
|
||||||
|
//// return x ^ rot32(x, 2) ^ rot32(x, 10) ^ rot32(x, 18) ^ rot32(x, 24);
|
||||||
|
//// }
|
||||||
|
// /**
|
||||||
|
// * L1函数: x ^ (x<<<2) ^ (x<<<10) ^ (x<<<18) ^ (x<<<24)
|
||||||
|
// * 输入: x_lo, x_hi
|
||||||
|
// * 输出: out[0]=lo, out[1]=hi
|
||||||
|
// */
|
||||||
|
// public static void L1(short x_lo, short x_hi, short[] out /*len==2*/) {
|
||||||
|
// short[] t = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] acc = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // acc = x
|
||||||
|
// acc[0] = x_lo;
|
||||||
|
// acc[1] = x_hi;
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 2)
|
||||||
|
// rot32(x_lo, x_hi, (short)2, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 10)
|
||||||
|
// rot32(x_lo, x_hi, (short)10, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 18)
|
||||||
|
// rot32(x_lo, x_hi, (short)18, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 24)
|
||||||
|
// rot32(x_lo, x_hi, (short)24, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// out[0] = acc[0];
|
||||||
|
// out[1] = acc[1];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /**
|
||||||
|
//// * L2函数
|
||||||
|
//// */
|
||||||
|
//// public static int L2(int x) {
|
||||||
|
//// return x ^ rot32(x, 8) ^ rot32(x, 14) ^ rot32(x, 22) ^ rot32(x, 30);
|
||||||
|
//// }
|
||||||
|
// /**
|
||||||
|
// * L2函数: x ^ (x<<<8) ^ (x<<<14) ^ (x<<<22) ^ (x<<<30)
|
||||||
|
// * 输入: x_lo, x_hi
|
||||||
|
// * 输出: out[0]=lo, out[1]=hi
|
||||||
|
// */
|
||||||
|
// public static void L2(short x_lo, short x_hi, short[] out /*len==2*/) {
|
||||||
|
// short[] t = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// short[] acc = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // acc = x
|
||||||
|
// acc[0] = x_lo;
|
||||||
|
// acc[1] = x_hi;
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 8)
|
||||||
|
// rot32(x_lo, x_hi, (short)8, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 14)
|
||||||
|
// rot32(x_lo, x_hi, (short)14, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 22)
|
||||||
|
// rot32(x_lo, x_hi, (short)22, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// // acc ^= rot32(x, 30)
|
||||||
|
// rot32(x_lo, x_hi, (short)30, t);
|
||||||
|
// acc[0] ^= t[0];
|
||||||
|
// acc[1] ^= t[1];
|
||||||
|
//
|
||||||
|
// out[0] = acc[0];
|
||||||
|
// out[1] = acc[1];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /** 创建31位无符号整数 */
|
||||||
|
//// public static int makeU31(int a, int b, int c, int d) {
|
||||||
|
//// return (((a & 0xFF) << 23) |
|
||||||
|
//// ((b & 0xFF) << 16) |
|
||||||
|
//// ((c & 0xFF) << 8) |
|
||||||
|
//// (d & 0xFF)) & 0x7FFFFFFF;
|
||||||
|
//// }
|
||||||
|
// /** 创建31位无符号整数,结果放到 out[0]=lo, out[1]=hi(15位) */
|
||||||
|
// public static void makeU31(short a, short b, short c, short d, short[] out /*len==2*/) {
|
||||||
|
// // 四个字节
|
||||||
|
// short b0 = (short)(a & 0xFF); // 最高字节
|
||||||
|
// short b1 = (short)(b & 0xFF);
|
||||||
|
// short b2 = (short)(c & 0xFF);
|
||||||
|
// short b3 = (short)(d & 0xFF); // 最低字节
|
||||||
|
//
|
||||||
|
// // 拼成 32 位: b0<<24 | b1<<16 | b2<<8 | b3
|
||||||
|
// // lo = 低16位
|
||||||
|
// out[0] = (short)((b2 << 8) | b3);
|
||||||
|
//
|
||||||
|
// // hi = 高15位(丢弃 bit31)
|
||||||
|
// out[1] = (short)((b0 << 7) | b1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// /** 创建32位无符号整数 */
|
||||||
|
//// public static int makeU32(int a, int b, int c, int d) {
|
||||||
|
//// return ((a & 0xFF) << 24) |
|
||||||
|
//// ((b & 0xFF) << 16) |
|
||||||
|
//// ((c & 0xFF) << 8) |
|
||||||
|
//// (d & 0xFF);
|
||||||
|
//// }
|
||||||
|
// /** 创建32位无符号整数,结果放到 out[0]=lo, out[1]=hi */
|
||||||
|
// public static void makeU32(short a, short b, short c, short d, short[] out /*len==2*/) {
|
||||||
|
// // 四个字节
|
||||||
|
// short b0 = (short)(a & 0xFF); // 最高字节
|
||||||
|
// short b1 = (short)(b & 0xFF);
|
||||||
|
// short b2 = (short)(c & 0xFF);
|
||||||
|
// short b3 = (short)(d & 0xFF); // 最低字节
|
||||||
|
//
|
||||||
|
// // lo = 低16位
|
||||||
|
// out[0] = (short)((b2 << 8) | b3);
|
||||||
|
//
|
||||||
|
// // hi = 高16位
|
||||||
|
// out[1] = (short)((b0 << 8) | b1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// /** 提取IV */
|
||||||
|
// public static void extractIv(byte[] input25Byte, byte[] output23Byte) {
|
||||||
|
// if (input25Byte == null || output23Byte == null) return;
|
||||||
|
//
|
||||||
|
// // 复制前17字节
|
||||||
|
// Util.arrayCopyNonAtomic(input25Byte, (short)0, output23Byte, (short)0, (short)17);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 处理剩余8字节
|
||||||
|
// byte[] src = JCSystem.makeTransientByteArray((short)8, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
// for (short i = 0; i < 8; i++) {
|
||||||
|
// src[i] = (byte) (input25Byte[(short)(17 + i)] & 0x3F);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// output23Byte[17] = (byte) ((src[0] << 2) | (src[1] >>> 4));
|
||||||
|
// output23Byte[18] = (byte) (((src[1] & 0x0F) << 4) | (src[2] >>> 2));
|
||||||
|
// output23Byte[19] = (byte) (((src[2] & 0x03) << 6) | src[3]);
|
||||||
|
// output23Byte[20] = (byte) ((src[4] << 2) | (src[5] >>> 4));
|
||||||
|
// output23Byte[21] = (byte) (((src[5] & 0x0F) << 4) | (src[6] >>> 2));
|
||||||
|
// output23Byte[22] = (byte) (((src[6] & 0x03) << 6) | src[7]);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 32位加法: (a_hi:a_lo) + (b_hi:b_lo)
|
||||||
|
// * out[0] = lo, out[1] = hi
|
||||||
|
// */
|
||||||
|
// static void add32(short a_lo, short a_hi,
|
||||||
|
// short b_lo, short b_hi,
|
||||||
|
// short[] out /*len=2*/) {
|
||||||
|
//
|
||||||
|
// // ---- 低16位 ----
|
||||||
|
// short lo_low = (short)((a_lo & 0x00FF) + (b_lo & 0x00FF));
|
||||||
|
// short carry0 = (short)(((a_lo & 0x00FF) + (b_lo & 0x00FF)) >>> 8);
|
||||||
|
//
|
||||||
|
// short a_lo_hi = (short)((a_lo >>> 8) & 0x00FF);
|
||||||
|
// short b_lo_hi = (short)((b_lo >>> 8) & 0x00FF);
|
||||||
|
// short lo_high = (short)(a_lo_hi + b_lo_hi + carry0);
|
||||||
|
// short carry1 = (short)(lo_high >>> 8);
|
||||||
|
//
|
||||||
|
// short lo_res = (short)((lo_high << 8) | (lo_low & 0x00FF));
|
||||||
|
//
|
||||||
|
// // ---- 高16位 ----
|
||||||
|
// short hi_low = (short)((a_hi & 0x00FF) + (b_hi & 0x00FF) + carry1);
|
||||||
|
// short carry2 = (short)(hi_low >>> 8);
|
||||||
|
//
|
||||||
|
// short a_hi_hi = (short)((a_hi >>> 8) & 0x00FF);
|
||||||
|
// short b_hi_hi = (short)((b_hi >>> 8) & 0x00FF);
|
||||||
|
// short hi_high = (short)(a_hi_hi + b_hi_hi + carry2);
|
||||||
|
//
|
||||||
|
// short hi_res = (short)((hi_high << 8) | (hi_low & 0x00FF));
|
||||||
|
//
|
||||||
|
// // ---- 输出 ----
|
||||||
|
// out[0] = lo_res;
|
||||||
|
// out[1] = hi_res;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 32位加法 + 返回进位(只用 short)
|
||||||
|
// * 输入: (a_hi:a_lo) + (b_hi:b_lo)
|
||||||
|
// * 输出: out[0]=lo, out[1]=hi
|
||||||
|
// * 返回: 最终进位(0/1)
|
||||||
|
// */
|
||||||
|
// static short add32_with_carry(short a_lo, short a_hi,
|
||||||
|
// short b_lo, short b_hi,
|
||||||
|
// short[] out /* len=2 */) {
|
||||||
|
// // ---- 低16位:分两段8位相加 ----
|
||||||
|
// short s0 = (short)((a_lo & (short)0x00FF) + (b_lo & (short)0x00FF)); // 0..510
|
||||||
|
// short c0 = (short)(s0 >>> 8); // 0/1
|
||||||
|
// short s1 = (short)(((a_lo >>> 8) & (short)0x00FF)
|
||||||
|
// + ((b_lo >>> 8) & (short)0x00FF)
|
||||||
|
// + c0); // 0..511
|
||||||
|
// short c1 = (short)(s1 >>> 8); // 0/1
|
||||||
|
// short lo = (short)((s1 << 8) | (s0 & (short)0x00FF));
|
||||||
|
//
|
||||||
|
// // ---- 高16位:再分两段8位相加,并加上 c1 ----
|
||||||
|
// short s2 = (short)((a_hi & (short)0x00FF) + (b_hi & (short)0x00FF) + c1);
|
||||||
|
// short c2 = (short)(s2 >>> 8); // 0/1
|
||||||
|
// short s3 = (short)(((a_hi >>> 8) & (short)0x00FF)
|
||||||
|
// + ((b_hi >>> 8) & (short)0x00FF)
|
||||||
|
// + c2); // 0..511
|
||||||
|
// short c3 = (short)(s3 >>> 8); // 最终进位 0/1
|
||||||
|
// short hi = (short)((s3 << 8) | (s2 & (short)0x00FF));
|
||||||
|
//
|
||||||
|
// out[0] = lo;
|
||||||
|
// out[1] = hi;
|
||||||
|
// return (short)(c3 & 1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 64位加法: a4 + b4 -> a4
|
||||||
|
// * 输入输出: short[4],低到高 (a[0]=lo16, a[1]=hi16, a[2]=lo16 of high dword, a[3]=hi16 of high dword)
|
||||||
|
// */
|
||||||
|
// static void add64(short[] a, short[] b) {
|
||||||
|
// short[] tmp = JCSystem.makeTransientShortArray((short)2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
|
||||||
|
//
|
||||||
|
// // 低 32 位
|
||||||
|
// short carry = add32_with_carry(a[0], a[1], b[0], b[1], tmp);
|
||||||
|
// a[0] = tmp[0];
|
||||||
|
// a[1] = tmp[1];
|
||||||
|
//
|
||||||
|
// // 高 32 位 + carry
|
||||||
|
// add32((short)(a[2] + (short)(carry & (short)0x0001)), a[3], b[2], b[3], tmp);
|
||||||
|
// a[2] = tmp[0];
|
||||||
|
// a[3] = tmp[1];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 32位异或
|
||||||
|
// public static void xor32(short a_lo, short a_hi, short b_lo, short b_hi, short[] out /*len==2*/) {
|
||||||
|
// out[0] = (short)(a_lo ^ b_lo);
|
||||||
|
// out[1] = (short)(a_hi ^ b_hi);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 把32位数 b (b[0]=lo, b[1]=hi) 左移 k 位 (0 <= k < 32),
|
||||||
|
// * 结果放到64位数 a (a[0]=最低16位 ... a[3]=最高16位)。
|
||||||
|
// */
|
||||||
|
// static void create_64b_from_32b(short[] a/*len=4*/, short[] b/*len=2*/, short k) {
|
||||||
|
// short a0 = b[0], a1 = b[1], a2 = 0, a3 = 0;
|
||||||
|
//
|
||||||
|
// if (k >= 16) {
|
||||||
|
// a3 = a2; // 0
|
||||||
|
// a2 = a1; // 原 hi16
|
||||||
|
// a1 = a0; // 原 lo16
|
||||||
|
// a0 = 0;
|
||||||
|
// k = (short)(k - 16);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// while (k > 0) {
|
||||||
|
// short c0 = (short)((a0 >>> 15) & 1);
|
||||||
|
// short c1 = (short)((a1 >>> 15) & 1);
|
||||||
|
// short c2 = (short)((a2 >>> 15) & 1);
|
||||||
|
//
|
||||||
|
// a3 = (short)((a3 << 1) | c2);
|
||||||
|
// a2 = (short)((a2 << 1) | c1);
|
||||||
|
// a1 = (short)((a1 << 1) | c0);
|
||||||
|
// a0 = (short)(a0 << 1);
|
||||||
|
// k--;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// a[0] = a0; a[1] = a1; a[2] = a2; a[3] = a3;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * (A & 0x7FFFFFFF),结果放在 out[4],只保留低32位并清掉最高bit。
|
||||||
|
// */
|
||||||
|
// static void and64_7FFFFFFF_to32(short[] A, short[] out) {
|
||||||
|
// out[0] = A[0]; // lo16
|
||||||
|
// out[1] = (short)(A[1] & 0x7FFF); // hi16 (清除最高bit)
|
||||||
|
// out[2] = 0;
|
||||||
|
// out[3] = 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 64位无符号右移 31 位
|
||||||
|
// * 输入: A[0..3] (short[4], A[0]最低16位)
|
||||||
|
// * 输出: out[0..3]
|
||||||
|
// */
|
||||||
|
// static void shr64u_31(short[] A, short[] out) {
|
||||||
|
// // 先拼出 64bit 的逻辑,逐段右移
|
||||||
|
// // A >>> 31 = (A >>> 16) >>> 15
|
||||||
|
//
|
||||||
|
// // 先右移 16,相当于丢掉 A[0],整体右移一半字
|
||||||
|
// out[0] = A[1]; // 原 A[1] -> 新低16位
|
||||||
|
// out[1] = A[2]; // 原 A[2]
|
||||||
|
// out[2] = A[3]; // 原 A[3]
|
||||||
|
// out[3] = 0; // 高位补0
|
||||||
|
//
|
||||||
|
// // 再右移 15 位
|
||||||
|
// short c0 = (short)((out[0] & (short)0xFFFF) >>> 15); // out[0] 最后一位变进位
|
||||||
|
// short c1 = (short)((out[1] & (short)0xFFFF) >>> 15);
|
||||||
|
// short c2 = (short)((out[2] & (short)0xFFFF) >>> 15);
|
||||||
|
//
|
||||||
|
// out[0] = (short)((c0 & 0x0001) | (out[1] << 1));
|
||||||
|
// out[1] = (short)((c1 & 0x0001) | (out[2] << 1));
|
||||||
|
// out[2] = (short)(c2 & 0x0001);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 32位无符号右移 1 位
|
||||||
|
// * 输入: lo,hi (short) 表示 32 位数 (hi:高16位, lo:低16位)
|
||||||
|
// * 输出: out[0]=lo, out[1]=hi
|
||||||
|
// */
|
||||||
|
// static void shr32u1(short lo, short hi, short[] out) {
|
||||||
|
// // >>>1:先处理低16位
|
||||||
|
// short nwLo = (short)(((((lo & (short)0xFFFF) >>> 1) & (short)0x7FFF)) | ((hi & 0x0001) << 15));
|
||||||
|
// short nwHi = (short)(((hi & (short)0xFFFF) >>> 1) & (short)0x7FFF);
|
||||||
|
//
|
||||||
|
// out[0] = nwLo;
|
||||||
|
// out[1] = nwHi;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// /** 打印/*十六进制(调试用,TODO 生产/JC 环境可移除) *//*
|
||||||
|
// public static void printHex(String label, byte[] data, int len) {
|
||||||
|
// System.out.print(label + ": ");
|
||||||
|
// for (int i = 0; i < len; i++) {
|
||||||
|
// System.out.printf("%02x ", data[i] & 0xFF);
|
||||||
|
// }
|
||||||
|
// System.out.println();
|
||||||
|
// }*/
|
||||||
|
//}
|
||||||
BIN
build_tools/Project/bin/com/cscn/javacard/cscn.cap
Normal file
BIN
build_tools/Project/bin/com/cscn/javacard/cscn.cap
Normal file
Binary file not shown.
BIN
build_tools/Project/bin/com/cscn/javacard/cscn.exp
Normal file
BIN
build_tools/Project/bin/com/cscn/javacard/cscn.exp
Normal file
Binary file not shown.
0
.idea/.gitignore → build_tools/Tools/ext_api/gp221/.idea/.gitignore
generated
vendored
0
.idea/.gitignore → build_tools/Tools/ext_api/gp221/.idea/.gitignore
generated
vendored
6
build_tools/Tools/ext_api/gp221/.idea/misc.xml
generated
Normal file
6
build_tools/Tools/ext_api/gp221/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
build_tools/Tools/ext_api/gp221/.idea/modules.xml
generated
Normal file
8
build_tools/Tools/ext_api/gp221/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/gp221.iml" filepath="$PROJECT_DIR$/gp221.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
10
build_tools/Tools/ext_api/gp221/.idea/runConfigurations.xml
generated
Normal file
10
build_tools/Tools/ext_api/gp221/.idea/runConfigurations.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
3
build_tools/Tools/ext_api/gp221/META-INF/MANIFEST.MF
Normal file
3
build_tools/Tools/ext_api/gp221/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Created-By: 1.6.0_30 (Sun Microsystems Inc.)
|
||||||
|
|
||||||
11
build_tools/Tools/ext_api/gp221/gp221.iml
Normal file
11
build_tools/Tools/ext_api/gp221/gp221.iml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines a method through which an Application may forward
|
||||||
|
* input data to another Application.<p>
|
||||||
|
*
|
||||||
|
* This interface shall be implemented by an Application that wishes to receive
|
||||||
|
* personalization data forwarded by its associated Security Domain. In such a
|
||||||
|
* scenario, if the Application implements both the {@link Application} and the
|
||||||
|
* {@link Personalization} interface, then the Security Domain shall use the
|
||||||
|
* {@link Personalization} interface. <p>
|
||||||
|
*
|
||||||
|
* @see Personalization
|
||||||
|
*
|
||||||
|
* @since export file version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface Application extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Processes application specific data received from another on-card entity.<p>
|
||||||
|
*
|
||||||
|
* If the Application invoking this method is a Security Domain then it shall
|
||||||
|
* be assumed that:<ul>
|
||||||
|
*
|
||||||
|
* <li>The <code>baBuffer</code> byte array is a <em>global</em> byte array;
|
||||||
|
*
|
||||||
|
* <li>The data forwarded by the Security Domain is a STORE DATA command. The
|
||||||
|
* <code>sOffset</code> parameter locates the class byte of the command and
|
||||||
|
* the <code>sLength</code> parameter indicates the length of the entire
|
||||||
|
* command (i.e. header + data field).
|
||||||
|
*
|
||||||
|
* <li>Any exception thrown by this method will be rethrown by the Security
|
||||||
|
* Domain, hence will be converted to and returned as a response status word
|
||||||
|
* to the off-card entity. If the exception is an {@link ISOException}, then
|
||||||
|
* the status word will be the reason code of that exception. Otherwise, a
|
||||||
|
* status word of '6F00' will be returned.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>Upon invocation of this method, the Java Card VM performs a
|
||||||
|
* context switch.</em>
|
||||||
|
*
|
||||||
|
* <li><em>As the Application is not the currently selected Application, it
|
||||||
|
* should not attempt to access transient memory of type
|
||||||
|
* <code>CLEAR_ON_DESELECT</code> during the processing of this method.</em>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is responsible for managing the atomic
|
||||||
|
* modification of its own data, if needed.</em>
|
||||||
|
*
|
||||||
|
* <li><em>As this method may be invoked by a Security Domain immaterial of
|
||||||
|
* the Application's internal state, the Application is responsible for
|
||||||
|
* ensuring that its internal state is valid for this operation.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing input data. Must be a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @param sOffset offset of input data within <code>baBuffer</code>.
|
||||||
|
* @param sLength length of input data.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading input data would
|
||||||
|
* cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public abstract void processData(byte[] baBuffer, short sOffset, short sLength);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.Shareable;
|
||||||
|
import javacard.security.CryptoException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface allows performing operations such as recovering a
|
||||||
|
* cryptographic key or signing data. The required algorithms and credentials
|
||||||
|
* are known implicitly.<p>
|
||||||
|
*
|
||||||
|
* It is intended that Security Domains would be able to access an {@link
|
||||||
|
* Authority} instance through a Global Service by a Controlling Authority
|
||||||
|
* Security Domain (CASD) with a service name of <code>({@link
|
||||||
|
* GPSystem#FAMILY_AUTHORITY}<<8|0x00)</code>.<p>
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.2: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface Authority extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used with {@link #init} method to indicate signing mode.
|
||||||
|
*/
|
||||||
|
public final byte MODE_SIGN=1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with {@link #init} method to indicate key recovery mode.
|
||||||
|
*/
|
||||||
|
public final byte MODE_KEY_RECOVERY=2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the Authority interface with the appropriate mode (<code>MODE_SIGN</code> or <code>MODE_KEY_RECOVERY</code>).
|
||||||
|
*
|
||||||
|
* @param theMode one of {@link #MODE_SIGN} or {@link #MODE_KEY_RECOVERY}.
|
||||||
|
*
|
||||||
|
* @exception CryptoException with the following reason code:<ul>
|
||||||
|
* <li><code>ILLEGUAL_VALUE</code> if theMode option is an undefined
|
||||||
|
* value.</ul>
|
||||||
|
*/
|
||||||
|
public void init(byte theMode) throws CryptoException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the signature of all/last input data.
|
||||||
|
* A call to this method resets this Authority interface to the state it was
|
||||||
|
* in when previously initialized via a call to init().
|
||||||
|
* That is, the object is reset and available to sign another message.
|
||||||
|
* The input and output buffer may overlap and shall be <em>global</em> arrays.
|
||||||
|
*
|
||||||
|
* @param inBuff the input buffer of data to be signed
|
||||||
|
* @param inOffset the offset in input buffer at which the signature starts
|
||||||
|
* @param inLength the byte length to sign
|
||||||
|
* @param sigBuff the output buffer to store signature data
|
||||||
|
* @param sigOffset the offset into sigBuff at which to begin signature generation
|
||||||
|
*
|
||||||
|
* @return the number of bytes of signature output in sigBuff
|
||||||
|
*
|
||||||
|
* @throws CryptoException with the following reason codes:<ul>
|
||||||
|
* <li><code>INVALID_INIT</code> if this Authority interface is not initialized or
|
||||||
|
* initialized in <code>MODE_KEY_RECOVERY</code> mode.
|
||||||
|
* <li><code>ILLEGAL_USE</code> if this Authority algorithm does not pad the message and
|
||||||
|
* the message is not block aligned.</ul>
|
||||||
|
* @throws SecurityException if the inBuff or sigBuff are not <em>global</em> arrays.
|
||||||
|
*/
|
||||||
|
public short sign(byte[] inBuff,
|
||||||
|
short inOffset,
|
||||||
|
short inLength,
|
||||||
|
byte[] sigBuff,
|
||||||
|
short sigOffset)
|
||||||
|
throws CryptoException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accumulates input data. for the current operation (<code>MODE_SIGN</code> or <code>MODE_KEY_RECOVERY</code>).
|
||||||
|
* <p>
|
||||||
|
* When this method is used, temporary storage of intermediate results is required.
|
||||||
|
* This method should only be used if all the input data required for the current operation
|
||||||
|
* is not available in one byte array.
|
||||||
|
* The <code>sign</code> or <code>recoverKey</code> methods are recommended whenever possible.
|
||||||
|
* The inBuff shall be <em>global</em> array.
|
||||||
|
*
|
||||||
|
* @param inBuff buffer containing input data
|
||||||
|
* @param inOffset offset of input data
|
||||||
|
* @param inLength length of input data
|
||||||
|
* @throws CryptoException with the following reason codes:<ul>
|
||||||
|
* <li><code>INVALID_INIT</code> if this Authority interface is not initialized.</ul>
|
||||||
|
* @throws SecurityException if the inBuff is not <em>global</em> array.
|
||||||
|
*/
|
||||||
|
public void update(byte[] inBuff,
|
||||||
|
short inOffset,
|
||||||
|
short inLength)
|
||||||
|
throws CryptoException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recovers a cryptographic key from a set of data
|
||||||
|
* structures provided in the input buffer (inBuff).
|
||||||
|
* As a mandatory step, the recovery mechanism includes the verification of
|
||||||
|
* the origin and integrity of the recovered key.
|
||||||
|
* This method knows, from the set of data structures present in the input
|
||||||
|
* buffer, which recovery mechanism is to be used.
|
||||||
|
* The recovered key is written in the ouput buffer (outBuff) at specified
|
||||||
|
* offset (outOffset), in the form of a key data structure whose format
|
||||||
|
* depends on the type of the key.
|
||||||
|
* A call to this method resets this instance of the Authority interface to
|
||||||
|
* the state it was in when previously initialized via a call to init().
|
||||||
|
* That is, the object is reset and available to recover another key.
|
||||||
|
* The input and output buffers may overlap and shall be <em>global</em> arrays.
|
||||||
|
*
|
||||||
|
* @param inBuff containing input data.
|
||||||
|
* @param inOffset offset of input data.
|
||||||
|
* @param inLength length of input data.
|
||||||
|
* @param outBuff the buffer where recovered key data structure shall be written
|
||||||
|
* @param outOffset offset where recovered key data structure shall be written
|
||||||
|
* @return <code>Length</code> of the recovered key data structure written
|
||||||
|
* in outBuff at outOffset,or 0 if the recovery mechanism failed
|
||||||
|
* (e.g. recovered key was considered invalid).
|
||||||
|
*
|
||||||
|
* @throws CryptoException - with the following reason codes:<ul>
|
||||||
|
* <li><code>INVALID_INIT</code> if this Authority interface is not initialized or
|
||||||
|
* initialized in <code>MODE_SIGN</code> mode.</ul>
|
||||||
|
* @throws SecurityException if the inBuff or outBuff are not <em>global</em> arrays.
|
||||||
|
*/
|
||||||
|
public short recoverKey(byte[] inBuff,
|
||||||
|
short inOffset,
|
||||||
|
short inLength,
|
||||||
|
byte[] outBuff,
|
||||||
|
short outOffset)
|
||||||
|
throws CryptoException;
|
||||||
|
|
||||||
|
}
|
||||||
343
build_tools/Tools/ext_api/gp221/org/globalplatform/CVM.java
Normal file
343
build_tools/Tools/ext_api/gp221/org/globalplatform/CVM.java
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines basic Cardholder Verification Method services
|
||||||
|
* (e.g. comparison of CVM value, CVM state query). It is typically exposed to
|
||||||
|
* on-card Applications by a Global Services Application implementing one or
|
||||||
|
* more Cardholder Verification Methods. Some services are restricted to
|
||||||
|
* Applications having the CVM Management Privilege.<p>
|
||||||
|
*
|
||||||
|
* To retrieve an instance of this interface, an Application shall invoke the
|
||||||
|
* {@link GPSystem#getCVM} method, or shall use a {@link GlobalService} instance
|
||||||
|
* of the {@link GPSystem#FAMILY_CVM} family. For backward compatibility, the
|
||||||
|
* {@link CVM} instances retrieved using the {@link GPSystem#getCVM} method are
|
||||||
|
* mapped onto those retrieved as Global Services of the {@link
|
||||||
|
* GPSystem#FAMILY_CVM} family.<p>
|
||||||
|
*
|
||||||
|
* The CVM instance maintains the following data (see Card Specification v2.2.1
|
||||||
|
* section 8.2.2 for more details):<ul>
|
||||||
|
*
|
||||||
|
* <li>CVM state: ACTIVE, INVALID_SUBMISSION, VALIDATED or BLOCKED. In addition,
|
||||||
|
* we distinguish the case where the CVM instance is not fully initialized
|
||||||
|
* (i.e. either the CVM value or the CVM try limit has not been set) and has
|
||||||
|
* never entered the state ACTIVE.
|
||||||
|
*
|
||||||
|
* <li>CVM try limit: the maximum value of the CVM try counter.
|
||||||
|
*
|
||||||
|
* <li>CVM try counter: the number of unsuccessful comparisons of the CVM value
|
||||||
|
* that may be performed before this CVM instance gets blocked.
|
||||||
|
*
|
||||||
|
* <li>CVM value: the secret value held by this CVM instance, stored in ASCII,
|
||||||
|
* BCD or HEX format.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Operations performed by this interface shall be independent of, and not
|
||||||
|
* interfere with, any transaction in progress (e.g. if the {@link #verify}
|
||||||
|
* method is invoked from within a transaction and this transaction is aborted,
|
||||||
|
* then the try counter is not revert to its original value).<p>
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.0: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface CVM extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The CVM value comparison was successful.
|
||||||
|
*/
|
||||||
|
public static final short CVM_SUCCESS = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CVM value comparison failed.
|
||||||
|
*/
|
||||||
|
public static final short CVM_FAILURE = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CVM value is formatted as ASCII bytes.<p>
|
||||||
|
*
|
||||||
|
* Note:<ul> <li><em>If the CVM value is stored in a format other than ASCII,
|
||||||
|
* it is the responsibility of the interface to convert to the expected
|
||||||
|
* format.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte FORMAT_ASCII = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CVM value is formatted as numerical digits, coded on a nibble (4 bits)
|
||||||
|
* and left justified.<p>
|
||||||
|
*
|
||||||
|
* Note:<ul> <li><em>If the CVM value is stored in a format other than BCD,
|
||||||
|
* it is the responsibility of the interface to convert to the expected
|
||||||
|
* format.</em>
|
||||||
|
* <li><em>If the length of the CVM value is odd, the right most nibble of
|
||||||
|
* the CVM value shall be high values ('F').</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte FORMAT_BCD = (byte) 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CVM value is formatted as hexadecimal (binary) data.<p>
|
||||||
|
*
|
||||||
|
* Note:<ul> <li><em>If the CVM value is stored in a format other than HEX,
|
||||||
|
* it is the responsibility of the interface to convert to the expected
|
||||||
|
* format.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte FORMAT_HEX = (byte) 0x03;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this CVM instance is active, that is, whether it has
|
||||||
|
* been fully initialized (i.e. both value and try limit) and is ready
|
||||||
|
* for use. If yes, then the CVM state is deemed to be in one of the
|
||||||
|
* following states: ACTIVE, INVALID_SUBMISSION, VALIDATED or BLOCKED.<p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM has been fully initialized and is
|
||||||
|
* ready for use, <code>false</code> otherwise (i.e. the CVM state is NOT_READY).
|
||||||
|
*/
|
||||||
|
public boolean isActive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether an attempt has been made to compare the CVM value, that
|
||||||
|
* is, whether the CVM state is INVALID_SUBMISSION or VALIDATED.<p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM state is INVALID_SUBMISSION or
|
||||||
|
* VALIDATED, <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isSubmitted();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether a successful comparison of the CVM value has occurred,
|
||||||
|
* that is, whether the CVM state is VALIDATED.<p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM state is VALIDATED,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isVerified();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this CVM instance is blocked, that is, whether the CVM
|
||||||
|
* state is BLOCKED.<p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM state is BLOCKED, <code>false</code>
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isBlocked();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CVM try counter, that is, the number of unsuccessful comparisons
|
||||||
|
* of the CVM value that may be performed before this CVM instance gets
|
||||||
|
* blocked.<p>
|
||||||
|
*
|
||||||
|
* @return current value of the CVM try counter.
|
||||||
|
*/
|
||||||
|
public byte getTriesRemaining();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the CVM value.<p>
|
||||||
|
*
|
||||||
|
* If the Application invoking this method does not have the CVM Management
|
||||||
|
* Privilege, or if the specified format (<code>bFormat</code>) is unknown
|
||||||
|
* (or not supported by this CVM instance), or if the new CVM value is not
|
||||||
|
* consistent with respect to the specified format, then the CVM value is not
|
||||||
|
* updated.<p>
|
||||||
|
*
|
||||||
|
* If the CVM value is successfully updated and the CVM try limit has already
|
||||||
|
* been successfully set previously, then this method also resets the CVM try
|
||||||
|
* counter to the CVM try limit, and (re)sets the CVM state to ACTIVE.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>If the Global Service Application providing this CVM instance has
|
||||||
|
* the Global Registry Privilege, it is able to check that the Application
|
||||||
|
* invoking this method has the CVM Management Privilege using the {@link
|
||||||
|
* GPRegistryEntry} interface;</em>
|
||||||
|
*
|
||||||
|
* <li><em>The CVM instance shall record the format, length, and value of the
|
||||||
|
* CVM value.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the new CVM value. Must be a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @param sOffset offset of the new CVM value within <code>baBuffer</code>.
|
||||||
|
* @param bLength length of the new CVM value.
|
||||||
|
* @param bFormat format of the new CVM value: {@link #FORMAT_ASCII}, {@link
|
||||||
|
* #FORMAT_BCD} or {@link #FORMAT_HEX}.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM value was successfully updated,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*
|
||||||
|
* @see GPRegistryEntry#PRIVILEGE_CVM_MANAGEMENT
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading the new CVM value
|
||||||
|
* would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public boolean update(byte[] baBuffer, short sOffset, byte bLength, byte bFormat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the CVM state to ACTIVE.<p>
|
||||||
|
*
|
||||||
|
* The CVM state can only be reset to ACTIVE from the states ACTIVE,
|
||||||
|
* INVALID_SUBMISSION or VALIDATED. In particular, it cannot be reset to
|
||||||
|
* ACTIVE if it is in state BLOCKED or if the CVM instance never entered the
|
||||||
|
* state ACTIVE, that is, if the CVM instance is not fully
|
||||||
|
* initialized.<p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM state was reset, <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean resetState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the CVM state to BLOCKED.<p>
|
||||||
|
*
|
||||||
|
* If the Application invoking this method does not have the CVM Management
|
||||||
|
* Privilege, then the CVM state is not updated.<p>
|
||||||
|
*
|
||||||
|
* The CVM state can only be set to BLOCKED if the CVM instance already
|
||||||
|
* entered the state ACTIVE once, that is, if the CVM instance is fully
|
||||||
|
* initialized. Notice that this method shall return <code>true</code> if the
|
||||||
|
* CVM state is already BLOCKED. <p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
* <li><em>If the Global Service Application providing this CVM instance has
|
||||||
|
* the Global Registry Privilege, it is able to check that the Application
|
||||||
|
* invoking this method has the CVM Management Privilege using the {@link
|
||||||
|
* GPRegistryEntry} interface;</em>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM state was set to BLOCKED,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*
|
||||||
|
* @see GPRegistryEntry#PRIVILEGE_CVM_MANAGEMENT
|
||||||
|
*/
|
||||||
|
public boolean blockState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the CVM state to ACTIVE, even if it is currently BLOCKED.<p>
|
||||||
|
*
|
||||||
|
* If the Application invoking this method does not have the CVM Management
|
||||||
|
* Privilege, then the CVM state is not updated.<p>
|
||||||
|
*
|
||||||
|
* The CVM state can only be set to ACTIVE if the CVM instance already
|
||||||
|
* entered the state ACTIVE once, that is, if the CVM instance is fully
|
||||||
|
* initialized.
|
||||||
|
*
|
||||||
|
* If the CVM state is successfully reset, then this method also resets the
|
||||||
|
* CVM try counter to the CVM try limit.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
* <li><em>If the Global Service Application providing this CVM instance has
|
||||||
|
* the Global Registry Privilege, it is able to check that the Application
|
||||||
|
* invoking this method has the CVM Management Privilege using the {@link
|
||||||
|
* GPRegistryEntry} interface;</em>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the CVM state was reset to ACTIVE,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*
|
||||||
|
* @see GPRegistryEntry#PRIVILEGE_CVM_MANAGEMENT
|
||||||
|
*/
|
||||||
|
public boolean resetAndUnblockState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the CVM try limit, that is, the maximum value of the CVM try
|
||||||
|
* counter.<p>
|
||||||
|
*
|
||||||
|
* If the Application invoking this method does not have the CVM Management
|
||||||
|
* Privilege, then the CVM try limit is not set.<p>
|
||||||
|
*
|
||||||
|
* If the CVM try limit is successfully set, then this method also resets the
|
||||||
|
* CVM try counter to the new CVM try limit. If the CVM value has already
|
||||||
|
* been successfully set previously, then this method also (re)sets the CVM
|
||||||
|
* state to ACTIVE.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
* <li><em>If the Global Service Application providing this CVM instance has
|
||||||
|
* the Global Registry Privilege, it is able to check that the Application
|
||||||
|
* invoking this method has the CVM Management Privilege using the {@link
|
||||||
|
* GPRegistryEntry} interface;</em>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param bTryLimit the maximum number of tries for the CVM.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the try limit was set, <code>false</code>
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @see GPRegistryEntry#PRIVILEGE_CVM_MANAGEMENT
|
||||||
|
*/
|
||||||
|
public boolean setTryLimit(byte bTryLimit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares a value with the stored CVM value.<p>
|
||||||
|
*
|
||||||
|
* If the CVM state is BLOCKED, or if the submitted format
|
||||||
|
* (<code>bFormat</code>) is unknown (or not supported by this CVM instance),
|
||||||
|
* or if this method throws a {@link NullPointerException} or an {@link
|
||||||
|
* ArrayIndexOutOfBoundsException}, then the comparison is deemed
|
||||||
|
* unsuccessful.<p>
|
||||||
|
*
|
||||||
|
* If the submitted CVM value is not in the same format as the stored CVM
|
||||||
|
* value, then format conversion shall occur according to the following rules
|
||||||
|
* prior to comparing values:<ul>
|
||||||
|
*
|
||||||
|
* <li>If HEX format is submitted and the stored CVM value is in ASCII or BCD
|
||||||
|
* format, then the conversion cannot occur and the comparison is deemed
|
||||||
|
* unsuccessful;
|
||||||
|
*
|
||||||
|
* <li>If BCD or ASCII format is submitted and the stored CVM value is in HEX
|
||||||
|
* format, then the conversion cannot occur and the comparison is deemed
|
||||||
|
* unsuccessful;
|
||||||
|
*
|
||||||
|
* <li>If ASCII format is submitted and the stored CVM value is in BCD
|
||||||
|
* format, then conversion can occur if the submitted CVM value only contains
|
||||||
|
* numerical ASCII characters: the numeric characters (coded on one byte) of
|
||||||
|
* the submitted value are converted to numeric nibbles, padded together in
|
||||||
|
* bytes, and a padding nibble 'F' is added on the right if necessary.
|
||||||
|
* Otherwise, the conversion cannot occur and the comparison is deemed
|
||||||
|
* unsuccessful;
|
||||||
|
*
|
||||||
|
* <li>If BCD format is submitted and the stored CVM value is in ASCII
|
||||||
|
* format, then conversion can occur if the stored CVM value only contains
|
||||||
|
* numerical ASCII characters: the numeric nibbles of the submitted value are
|
||||||
|
* expanded to the corresponding characters coded on one byte and the padding
|
||||||
|
* nibble 'F' is deleted (if present). Otherwise, the conversion cannot occur
|
||||||
|
* and the comparison is deemed unsuccessful; </ul>
|
||||||
|
*
|
||||||
|
* If the comparison is unsuccessful and the CVM state is not BLOCKED, then
|
||||||
|
* the CVM try counter must be decremented (by 1). In this case, if the CVM
|
||||||
|
* try counter reaches a value of '0' then the CVM state shall be set to
|
||||||
|
* BLOCKED, otherwise the CVM state shall be set to INVALID_SUBMISSION.<p>
|
||||||
|
*
|
||||||
|
* If the comparison is successful, then the CVM try counter shall be reset
|
||||||
|
* to the CVM try limit and the CVM state shall be set to VALIDATED.<p>
|
||||||
|
*
|
||||||
|
* The CVM try counter and the CVM state shall not conform to a transaction
|
||||||
|
* in progress, i.e. they shall not revert to a previous value if a
|
||||||
|
* transaction in progress is aborted.<p>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the submitted CVM value. Must be a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @param sOffset offset of the submitted CVM value within <code>baBuffer</code>.
|
||||||
|
* @param bLength length of the submitted CVM value.
|
||||||
|
* @param bFormat format of the submitted CVM value: {@link #FORMAT_ASCII},
|
||||||
|
* {@link #FORMAT_BCD} or {@link #FORMAT_HEX}.
|
||||||
|
*
|
||||||
|
* @return {@link #CVM_SUCCESS} if the comparison was successful, {@link
|
||||||
|
* #CVM_FAILURE} otherwise.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading the submitted CVM
|
||||||
|
* value would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short verify(byte[] baBuffer, short sOffset, byte bLength, byte bFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface allows querying and potentially modifying the registry data of
|
||||||
|
* an Application registered within the GlobalPlatform Registry.<p>
|
||||||
|
*
|
||||||
|
* Every {@link GPRegistryEntry} instance to an Application registered within
|
||||||
|
* the GlobalPlatform Registry.<p>
|
||||||
|
*
|
||||||
|
* To retrieve an instance of this interface, an Application shall invoke the
|
||||||
|
* {@link GPSystem#getRegistryEntry} method.<p>
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.1: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface GPRegistryEntry extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Privilege indicating Authorized Management (0x09).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_AUTHORIZED_MANAGEMENT = (byte) 0x09;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Card Lock (0x03).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_CARD_LOCK = (byte) 0x03;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Card Reset (0x05).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_CARD_RESET = (byte) 0x05;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Card Terminate (0x04).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_CARD_TERMINATE = (byte) 0x04;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating CVM Management (0x06).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_CVM_MANAGEMENT = (byte) 0x06;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating DAP verification (0x01).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_DAP_VERIFICATION = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Delegated Management (0x02).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_DELEGATED_MANAGEMENT = (byte) 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Final Application (0x0E).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_FINAL_APPLICATION = (byte) 0x0E;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Global Delete (0x0B).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_GLOBAL_DELETE = (byte) 0x0B;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Global Lock (0x0C).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_GLOBAL_LOCK = (byte) 0x0C;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Global Registry (0x0D).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_GLOBAL_REGISTRY = (byte) 0x0D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Global Service (0x0F).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_GLOBAL_SERVICE = (byte) 0x0F;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Mandated DAP verification privilege (0x07).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_MANDATED_DAP = (byte) 0x07;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Receipt Generation (0x10).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_RECEIPT_GENERATION = (byte) 0x10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating application is a Security Domain (0x00).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_SECURITY_DOMAIN = (byte) 0x00;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Token Verification (0x0A).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_TOKEN_VERIFICATION = (byte) 0x0A;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Trusted Path (0x08).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_TRUSTED_PATH = (byte) 0x08;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privilege indicating Ciphered Load File Data Block (0x11).
|
||||||
|
*/
|
||||||
|
public static final byte PRIVILEGE_CIPHERED_LOAD_FILE_DATA_BLOCK = (byte) 0x11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deregisters a service name.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall check that the Application invoking this method corresponds
|
||||||
|
* to <code>this</code> entry, that it has the Global Service Privilege, and
|
||||||
|
* that the specified service name was previously uniquely registered by that
|
||||||
|
* same Application. If not, this method shall throw an exception (see
|
||||||
|
* below).<p>
|
||||||
|
*
|
||||||
|
* @param sServiceName the service name that shall be deregistered.<p>
|
||||||
|
*
|
||||||
|
* A service name is encoded on 2 bytes, the 1st byte identifying a family of
|
||||||
|
* services and the 2nd byte identifying a service within that family.<p>
|
||||||
|
*
|
||||||
|
* The {@link GPSystem} class defines a set of constants
|
||||||
|
* <code>FAMILY_XXX</code> (of the <code>byte</code> type) that may be used to
|
||||||
|
* build a service name (of the <code>short</code> type) suitable to invoke
|
||||||
|
* this method as shown in the following examples:<ul>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link GPSystem#FAMILY_CVM}<<8)|0x11)</code>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link GPSystem#FAMILY_HTTP_ADMINISTRATION}<<8)|0x00)</code>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception ISOException if this method is not supported or if the service
|
||||||
|
* name was not found or if the conditions allowing to deregister the service
|
||||||
|
* name are not satisfied.
|
||||||
|
*
|
||||||
|
* @see #registerService
|
||||||
|
* @see GPSystem#FAMILY_CVM
|
||||||
|
* @see GPSystem#FAMILY_SECURE_CHANNEL
|
||||||
|
* @see GPSystem#FAMILY_USSM
|
||||||
|
* @see GPSystem#FAMILY_AUTHORITY
|
||||||
|
* @see GPSystem#FAMILY_HTTP_ADMINISTRATION
|
||||||
|
* @see GPSystem#FAMILY_HTTP_REPORT
|
||||||
|
*/
|
||||||
|
public void deregisterService(short sServiceName) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the AID of the Application corresponding to <code>this</code> entry.
|
||||||
|
*
|
||||||
|
* @return {@link AID} instance identifying the Application corresponding to
|
||||||
|
* <code>this</code> entry.
|
||||||
|
*/
|
||||||
|
public AID getAID();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Privilege Bytes of the Application corresponding to
|
||||||
|
* <code>this</code> entry.
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array where Privileges Bytes shall be written.
|
||||||
|
* @param sOffset offset within <code>baBuffer</code> where Privileges Bytes
|
||||||
|
* shall be written.
|
||||||
|
*
|
||||||
|
* @return <code>sOffset</code> + number of Privilege Bytes written to
|
||||||
|
* <code>baBuffer</code>.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not accessible in
|
||||||
|
* the caller's context e.g. <code>baBuffer</code> is not a <em>global</em>
|
||||||
|
* array nor an array belonging to the caller context.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if writing Privileges Bytes would
|
||||||
|
* cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short getPrivileges(byte[] baBuffer, short sOffset) throws ArrayIndexOutOfBoundsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Life Cycle State of the Application corresponding to
|
||||||
|
* <code>this</code> entry.
|
||||||
|
*
|
||||||
|
* @return the Life Cycle State of the Application corresponding to
|
||||||
|
* <code>this</code> entry.
|
||||||
|
*/
|
||||||
|
public byte getState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the Application corresponding to <code>this</code> entry is
|
||||||
|
* associated with the specified Security Domain.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall check that the specified <code>sdAID</code> indeed
|
||||||
|
* identifies a Security Domain present on the card, and check that the
|
||||||
|
* Application corresponding to <code>this</code> entry is associated with
|
||||||
|
* this Security Domain. If not, this method shall return
|
||||||
|
* <code>false</code>.<p>
|
||||||
|
*
|
||||||
|
* @param sdAID AID of a Security Domain.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the Application corresponding to
|
||||||
|
* <code>this</code> entry is associated with the specified Security Domain,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isAssociated(AID sdAID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the Application corresponding to <code>this</code> entry has
|
||||||
|
* the specified privilege.<p>
|
||||||
|
*
|
||||||
|
* If the specified privilege is unknown, this method shall return
|
||||||
|
* <code>false</code>.
|
||||||
|
*
|
||||||
|
* @param bPrivilege the privilege number to check, i.e. one of the
|
||||||
|
* <code>PRIVILEGE_XXX</code> constants.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the Application corresponding to
|
||||||
|
* <code>this</code> entry has the specified privilege, <code>false</code>
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isPrivileged(byte bPrivilege);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a service name identifying a service provided by the Application
|
||||||
|
* corresponding to <code>this</code> entry.<p>
|
||||||
|
*
|
||||||
|
* The specified service name (<code>sServiceName</code>) shall be unique
|
||||||
|
* among all the service names previously registered in the GlobalPlatform
|
||||||
|
* Registry using this method. Following successful invocation of this method,
|
||||||
|
* this service name is known to be uniquely registered: no other Application
|
||||||
|
* on the card will be able to register the same service name (until this
|
||||||
|
* service name is deregistered (see {@link #deregisterService})). If the
|
||||||
|
* service name identifies a family of service, no other Application on the
|
||||||
|
* card will be able to register a service of that family.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall first check that the Application invoking this method
|
||||||
|
* corresponds to <code>this</code> entry and that it has the Global Service
|
||||||
|
* Privilege.<p>
|
||||||
|
*
|
||||||
|
* Then the OPEN shall check that the specified service name:<ul>
|
||||||
|
*
|
||||||
|
* <li>is not already uniquely registered in the GlobalPlatform Registry; if
|
||||||
|
* the service name identifies an entire family of services, then the OPEN
|
||||||
|
* shall check that no service name of that family is registered.
|
||||||
|
*
|
||||||
|
* <li>was previously recorded for the Application corresponding to
|
||||||
|
* <code>this</code> entry (i.e. specified as part of System Install
|
||||||
|
* Parameters in the INSTALL command).
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* If any of the above conditions is not satisfied, this method shall throw an
|
||||||
|
* exception (see below). Otherwise, the specified service name shall be
|
||||||
|
* uniquely registered in the GlobalPlatform Registry.<p>
|
||||||
|
*
|
||||||
|
* @param sServiceName the service name that shall be uniquely registered.<p>
|
||||||
|
*
|
||||||
|
* A service name is encoded on 2 bytes, the 1st byte identifying a family of
|
||||||
|
* services and the 2nd byte identifying a service within that family. If the
|
||||||
|
* 2nd byte is set to <code>0x00</code>, the caller of this method is
|
||||||
|
* registering an entire family of service.<p>
|
||||||
|
*
|
||||||
|
* The {@link GPSystem} class defines a set of constants
|
||||||
|
* <code>FAMILY_XXX</code> (of the <code>byte</code> type) that may be used to
|
||||||
|
* build a service name (of the <code>short</code> type) suitable to invoke
|
||||||
|
* this method as shown in the following examples:<ul>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link GPSystem#FAMILY_CVM}<<8)|0x11)</code>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link GPSystem#FAMILY_HTTP_ADMINISTRATION}<<8)|0x00)</code>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception ISOException if this method is not supported or if the
|
||||||
|
* conditions allowing to register the service name are not satisfied.
|
||||||
|
*
|
||||||
|
* @see #deregisterService
|
||||||
|
* @see GPSystem#getService
|
||||||
|
* @see GPSystem#FAMILY_CVM
|
||||||
|
* @see GPSystem#FAMILY_SECURE_CHANNEL
|
||||||
|
* @see GPSystem#FAMILY_USSM
|
||||||
|
* @see GPSystem#FAMILY_AUTHORITY
|
||||||
|
* @see GPSystem#FAMILY_HTTP_ADMINISTRATION
|
||||||
|
* @see GPSystem#FAMILY_HTTP_REPORT
|
||||||
|
*/
|
||||||
|
public void registerService(short sServiceName) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Life Cycle state of the Application corresponding to
|
||||||
|
* <code>this</code> entry.<p>
|
||||||
|
*
|
||||||
|
* This method enforces the Life Cycle State transition rules described in
|
||||||
|
* Card Specification v2.2.1 section 5.<p>
|
||||||
|
*
|
||||||
|
* If <code>this</code> entry corresponds to the Issuer Security Domain (ISD),
|
||||||
|
* then the OPEN shall check that the requested transition complies with Card
|
||||||
|
* Life Cycle State transition rules. If needed, the OPEN shall check that the
|
||||||
|
* Application invoking this method has the Card Lock Privilege or the Card
|
||||||
|
* Terminate Privilege.<p>
|
||||||
|
*
|
||||||
|
* Otherwise, the following rules shall apply:<ul>
|
||||||
|
*
|
||||||
|
* <li>If <code>this</code> entry corresponds to a Security Domain, then the
|
||||||
|
* OPEN shall check that the requested transition complies with Security
|
||||||
|
* Domains' Life Cycle State transition rules.
|
||||||
|
*
|
||||||
|
* <li>If <code>this</code> entry does not correspond to a Security Domain,
|
||||||
|
* then the OPEN shall check the requested transition complies with
|
||||||
|
* Applications' Life Cycle State transition rules.
|
||||||
|
*
|
||||||
|
* <li>If this method is invoked to transition an Application (or Security
|
||||||
|
* Domain) from the INSTALLED state to the SELECTABLE state, then the request
|
||||||
|
* shall be rejected.
|
||||||
|
*
|
||||||
|
* <li>If the high order bit (b8) of <code>bState</code> is set to 1, then the
|
||||||
|
* call to this method shall be interpreted as an attempt to lock an
|
||||||
|
* Application (or Security Domain), and other bits of <code>bState</code>
|
||||||
|
* shall be ignored (b7-b1).
|
||||||
|
*
|
||||||
|
* <li>If <code>this</code> entry corresponds to an Application (or Security
|
||||||
|
* Domain) that is currenly locked, then only the high order bit (b8) of
|
||||||
|
* <code>bState</code> shall be taken into account and, if it is set to 0 then
|
||||||
|
* the call to this method shall be interpreted as an attempt to unlock the
|
||||||
|
* Application (or Security Domain). Other bits of <code>bState</code> shall
|
||||||
|
* be ignored (b7-b1).
|
||||||
|
*
|
||||||
|
* <li>If this method is invoked to lock or unlock an Application (or Security
|
||||||
|
* Domain), then the OPEN shall check that the Application invoking this
|
||||||
|
* method either corresponds to <code>this</code> entry or has the Global Lock
|
||||||
|
* Privilege.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param bState the new Life Cycle State. See Card Specification v2.2.1
|
||||||
|
* section 11.1.1 for details on Life Cycle State Coding. A value of {@link
|
||||||
|
* GPSystem#APPLICATION_LOCKED} (resp. 0x00) may be used to request locking
|
||||||
|
* (resp. unlocking) an Application or a Security Domain (other than the ISD).
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the transition was successful,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean setState(byte bState);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
507
build_tools/Tools/ext_api/gp221/org/globalplatform/GPSystem.java
Normal file
507
build_tools/Tools/ext_api/gp221/org/globalplatform/GPSystem.java
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class exposes a subset of the behavior of the OPEN to the
|
||||||
|
* outside world. The OPEN implements and enforces a Card Issuer's security
|
||||||
|
* policy relating to these services. It provides functionality at
|
||||||
|
* the same level as the JCRE, i.e. the "system" context with special
|
||||||
|
* privileges.
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.0: initial version.
|
||||||
|
* <li>export file version 1.1: new services and/or constants added.
|
||||||
|
* <li>export file version 1.3: new services and/or constants added.
|
||||||
|
* <li>export file version 1.5: new services and/or constants added.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GPSystem
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The current applet context is in the Life Cycle State of INSTALLED (0x03).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>The Life Cycle State INSTALLED could be indicated along with another application
|
||||||
|
* specific Life Cycle State, e.g. a value of (0x07) indicates that the applet has been made
|
||||||
|
* selectable.</em>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static final byte APPLICATION_INSTALLED = (byte) 0x03;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current applet context is in the Life Cycle State of SELECTABLE (0x07).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>The Life Cycle State SELECTABLE could be indicated along with another application
|
||||||
|
* specific Life Cycle State.</em>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static final byte APPLICATION_SELECTABLE = (byte) 0x07;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current applet context is in the Life Cycle State of LOCKED (0x80).
|
||||||
|
*
|
||||||
|
* To know whether an application is locked or not, a logical AND operation
|
||||||
|
* shall be performed between this constant and the current application life
|
||||||
|
* cycle state.
|
||||||
|
*/
|
||||||
|
public static final byte APPLICATION_LOCKED = (byte) 0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Security Domain is in the Life Cycle State of PERSONALIZED (0x0F).
|
||||||
|
*/
|
||||||
|
public static final byte SECURITY_DOMAIN_PERSONALIZED = (byte) 0x0F;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The card is in the Life Cycle State of OP_READY (0x01).
|
||||||
|
*/
|
||||||
|
public static final byte CARD_OP_READY = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The card is in the Life Cycle State of INITIALIZED (0x07).
|
||||||
|
*/
|
||||||
|
public static final byte CARD_INITIALIZED = (byte) 0x07;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The card is in the Life Cycle State of SECURED (0x0F).
|
||||||
|
*/
|
||||||
|
public static final byte CARD_SECURED = (byte) 0x0F;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The card is in the Life Cycle State of CARD_LOCKED (0x7F).
|
||||||
|
*/
|
||||||
|
public static final byte CARD_LOCKED = (byte) 0x7F;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The card is in the Life Cycle State of TERMINATED (0xFF).
|
||||||
|
*/
|
||||||
|
public static final byte CARD_TERMINATED = (byte) 0xFF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is a Global PIN (0x11).
|
||||||
|
*/
|
||||||
|
public static final byte CVM_GLOBAL_PIN = (byte) 0x11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 1 (0x01).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_1 = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 2 (0x02).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_2 = (byte) 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 3 (0x03).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_3 = (byte) 0x03;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 4 (0x04).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_4 = (byte) 0x04;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 5 (0x05).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_5 = (byte) 0x05;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 6 (0x06).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_6 = (byte) 0x06;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 7 (0x07).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_7 = (byte) 0x07;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the required CVM interface is the ETSI PIN App 8 (0x08).
|
||||||
|
* @since export file version 1.5
|
||||||
|
*/
|
||||||
|
public static final byte CVM_ETSI_PIN_APP_8 = (byte) 0x08;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the family of the Secure Channel Global Service Identifier (0x81).
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_SECURE_CHANNEL = (byte) 0x81;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the family of the CVM Global Service Identifier (0x82).
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_CVM = (byte) 0x82;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since export file version 1.2
|
||||||
|
* @deprecated Use {@link #FAMILY_AUTHORITY} instead.
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_AUHTORITY= (byte)0x83;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the family of the Authority Service Identifier (0x83).
|
||||||
|
* @since export file version 1.2
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_AUTHORITY= (byte)0x83;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the family of the HTTP Administration Service Identifier (0x84).
|
||||||
|
* @since export file version 1.3
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_HTTP_ADMINISTRATION= (byte)0x84;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the family of the HTTP Report Service Identifier (0x85).
|
||||||
|
* @since export file version 1.3
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_HTTP_REPORT= (byte)0x85;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the family of the USSM Global Service Identifier (0xA0).
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
public static final byte FAMILY_USSM = (byte) 0xA0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the generic Global Service Identifier (0x80).
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
public static final byte GLOBAL_SERVICE_IDENTIFIER = (byte) 0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Life Cycle State of the current applet context.<p>
|
||||||
|
*
|
||||||
|
* @return the Life Cycle State of the current applet context.
|
||||||
|
*
|
||||||
|
* @see #APPLICATION_INSTALLED
|
||||||
|
* @see #APPLICATION_SELECTABLE
|
||||||
|
* @see #APPLICATION_LOCKED
|
||||||
|
*/
|
||||||
|
public static byte getCardContentState()
|
||||||
|
{
|
||||||
|
return ((byte)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Life Cycle State of the card.<p>
|
||||||
|
*
|
||||||
|
* @return the Life Cycle State of the card.
|
||||||
|
*
|
||||||
|
* @see #CARD_OP_READY
|
||||||
|
* @see #CARD_INITIALIZED
|
||||||
|
* @see #CARD_SECURED
|
||||||
|
* @see #CARD_LOCKED
|
||||||
|
* @see #CARD_TERMINATED
|
||||||
|
*/
|
||||||
|
public static byte getCardState()
|
||||||
|
{
|
||||||
|
return((byte)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a reference to a {@link CVM} instance provided by the OPEN.<p>
|
||||||
|
*
|
||||||
|
* Since export file version 1.1, this method allows looking up for CVM
|
||||||
|
* instances registered as Global Services by so-called Global Services
|
||||||
|
* Applications (i.e. Applications having the Global Service Privilege) and
|
||||||
|
* the following mechanism is defined to retrieve such instances:<ul>
|
||||||
|
*
|
||||||
|
* <li>The OPEN looks up in the GlobalPlatform Registry for a Global Services
|
||||||
|
* Application (i.e. having the Global Service Privilege) that registered a
|
||||||
|
* Global Service with the specified <code>bCVMIdentifier</code> identifier
|
||||||
|
* for the {@link #FAMILY_CVM} family, or that uniquely registered a Global
|
||||||
|
* Service for the entire {@link #FAMILY_CVM} family.
|
||||||
|
*
|
||||||
|
* <li>The OPEN then retrieves the corresponding {@link GlobalService}
|
||||||
|
* instance by invoking the {@link Applet#getShareableInterfaceObject} method
|
||||||
|
* of that Global Services Application with the <code>clientAID</code>
|
||||||
|
* parameter set to the AID of the current applet context (i.e. the one
|
||||||
|
* invoking this method) and the <code>parameter</code> parameter set to
|
||||||
|
* {@link #GLOBAL_SERVICE_IDENTIFIER}.
|
||||||
|
*
|
||||||
|
* <li>The OPEN then retrieves a {@link Shareable} instance by invoking the
|
||||||
|
* {@link GlobalService#getServiceInterface} method with the
|
||||||
|
* <code>clientRegistryEntry</code> parameter set to the {@link
|
||||||
|
* GPRegistryEntry} instance of the current applet context (i.e. the one
|
||||||
|
* invoking this method), with the <code>sServiceName</code> set to
|
||||||
|
* <code>({@link #FAMILY_CVM}<<8|bCVMIdentifier)</code>, the
|
||||||
|
* <code>baBuffer</code> parameter set to <code>null</code>, and the
|
||||||
|
* <code>sOffset</code> and <code>sLength</code> set to zero.
|
||||||
|
*
|
||||||
|
* <li>Finally, the OPEN casts the retrieved {@link Shareable} instance to the
|
||||||
|
* {@link CVM} interface before returning it.
|
||||||
|
*
|
||||||
|
* <li>If any of the above steps fails, the requested CVM instance is deemed
|
||||||
|
* to be unavailable.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* For backward compatibility, the {@link #CVM_GLOBAL_PIN} constant can still
|
||||||
|
* be used to access a Global Service registered with the <code>({@link
|
||||||
|
* #FAMILY_CVM}<<8|{@link #CVM_GLOBAL_PIN})</code> identifier, or uniquely
|
||||||
|
* registered for the entire {@link #FAMILY_CVM} family. Whether such a
|
||||||
|
* service is available or not still depends on the issuer's policy.
|
||||||
|
*
|
||||||
|
* @param bCVMIdentifier identifies the requested CVM instance.
|
||||||
|
*
|
||||||
|
* @return requested CVM instance, or <code>null</code> if the requested CVM
|
||||||
|
* instance is not available.
|
||||||
|
*
|
||||||
|
* @see #CVM_GLOBAL_PIN
|
||||||
|
*/
|
||||||
|
public static CVM getCVM(byte bCVMIdentifier)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a {@link SecureChannel} instance.<p>
|
||||||
|
*
|
||||||
|
* This method allows the Application associated with the current applet
|
||||||
|
* context to retrieve a {@link SecureChannel} instance provided by its
|
||||||
|
* associated Security Domain.<p>
|
||||||
|
*
|
||||||
|
* Since export file version 1.1, although not required, this method may be
|
||||||
|
* implemented using the Global Service facility, in which case {@link
|
||||||
|
* SecureChannel} instances would be registered by Security Domains as Global
|
||||||
|
* Services. In this case, Security Domains shall check that they only provide
|
||||||
|
* such {@link SecureChannel} instances to their associated Applications.<p>
|
||||||
|
*
|
||||||
|
* @return the SecureChannel interface object reference.
|
||||||
|
*
|
||||||
|
* @see #getCVM the GPSystem.getCVM() method for an example of how to access a Global Service.
|
||||||
|
*/
|
||||||
|
public static SecureChannel getSecureChannel()
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks the card.
|
||||||
|
*
|
||||||
|
* This method shall be used to transition the card to {@link #CARD_LOCKED}
|
||||||
|
* Life Cycle State.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall check that the Application invoking this method has the Card
|
||||||
|
* Lock Privilege. If not, the transition shall be rejected. <p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the card was locked, <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean lockCard()
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminates the card.
|
||||||
|
*
|
||||||
|
* This method shall be used to transition the card to {@link
|
||||||
|
* #CARD_TERMINATED} Life Cycle State.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall check that the Application invoking this method has the Card
|
||||||
|
* Terminate Privilege. If not, the transition shall be rejected.<p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the card was terminated, <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean terminateCard()
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the historical bytes of the Answer To Reset (ATR) string.<p>
|
||||||
|
*
|
||||||
|
* This method only updates the ATR string that is used for the contact-based
|
||||||
|
* IO interface (as specified by [ISO/IEC 7816] upon power-up or cold
|
||||||
|
* reset. The ATR string used for warm reset shall remain unchanged. The new
|
||||||
|
* historical bytes shall be visible upon next power-up or cold reset.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall check that the Application invoking this method has the Card
|
||||||
|
* Reset Privilege and that the <code>bLength</code> is both positive and
|
||||||
|
* lower than 16. If not, the change shall be rejected.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
* <li><em>The OPEN is responsible for synchronizing the length of historical
|
||||||
|
* bytes in the format character (low order nibble of T0) of the ATR string.</em>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the ATR historical bytes.
|
||||||
|
* @param sOffset offset of the ATR historical bytes.
|
||||||
|
* @param bLength length of the ATR historical bytes.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if ATR historical bytes were set, <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean setATRHistBytes (byte[] baBuffer, short sOffset, byte bLength)
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Life Cycle state of the Application invoking this method.
|
||||||
|
*
|
||||||
|
* This method allows the Application associated with the current applet
|
||||||
|
* context to lock itself or to change its state from an application specific
|
||||||
|
* Life Cycle State to another application specific Life Cycle State. An
|
||||||
|
* Application cannot unlock itself.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall check that the Application is currently in an application
|
||||||
|
* specific Life Cycle State (i.e. in the range [0x07 .. 0x7F] and with its 3
|
||||||
|
* low order bits set to 1), in particular that it is not in the {@link
|
||||||
|
* #APPLICATION_INSTALLED} state and not currently locked. If not, the change
|
||||||
|
* shall be rejected.
|
||||||
|
*
|
||||||
|
* The OPEN shall check that <code>bState</code> either encodes an application
|
||||||
|
* specific Life Cycle State or has its high order bit (b8) set to 1: the
|
||||||
|
* latter case shall be interpreted as a request from the the Application to
|
||||||
|
* lock itself.
|
||||||
|
*
|
||||||
|
* @param bState either an application specific Life Cycle State (i.e. in the
|
||||||
|
* range [0x07 .. 0x7F] and with its 3 low order bits set to 1), or any value
|
||||||
|
* having its high order bit (b8) set to 1. A value of {@link
|
||||||
|
* #APPLICATION_LOCKED} may be used to request locking the Application.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the Life Cycle State of the Application was
|
||||||
|
* changed, <code>false</code> otherwise.
|
||||||
|
*
|
||||||
|
* @see #APPLICATION_INSTALLED
|
||||||
|
* @see #APPLICATION_LOCKED
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.0: initial version.
|
||||||
|
* <li>export file version 1.5: this method now allows the application
|
||||||
|
* associated with the current applet context to lock itself.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static boolean setCardContentState(byte bState)
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a {@link GPRegistryEntry} instance.<p>
|
||||||
|
*
|
||||||
|
* This method allows the Application associated with the current applet
|
||||||
|
* context to get its own {@link GPRegistryEntry} instance or the one of
|
||||||
|
* another Application.
|
||||||
|
*
|
||||||
|
* If the <code>aid</code> parameter is not <code>null</code> and does not
|
||||||
|
* identify the Application invoking this method, the OPEN shall check that
|
||||||
|
* the Application invoking this method has the Global Registry Privilege. If
|
||||||
|
* not, this method shall return <code>null</code>.<p>
|
||||||
|
*
|
||||||
|
* @param aid the AID of the Application whose {@link GPRegistryEntry}
|
||||||
|
* instance is requested. Use <code>null</code> to retrieve the {@link
|
||||||
|
* GPRegistryEntry} instance of the current applet context.
|
||||||
|
*
|
||||||
|
* @return the requested {@link GPRegistryEntry} instance if it was found in
|
||||||
|
* the GlobalPlatform Registry and the Application invoking this method is
|
||||||
|
* allowed to access that entry, <code>null</code> otherwise.
|
||||||
|
*
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
public static GPRegistryEntry getRegistryEntry(AID aid)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a {@link GlobalService} instance matching the specified service name
|
||||||
|
* (<code>sServiceName</code>).<p>
|
||||||
|
*
|
||||||
|
* The <code>serverAID</code> parameter is optional (i.e. may be set to
|
||||||
|
* <code>null</code>) and identifies the Global Services Application providing
|
||||||
|
* the service.<p>
|
||||||
|
*
|
||||||
|
* The OPEN shall look for the Global Services Application providing the
|
||||||
|
* service:<ul>
|
||||||
|
*
|
||||||
|
* <li>If the <code>serverAID</code> parameter is <code>null</code>, then the
|
||||||
|
* OPEN shall look for the specified service name among the set of uniquely
|
||||||
|
* registered service names (see {@link GPRegistryEntry#registerService}). If
|
||||||
|
* the requested service name only identifies a family of services, then the
|
||||||
|
* OPEN shall look for a uniquely registered service name of the requested
|
||||||
|
* family (the search strategy remains implementation dependent). If a
|
||||||
|
* matching service name is found, the Global Services Application is the one
|
||||||
|
* that uniquely registered that service name.
|
||||||
|
*
|
||||||
|
* <li>Otherwise, if the <code>serverAID</code> parameter is not
|
||||||
|
* <code>null</code>, then the OPEN shall look in the GlobalPlatform Registry
|
||||||
|
* for the corresponding Application:<ul>
|
||||||
|
*
|
||||||
|
* <li>If the Application does not have the Global Service Privilege, then
|
||||||
|
* the search is deemed to be unsuccessful.
|
||||||
|
*
|
||||||
|
* <li>If the requested service name (or family of service) was not
|
||||||
|
* previously recorded for that Application (i.e. not specified as part of
|
||||||
|
* System Install Parameters in the INSTALL command), then the search is
|
||||||
|
* deemed to be unsuccessful.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* If a Global Services Application was found, then the OPEN shall retrieve
|
||||||
|
* the {@link GlobalService} instance by invoking the {@link
|
||||||
|
* Applet#getShareableInterfaceObject} method of that Global Services
|
||||||
|
* Application with the <code>clientAID</code> parameter set to the AID of the
|
||||||
|
* current applet context (i.e. the one invoking this method) and the
|
||||||
|
* <code>parameter</code> parameter set to {@link #GLOBAL_SERVICE_IDENTIFIER}.
|
||||||
|
*
|
||||||
|
* @param serverAID AID of the Global Services Application providing the
|
||||||
|
* requested service, or <code>null</code> if the caller of this method is
|
||||||
|
* requesting a uniquely registered service name.<p>
|
||||||
|
*
|
||||||
|
* @param sServiceName service name identifying a service or a family of
|
||||||
|
* services.<p>
|
||||||
|
*
|
||||||
|
* A service name is encoded on 2 bytes, the 1st byte identifying a family of
|
||||||
|
* services and the 2nd byte identifying a service within that family. If the
|
||||||
|
* 2nd byte is set to <code>0x00</code>, the caller of this method is
|
||||||
|
* requesting a service of the specified family, but does not care exactly
|
||||||
|
* which service within that family.<p>
|
||||||
|
*
|
||||||
|
* This class defines a set of constants <code>FAMILY_XXX</code> (of the
|
||||||
|
* <code>byte</code> type) that may be used to build a service name (of the
|
||||||
|
* <code>short</code> type) suitable to invoke this method as shown in the
|
||||||
|
* following examples:<ul>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link #FAMILY_CVM}<<8)|0x11)</code>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link #FAMILY_HTTP_ADMINISTRATION}<<8)|0x00)</code>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return the {@link GlobalService} instance giving access to the requested
|
||||||
|
* service, or <code>null</code> if the Global Services Application could not
|
||||||
|
* be found or did not provide a {@link GlobalService} instance.
|
||||||
|
*
|
||||||
|
* @see #GLOBAL_SERVICE_IDENTIFIER
|
||||||
|
* @see #FAMILY_CVM
|
||||||
|
* @see #FAMILY_SECURE_CHANNEL
|
||||||
|
* @see #FAMILY_USSM
|
||||||
|
* @see #FAMILY_AUTHORITY
|
||||||
|
* @see #FAMILY_HTTP_ADMINISTRATION
|
||||||
|
* @see #FAMILY_HTTP_REPORT
|
||||||
|
* @see GPRegistryEntry#registerService
|
||||||
|
*
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
public static GlobalService getService(AID serverAID, short sServiceName)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface allows requesting a Global Services Application for a
|
||||||
|
* Shareable Interface Object (SIO) providing the actual service.<p>
|
||||||
|
*
|
||||||
|
* To retrieve an instance of this interface, an Application shall invoke the
|
||||||
|
* {@link GPSystem#getService} method.<p>
|
||||||
|
*
|
||||||
|
* @since export file version 1.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface GlobalService extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Key Access indicating key may be used by the Security Domain and any
|
||||||
|
* associated Application (0x00).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_ACCESS_ANY = (byte) 0x00;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key Access indicating key may be used by the Security Domain but not by any
|
||||||
|
* associated Application (0x01).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_ACCESS_SECURITY_DOMAIN = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key Access indicating key may be used by any associated Application but not
|
||||||
|
* by the Security Domain (0x02).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_ACCESS_APPLICATION = (byte) 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating AES (0x88).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_AES = (byte) 0x88;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating Triple DES reserved for specific implementations (0x81).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_3DES = (byte) 0x81;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating Triple DES in CBC mode (0x82).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_3DES_CBC = (byte) 0x82;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating DES with ECB/CBC implicitly known (0x80).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_DES = (byte) 0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating DES in CBC mode (0x84).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_DES_CBC = (byte) 0x84;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating DES in ECB mode (0x83).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_DES_ECB = (byte) 0x83;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating extended key format (0xFF).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_EXTENDED = (byte) 0xFF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating HMAC SHA1, length of HMAC implicitly known (0x90).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_HMAC_SHA1 = (byte) 0x90;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating HMAC SHA1, length of HMAC is 160 bits (0x91).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_HMAC_SHA1_160 = (byte) 0x91;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private Key Chinese Remainder p component (0xA4).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_CRT_P = (byte) 0xA4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private Key Chinese Remainder q component (0xA5).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_CRT_Q = (byte) 0xA5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private Key Chinese Remainder pq component (0xA6).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_CRT_PQ = (byte) 0xA6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private Key Chinese Remainder dp1 component (0xA7).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_CRT_DP1 = (byte) 0xA7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private Key Chinese Remainder dq1 component (0xA8).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_CRT_DQ1 = (byte) 0xA8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private exponent (0xA3).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_EXPONENT = (byte) 0xA3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Private Key modulus (0xA2).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PRIVATE_MODULUS = (byte) 0xA2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Public Key exponent (0xA0).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PUBLIC_EXPONENT = (byte) 0xA0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key type indicating RSA Public Key modulus (0xA1).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_TYPE_RSA_PUBLIC_MODULUS = (byte) 0xA1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating computation and decipherment (0x40).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_COMPUTATION_DECIPHERMENT = (byte) 0x40;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating sensitive data confidentiality (0x08).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_CONFIDENTIALITY = (byte) 0x08;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating cryptographic authorization (0x01).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_CRYPTOGRAPHIC_AUTHORIZATION = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating cryptographic checksum e.g. MAC (0x04).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_CRYPTOGRAPHIC_CHECKSUM = (byte) 0x04;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating Digital Signature (0x02).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_DIGITAL_SIGNATURE = (byte) 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating Secure Messaging in command data field (0x10).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_SM_COMMAND = (byte) 0x10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating Secure Messaging in response data field (0x20).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_SM_RESPONSE = (byte) 0x20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key usage indicating verification and encipherment (0x80).
|
||||||
|
*/
|
||||||
|
public static final byte KEY_USAGE_VERIFICATION_ENCIPHERMENT = (byte) 0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a Shareable Interface Object (SIO) actually providing the requested service.<p>
|
||||||
|
*
|
||||||
|
* The Application invoking this method shall set the
|
||||||
|
* <code>clientRegistryEntry</code> to its own {@link GPRegistryEntry}
|
||||||
|
* instance.<p>
|
||||||
|
*
|
||||||
|
* The Global Services Application shall verify the validity of the request
|
||||||
|
* according to its own security policies for the specified
|
||||||
|
* <code>sServiceName</code>, based on the identity and characteristics of the
|
||||||
|
* Application invoking this method as registered by the specified
|
||||||
|
* <code>clientRegistryEntry</code>, and possibly based on the data contained
|
||||||
|
* in the <code>baBuffer</code> byte array.<p>
|
||||||
|
*
|
||||||
|
* If the request is valid, the Global Service Application returns a SIO
|
||||||
|
* implementing the actual service: this SIO may either be this {@link
|
||||||
|
* GlobalService} instance or another object. If the request is deemed to be
|
||||||
|
* invalid, the Global Services Application shall reject the request by either
|
||||||
|
* throwing an exception or returning <code>null</code>.<p>
|
||||||
|
*
|
||||||
|
* It is assumed that the Application invoking this method is aware of the
|
||||||
|
* interface (extension of the {@link Shareable} interface) to which the
|
||||||
|
* retrieved SIO shall be casted in order to acces the service.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>It shall be noticed that an Application having the Global Registry
|
||||||
|
* Privilege could potentially invoke this method with the
|
||||||
|
* <code>clientRegistryEntry</code> parameter set to the {@link
|
||||||
|
* GPRegistryEntry} instance of another Application. If the Global Services
|
||||||
|
* Application itself has the Global Registry Privilege, it may explicitly
|
||||||
|
* retrieve and check the {@link GPRegistryEntry} instance of the Application
|
||||||
|
* invoking this method, by performing the following call:
|
||||||
|
* <code>GPSystem.getRegistryEntry(JCSystem.getPreviousContextAID())</code>.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param clientRegistryEntry the {@link GPRegistryEntry} instance of the
|
||||||
|
* requesting Application.<p>
|
||||||
|
* @param sServiceName a service name identifying the requested service.<p>
|
||||||
|
*
|
||||||
|
* A service name is encoded on 2 bytes, the 1st byte identifying a family of
|
||||||
|
* services and the 2nd byte identifying a service within that family.<p>
|
||||||
|
*
|
||||||
|
* The {@link GPSystem} class defines a set of constants
|
||||||
|
* <code>FAMILY_XXX</code> (of the <code>byte</code> type) that may be used to
|
||||||
|
* build a service name (of the <code>short</code> type) suitable to invoke
|
||||||
|
* this method as shown in the following examples:<ul>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link GPSystem#FAMILY_CVM}<<8)|0x11)</code>
|
||||||
|
*
|
||||||
|
* <li><code>(short)(({@link GPSystem#FAMILY_HTTP_ADMINISTRATION}<<8)|0x00)</code>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing additional parameters of the request,
|
||||||
|
* potentially authentication data. Must be <em>global</em> byte array.
|
||||||
|
* @param sOffset offset of the additional parameters.
|
||||||
|
* @param sLength length of the additional parameters.
|
||||||
|
*
|
||||||
|
* @return the SIO providing the actual service, or <code>null</code> if the
|
||||||
|
* service is not available or the request was rejected. Alternatively, this
|
||||||
|
* method may reject the request by throwing an <code>ISOException</code>.
|
||||||
|
*
|
||||||
|
* @exception ISOException if the request was rejected. Although not
|
||||||
|
* mandatory, it is recommended to use one of the following reason codes:<ul>
|
||||||
|
* <li>'6A88' if the specified service was not found or is not available.
|
||||||
|
* <li>'6982' if some security conditions are not satisfied.
|
||||||
|
* <li>'6985' if some other conditions are not satisfied.
|
||||||
|
* </ul>
|
||||||
|
* Alternatively, this method may reject the request by returning <code>null</code>.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if the Global Services Application requires
|
||||||
|
* reading data from <code>baBuffer</code> and <code>baBuffer</code> is not a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @exception NullPointerException if the Global Services Application requires
|
||||||
|
* reading data from <code>baBuffer</code> and <code>baBuffer</code> is
|
||||||
|
* <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if the Global Services
|
||||||
|
* Application requires reading data from <code>baBuffer</code> and reading
|
||||||
|
* data would cause access of data outside array bounds.
|
||||||
|
*
|
||||||
|
* @see GPSystem#getService
|
||||||
|
* @see GPSystem#FAMILY_CVM
|
||||||
|
* @see GPSystem#FAMILY_SECURE_CHANNEL
|
||||||
|
* @see GPSystem#FAMILY_USSM
|
||||||
|
* @see GPSystem#FAMILY_AUTHORITY
|
||||||
|
* @see GPSystem#FAMILY_HTTP_ADMINISTRATION
|
||||||
|
* @see GPSystem#FAMILY_HTTP_REPORT
|
||||||
|
*/
|
||||||
|
public Shareable getServiceInterface(GPRegistryEntry clientRegistryEntry, short sServiceName, byte[] baBuffer, short sOffset, short sLength) throws ISOException;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines a method to trigger a new HTTP administration session.<p>
|
||||||
|
*
|
||||||
|
* To retrieve an instance of this interface, an Application shall use the
|
||||||
|
* {@link GlobalService} instance, if available, registered with a service name
|
||||||
|
* of <code>({@link GPSystem#FAMILY_HTTP_ADMINISTRATION}<<8|0x00)</code>.
|
||||||
|
*
|
||||||
|
* @see GlobalService
|
||||||
|
* @see GPSystem#getService
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.3: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public interface HTTPAdministration extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Triggers a new administration session. <p>
|
||||||
|
*
|
||||||
|
* The Security Domain of the Application invoking this method will handle the
|
||||||
|
* SCP81 (PSK TLS) security of the communication. <p>
|
||||||
|
*
|
||||||
|
* The Application invoking this method will be notified of the result of the
|
||||||
|
* request if it implements the {@link HTTPReportListener} interface. <p>
|
||||||
|
*
|
||||||
|
* @param triggeringParameters byte array containing administration session
|
||||||
|
* triggering parameters.
|
||||||
|
* @param offset offset of triggering parameters within <code>triggeringParameters</code>.
|
||||||
|
* @param length length of triggering parameters.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>triggeringParameters</code> is not
|
||||||
|
* accessible in the caller's context.
|
||||||
|
* @exception NullPointerException if <code>triggeringParameters</code> is
|
||||||
|
* <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading triggering parameters
|
||||||
|
* command would cause access of data outside array bounds.
|
||||||
|
*
|
||||||
|
* @exception ISOException with one of the following reason codes: <ul>
|
||||||
|
* <li> <code>SW_WRONG_DATA</code> if parameters are not
|
||||||
|
* correctly formatted.
|
||||||
|
* <li> <code>SW_CONDITIONS_NOT_SATISFIED</code> if the request could not be
|
||||||
|
* processed (e.g. if no SCP81 session could be established).
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
void requestHTTPAdministrationSession (byte[] triggeringParameters,
|
||||||
|
short offset,
|
||||||
|
short length);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.Shareable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines a method to receive a notification upon completion
|
||||||
|
* (success or failure) of an HTTP Administration Session.<p>
|
||||||
|
*
|
||||||
|
* An Application that wishes to receive such a notification shall implement the
|
||||||
|
* {@link javacard.framework.Applet#getShareableInterfaceObject} to return an
|
||||||
|
* {@link HTTPReportListener} instance when the <code>clientAID</code> parameter
|
||||||
|
* is set to <code>null</code>, and the <code>parameter</code> parameter is set
|
||||||
|
* to {@link GPSystem#FAMILY_HTTP_REPORT}.<p>
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.3: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface HTTPReportListener extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constant notifying that a HTTP Administration Session ended successfully
|
||||||
|
*/
|
||||||
|
public final static short HTTP_SESSION_NO_ERROR=0x0001;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant notifying that a HTTP Administration Session failed. That is, the
|
||||||
|
* retry policy of the session is exhausted and the administration session
|
||||||
|
* request is aborted.
|
||||||
|
*/
|
||||||
|
public final static short HTTP_SESSION_ERROR=(short) 0x8001;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the Application that the requested HTTP Administration Session
|
||||||
|
* successfully completed or not. <p>
|
||||||
|
*
|
||||||
|
* The OPEN notifies the Application when the HTTP Administration Session ends
|
||||||
|
* or when the retry policy is exhausted.<p>
|
||||||
|
*
|
||||||
|
* @param status Either {@link #HTTP_SESSION_NO_ERROR} (failure) or {@link
|
||||||
|
* #HTTP_SESSION_ERROR} (success).
|
||||||
|
*/
|
||||||
|
public void httpAdministationSessionReport(short status);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines a method through which an Application may forward
|
||||||
|
* input data to another Application and retrieve output data from that
|
||||||
|
* Application.<p>
|
||||||
|
*
|
||||||
|
* This interface shall be implemented by an Application that wishes to receive
|
||||||
|
* personalization data forwarded by its associated Security Domain and request
|
||||||
|
* outputting response data. In such a scenario, if the Application implements
|
||||||
|
* both the {@link Application} and the {@link Personalization} interface, then
|
||||||
|
* the Security Domain shall use the {@link Personalization} interface. <p>
|
||||||
|
*
|
||||||
|
* @see Application
|
||||||
|
*
|
||||||
|
* @since export file version 1.2
|
||||||
|
*/
|
||||||
|
public interface Personalization extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Processes application specific data received from another on-card entity.<p>
|
||||||
|
*
|
||||||
|
* If the Application invoking this method is a Security Domain then it shall
|
||||||
|
* be assumed that:<ul>
|
||||||
|
*
|
||||||
|
* <li>Both the <code>inBuffer</code> and <code>outBuffer</code> byte arrays
|
||||||
|
* are <em>global</em> byte arrays;
|
||||||
|
*
|
||||||
|
* <li>The data forwarded by the Security Domain is a STORE DATA command. The
|
||||||
|
* <code>sOffset</code> parameter locates the class byte of the command and
|
||||||
|
* the <code>sLength</code> parameter indicates the length of the entire
|
||||||
|
* command (i.e. header + data field).
|
||||||
|
*
|
||||||
|
* <li>The Security Domain will send back to the off-card entity the output
|
||||||
|
* data written by the Application to <code>outBuffer</code>.
|
||||||
|
*
|
||||||
|
* <li>Any exception thrown by this method will be rethrown by the Security
|
||||||
|
* Domain, hence will be converted to and returned as a response status word
|
||||||
|
* to the off-card entity. If the exception is an {@link ISOException}, then
|
||||||
|
* the status word will be the reason code of that exception. Otherwise, a
|
||||||
|
* status word of '6F00' will be returned.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>Upon invocation of this method, the Java Card VM performs a
|
||||||
|
* context switch.</em>
|
||||||
|
*
|
||||||
|
* <li><em>As the Application is not the currently selected Application, it
|
||||||
|
* should not attempt to access transient memory of type
|
||||||
|
* <code>CLEAR_ON_DESELECT</code> during the processing of this method.</em>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is responsible for managing the atomic
|
||||||
|
* modification of its own data, if needed.</em>
|
||||||
|
*
|
||||||
|
* <li><em>As this method may be invoked by a Security Domain immaterial of
|
||||||
|
* the Application's internal state, the Application is responsible for
|
||||||
|
* ensuring that its internal state is valid for this operation.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param inBuffer byte array containing input data. Must be a <em>global</em>
|
||||||
|
* byte array.
|
||||||
|
* @param inOffset offset of input data within <code>inBuffer</code>.
|
||||||
|
* @param inLength length of input data.
|
||||||
|
* @param outBuffer byte array where output data shall be written. Must be a
|
||||||
|
* <em>global</em> byte array.
|
||||||
|
* @param outOffset offset where output data shall be written within
|
||||||
|
* <code>inBuffer</code>.
|
||||||
|
*
|
||||||
|
* @return the number of bytes written to <code>outBuffer</code>.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>inBuffer</code> or
|
||||||
|
* <code>outBuffer</code> is not a <em>global</em> byte array.
|
||||||
|
* @exception NullPointerException if <code>inBuffer</code> or
|
||||||
|
* <code>outBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading intput data or writing
|
||||||
|
* output data would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short processData (byte[] inBuffer, short inOffset, short inLength, byte[] outBuffer, short outOffset);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,493 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines basic Secure Channel services used to manage entity
|
||||||
|
* authentication and protect APDU commands and responses. It is typically
|
||||||
|
* exposed by a Security Domain to its associated Applications.<p>
|
||||||
|
*
|
||||||
|
* Using an instance of this interface requires no knowledge of the underlying
|
||||||
|
* protocols, algorithms and secrets used to perform entity authentication and
|
||||||
|
* provide integrity and confidentiality of APDU commands and responses, which
|
||||||
|
* only need to be known by the provider of the instance.<p>
|
||||||
|
*
|
||||||
|
* An Application that wishes to delegate such activities to its associated
|
||||||
|
* Security Domain shall retrieve a {@link SecureChannel} instance provided by
|
||||||
|
* its associated Security Domain using the {@link GPSystem#getSecureChannel}
|
||||||
|
* method. On some implementations, this {@link SecureChannel} instance may also
|
||||||
|
* be retrieved using the {@link GPSystem#getService} method.<p>
|
||||||
|
*
|
||||||
|
* If the card supports logical channels, this interface is responsible for
|
||||||
|
* correctly handling any indication of a logical channel number present in the
|
||||||
|
* class byte of APDU commands. In particular, it shall be able to verify and
|
||||||
|
* remove (i.e. unwrap) the protection (if any) of an APDU command without
|
||||||
|
* altering such indication of a logical channel number.
|
||||||
|
*
|
||||||
|
* Upon successful initialization of a Secure Channel Session, the
|
||||||
|
* implementation shall establish both a compulsory Session Security Level and a
|
||||||
|
* Current Security Level:<ul>
|
||||||
|
*
|
||||||
|
* <li>The compulsory <em>Session Security Level</em> is the Security Level negotiated
|
||||||
|
* during the initialization of the session, that shall apply as a minimum
|
||||||
|
* security requirement during the entire Secure Channel Session. The compulsory
|
||||||
|
* Session Security Level shall only be reset upon (full) termination of the
|
||||||
|
* Secure Channel Session.
|
||||||
|
*
|
||||||
|
* <li>The <em>Current Security Level</em> is the security requirement that
|
||||||
|
* shall indeed apply to APDU commands (and responses) during the session and is
|
||||||
|
* initialized to the same value as the compulsory Session Security Level at the
|
||||||
|
* beginning of the session. The Current Security Level may be subsequently
|
||||||
|
* updated (e.g. R-MAC or not) upon successful processing of some commands
|
||||||
|
* specific to the underlying security protocol or upon successful invocation of
|
||||||
|
* the {@link SecureChannelx#setSecurityLevel} method (if supported), but shall
|
||||||
|
* never get below the minimum requirement defined by the compulsory Session
|
||||||
|
* Security Level. The Current Security Level, as well as any information
|
||||||
|
* relating to the Secure Channel Session (except the compulsory Session
|
||||||
|
* Security Level), shall be reset upon abortion or termination of the Secure
|
||||||
|
* Channel Session.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <a name="sc_abort">See Card Specification v2.2.1 section 10.2.3 for details
|
||||||
|
* about abortion and termination of a Secure Channel Session.</a><p>
|
||||||
|
*
|
||||||
|
* Until it is aborted, a Secure Channel Session shall be bound to the following
|
||||||
|
* information:<ul>
|
||||||
|
|
||||||
|
* <li>the Logical Channel on which it was initiated: The session only exists on
|
||||||
|
* the Logical Channel on which it was initiated. If an Application invokes this
|
||||||
|
* interface from another Logical Channel, then the interface shall behave as if
|
||||||
|
* no Secure Channel Session was currently open but the existing session shall
|
||||||
|
* neither be aborted nor be terminated. For resource management reasons,
|
||||||
|
* attempts to open another Secure Channel Session from another Logical Channel
|
||||||
|
* (i.e. concurrently to the existing one(s)) may be rejected by the
|
||||||
|
* implementation.
|
||||||
|
|
||||||
|
* <li>the Application that initiated the session: Any call performed to this
|
||||||
|
* interface by another Application from the Logical Channel attached to the
|
||||||
|
* session shall be rejected with an exception. For example, this may happen if
|
||||||
|
* this other Application somehow obtained a reference to this interface using
|
||||||
|
* the sharing mechanism.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.0: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface SecureChannel extends Shareable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Entity Authentication has occurred as Application Provider (0x80).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>Entity Authentication and the level of security that will be applied by the {@link #wrap}
|
||||||
|
* and {@link #unwrap} methods are not necessarily related. A Security Domain, by default, could
|
||||||
|
* verify the MAC on any command passed as a parameter in the {@link #unwrap} method without
|
||||||
|
* entity authentication previously having occurred.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte AUTHENTICATED = (byte) 0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #unwrap} method will decrypt incoming command data (0x02).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>Command data decryption could be indicated along with entity authentication and one or more
|
||||||
|
* levels of security.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte C_DECRYPTION = (byte) 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #unwrap} method will verify the MAC on an incoming command (0x01).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>MAC verification could be indicated along with entity authentication and one or more
|
||||||
|
* levels of security, e.g. a value of '03' indicates that while entity authentication has not
|
||||||
|
* occurred, the {@link #unwrap} method will decrypt the command data of incoming commands
|
||||||
|
* and verify the MAC on incoming commands.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte C_MAC = (byte) 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #wrap} method will encrypt the outgoing response data (0x20).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>Response data encryption could be indicated along with entity authentication and one
|
||||||
|
* or more levels of security.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte R_ENCRYPTION = (byte) 0x20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #wrap} method will generate a MAC for the outgoing response data (0x10).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>MAC generation could be indicated along with entity authentication and one or more
|
||||||
|
* levels of security, e.g. a value of '91' indicates that entity authentication has occurred,
|
||||||
|
* that the {@link #unwrap} method will verify the MAC on incoming commands and that the
|
||||||
|
* {@link #wrap} method will generate a MAC on outgoing response data.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte R_MAC = (byte) 0x10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity Authentication has not occurred (0x00).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>Entity Authentication and the level of security that will be applied by the
|
||||||
|
* {@link #wrap} and {@link #unwrap} methods are not necessarily related. A
|
||||||
|
* Security Domain, by default, could verify the MAC on any command passed as a parameter in
|
||||||
|
* the {@link #unwrap} method without entity authentication previously having occurred.</em>
|
||||||
|
* <li><em>The {@link #wrap} and {@link #unwrap} methods will not apply any cryptographic
|
||||||
|
* processing to command or response data.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte NO_SECURITY_LEVEL = (byte) 0x00;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity Any Authentication has occurred (0x40).
|
||||||
|
* <p>Note:<ul>
|
||||||
|
* <li><em>The authenticated entity is not the Application Provider of the Application.</em>
|
||||||
|
* <li><em>Entity Authentication and the level of security that will be applied by the {@link #wrap}
|
||||||
|
* and {@link #unwrap} methods are not necessarily related. A Security Domain, by default, could
|
||||||
|
* verify the MAC on any command passed as a parameter in the {@link #unwrap} method without
|
||||||
|
* entity authentication previously having occurred.</em> </ul>
|
||||||
|
*/
|
||||||
|
public static final byte ANY_AUTHENTICATED = (byte) 0x40;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes security related APDU commands, that is, APDU commands relating
|
||||||
|
* to the underlying security protocol.<p>
|
||||||
|
*
|
||||||
|
* As the intention is to allow an Application to use Secure Channel services
|
||||||
|
* without having any knowledge of the underlying security protocols, the
|
||||||
|
* Application may assume that APDU commands that it does not recognize are
|
||||||
|
* part of the security protocol and will be recognized by this {@link
|
||||||
|
* SecureChannel} instance. Therefore, the Application may either invoke this
|
||||||
|
* method prior to determining if it recognizes the command or only invoke
|
||||||
|
* this method for commands it does not recognize. In turn, this method will
|
||||||
|
* throw an {@link ISOException} if it does not recognize the APDU command as
|
||||||
|
* a security related APDU command.<p>
|
||||||
|
*
|
||||||
|
* This method is responsible for receiving the data field of APDU commands
|
||||||
|
* that are recognized (i.e. that belong to the security protocol). When
|
||||||
|
* processing a command, this method shall write response data in the
|
||||||
|
* <code>APDU</code> buffer at offset {@link ISO7816#OFFSET_CDATA} or return
|
||||||
|
* a status word under the form of an {@link ISOException}. The Application is
|
||||||
|
* responsible for outputting such response data and/or status word.<p>
|
||||||
|
*
|
||||||
|
* @param apdu the incoming <code>APDU</code> object.
|
||||||
|
*
|
||||||
|
* @return the number of bytes to be output (i.e. length of response data).
|
||||||
|
*
|
||||||
|
* @exception ISOException with a reason code reflecting some error detected
|
||||||
|
* by the underlying security protocol, or with one of the following reason
|
||||||
|
* codes if the APDU command is not recognized and does not relate to the
|
||||||
|
* underlying security protocol:<ul>
|
||||||
|
* <li>'6E00' if the class byte of the command is not recognized by this method.
|
||||||
|
* <li>'6D00' if the instruction byte of the command is not recognized by this method.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public short processSecurity(APDU apdu) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes and adds security protection to an outgoing APDU response
|
||||||
|
* according to the <em>Current Security Level</em>.<p>
|
||||||
|
*
|
||||||
|
* If the Current Security Level is {@link #NO_SECURITY_LEVEL} and is
|
||||||
|
* different from the compulsory Session Security Level (i.e. a previous
|
||||||
|
* Secure Channel Session was <a href="#sc_abort">aborted</a> but not fully
|
||||||
|
* terminated), then this method shall throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* Otherwise, this method shall attempt computing and adding a security
|
||||||
|
* protection to the outgoing message according to the Current Security Level
|
||||||
|
* (e.g. {@link #R_MAC} and/or {@link #R_ENCRYPTION}). If the Current
|
||||||
|
* Security Level does not require any protection for APDU responses (which
|
||||||
|
* includes the case where there is no Secure Channel Session currently
|
||||||
|
* open), the outgoing response message shall remain as is in the within the
|
||||||
|
* <code>baBuffer</code> byte array and the returned length shall be set to a
|
||||||
|
* value of <code>(sLength - 2)</code>, indicating the status bytes are no
|
||||||
|
* longer present at the end of the returned data.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is responsible for appending the expected status bytes
|
||||||
|
* at the end of the response data prior to invoking this method in order for
|
||||||
|
* them to be protected by secure messaging. The status bytes shall be
|
||||||
|
* subsequently removed by this method.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing response data (including the
|
||||||
|
* expected status bytes).
|
||||||
|
* @param sOffset offset of response data.
|
||||||
|
* @param sLength length of response data (including the expected status
|
||||||
|
* bytes).
|
||||||
|
*
|
||||||
|
* @return length of the reformatted (wrapped) response data, with security
|
||||||
|
* information added and status bytes removed.
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not accessible in
|
||||||
|
* the caller's context e.g. <code>baBuffer</code> is not a <em>global</em>
|
||||||
|
* array nor an array belonging to the caller context.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if writing security information
|
||||||
|
* in <code>baBuffer</code> would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short wrap(byte[] baBuffer, short sOffset, short sLength) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies and removes the security protection of an incoming APDU command
|
||||||
|
* according to the <em>Current Security Level</em>.<p>
|
||||||
|
*
|
||||||
|
* If the Current Security Level is {@link #NO_SECURITY_LEVEL} and is
|
||||||
|
* different from the compulsory Session Security Level (i.e. a previous
|
||||||
|
* Secure Channel Session was <a href="#sc_abort">aborted</a> but not fully
|
||||||
|
* terminated), then this method shall throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* If the class byte does not indicate secure messaging (according to ISO/IEC
|
||||||
|
* 7816-4), then this method shall not attempt to verify and remove any
|
||||||
|
* security protection: the incoming command shall remain as is within the
|
||||||
|
* <code>baBuffer</code> byte array and the returned length shall be set to
|
||||||
|
* the value of the <code>sLength</code> parameter.<p>
|
||||||
|
*
|
||||||
|
* If the class byte indicates secure messaging (according to ISO/IEC
|
||||||
|
* 7816-4), then this method shall attempt verifying and removing the
|
||||||
|
* security protection according to the Current Security Level:<ul>
|
||||||
|
*
|
||||||
|
* <li>If the Current Security Level is {@link #NO_SECURITY_LEVEL}, {@link
|
||||||
|
* #AUTHENTICATED} or {@link #ANY_AUTHENTICATED}, then this method shall not
|
||||||
|
* attempt to verify and remove any security protection, the incoming command
|
||||||
|
* will remain as is within the <code>baBuffer</code> byte array (with class
|
||||||
|
* byte indicating secure messaging) and the returned length shall be set to
|
||||||
|
* the value of the <code>sLength</code> parameter.
|
||||||
|
*
|
||||||
|
* <li>Incorrect verification and removal of the security protection shall
|
||||||
|
* result in an exception being thrown (see below) and the current Secure
|
||||||
|
* Channel Session being <a href="#sc_abort">aborted</a>: all information
|
||||||
|
* relating to the Secure Channel Session, except the compulsory Session
|
||||||
|
* Security Level, shall be reset.
|
||||||
|
*
|
||||||
|
* <li>Correct verification and removal of the security protection shall
|
||||||
|
* result in the incoming command being reformatted within the
|
||||||
|
* <code>baBuffer</code> byte array (a.k.a. unwrapped command). A reformatted
|
||||||
|
* case 1 or case 2 command shall include an Lc byte set to '00'.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is implicitly responsible for receiving the data field
|
||||||
|
* of the incomping APDU command prior to invoking this method.</em>
|
||||||
|
*
|
||||||
|
* <li><em>Depending on the underlying security protocol, if R_MAC is
|
||||||
|
* indicated by the Current Security Level, R-MAC computation may be
|
||||||
|
* initiated on the reformatted command once secure messaging processing of
|
||||||
|
* the incoming command has successfully completed. If no secure messaging
|
||||||
|
* processing was required for the incoming command, R-MAC computation would
|
||||||
|
* be initiated on the unmodified incoming command, appended with a Lc byte
|
||||||
|
* of '00' in the event of a case 1 or case 2 command.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the incoming APDU command.
|
||||||
|
* @param sOffset offset of the incoming APDU command, i.e. offset of the
|
||||||
|
* class byte.
|
||||||
|
* @param sLength length of the incoming APDU command, i.e length of the
|
||||||
|
* entire APDU command (header + data field).
|
||||||
|
*
|
||||||
|
* @return length of the reformatted (unwrapped) APDU command, i.e length of
|
||||||
|
* the entire APDU command (header + data field).
|
||||||
|
*
|
||||||
|
* @exception ISOException with one of the following reason codes (other
|
||||||
|
* reason codes specific to the underlying security protocol may be
|
||||||
|
* returned):<ul>
|
||||||
|
*
|
||||||
|
* <li>'6985' if the Current Security Level is {@link #NO_SECURITY_LEVEL} but
|
||||||
|
* the compulsory Session Security Level is different from {@link
|
||||||
|
* #NO_SECURITY_LEVEL}, that is, a previous Secure Channel Session was <a
|
||||||
|
* href="#sc_abort">aborted</a> but not fully terminated.
|
||||||
|
*
|
||||||
|
* <li>'6982' if this method failed
|
||||||
|
* verifying or removing the security protection of the incoming APDU
|
||||||
|
* command.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not accessible in
|
||||||
|
* the caller's context e.g. <code>baBuffer</code> is not a <em>global</em> array nor
|
||||||
|
* an array belonging to the caller context.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading the incoming APDU
|
||||||
|
* command would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short unwrap(byte [] baBuffer, short sOffset, short sLength) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts sensitive user data.<p>
|
||||||
|
*
|
||||||
|
* The decryption algorithm and cryptographic key used to decrypt data, as
|
||||||
|
* well as any padding method, are known implicitly and depend on the
|
||||||
|
* underlying security protocol.<p>
|
||||||
|
*
|
||||||
|
* If the Current Security Level is {@link #NO_SECURITY_LEVEL} or the
|
||||||
|
* necessary cryptographic keys are not available, then this method shall
|
||||||
|
* throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* Otherwise, the data shall be decrypted and the clear text data shall
|
||||||
|
* replace the encrypted data within the <code>baBuffer</code> byte
|
||||||
|
* array. The removal of padding may cause the length of the clear text data
|
||||||
|
* to be shorter than the length of the encrypted data. Any failure in the
|
||||||
|
* decryption or padding removal process shall result in an exception being
|
||||||
|
* thrown (see below).<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is responsible for removing application specific
|
||||||
|
* padding, if any. For example, if the underlying security protocol is SCP
|
||||||
|
* '02', then no padding method is defined and this method will not remove any
|
||||||
|
* padding.</em>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is responsible for checking the integrity of the
|
||||||
|
* decrypted data. </em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the data that shall be decrypted.
|
||||||
|
* @param sOffset offset of the data that shall be decrypted.
|
||||||
|
* @param sLength length of the data that shall be decrypted.
|
||||||
|
*
|
||||||
|
* @return length of the decrypted data, with any padding removed if a padding
|
||||||
|
* method is defined for the underlying security protocol.
|
||||||
|
*
|
||||||
|
* @exception ISOException with one of the following reason codes (other
|
||||||
|
* reason codes specific to the underlying security protocol may be
|
||||||
|
* returned):<ul>
|
||||||
|
*
|
||||||
|
* <li>'6985' if there is no Secure
|
||||||
|
* Channel Session currently open.
|
||||||
|
*
|
||||||
|
* <li>'6700' if the length of the data that shall
|
||||||
|
* be decrypted is not valid (e.g. underlying algorithm requires data to be
|
||||||
|
* block-aligned and input data are not).</li>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not accessible in
|
||||||
|
* the caller's context e.g. <code>baBuffer</code> is not a <em>global</em>
|
||||||
|
* array nor an array belonging to the caller context.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is
|
||||||
|
* <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading user data or writing
|
||||||
|
* decrypted data would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short decryptData(byte[] baBuffer, short sOffset, short sLength) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts sensitive user data.<p>
|
||||||
|
*
|
||||||
|
* If this method is not supported by the implementation or the underlying
|
||||||
|
* protocol does not define any sensitive data encryption mechanism, it shall
|
||||||
|
* do nothing and simply throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* The encryption algorithm and cryptographic key used to encrypt data, as
|
||||||
|
* well as any padding method, are known implicitly and depend on the
|
||||||
|
* underlying security protocol.<p>
|
||||||
|
*
|
||||||
|
* If the Current Security Level is {@link #NO_SECURITY_LEVEL} or the
|
||||||
|
* necessary cryptographic keys are not available, then this method shall
|
||||||
|
* throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* Otherwise, the data shall be padded (NOTE: depends on the underlying
|
||||||
|
* protocol) and encrypted and the encrypted data shall replace the clear
|
||||||
|
* text data within the <code>baBuffer</code> byte array. The addition of
|
||||||
|
* padding may cause the length of the encrypted data to be longer than the
|
||||||
|
* length of the clear text data. Any failure in the padding or encryption
|
||||||
|
* process shall result in an exception being thrown (see below).<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>The Application is responsible for adding application specific
|
||||||
|
* padding, if needed. For example, if the underlying security protocol is SCP
|
||||||
|
* '02', then no padding method is defined and this method by itself will not
|
||||||
|
* add any padding, which may lead to an exception being thrown (see below) if
|
||||||
|
* input data are not block-aligned.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the data that shall be encrypted.
|
||||||
|
* @param sOffset offset of the data that shall be encrypted.
|
||||||
|
* @param sLength length of the data that shall be encrypted.
|
||||||
|
*
|
||||||
|
* @return length of the encrypted data.
|
||||||
|
*
|
||||||
|
* @exception ISOException with one of the following reason codes (other
|
||||||
|
* reason codes specific to the underlying security protocol may be
|
||||||
|
* returned):<ul>
|
||||||
|
*
|
||||||
|
* <li>'6982' if this method is not
|
||||||
|
* supported by the implementation.
|
||||||
|
*
|
||||||
|
* <li>'6985' if there is no Secure Channel Session currently open.
|
||||||
|
*
|
||||||
|
* <li>'6700' if the length of the data that shall
|
||||||
|
* be encrypted is not valid (e.g. underlying algorithm requires data to be
|
||||||
|
* block-aligned and input data are not).</li>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not accessible in
|
||||||
|
* the caller's context e.g. <code>baBuffer</code> is not a <em>global</em>
|
||||||
|
* array nor an array belonging to the caller context.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is
|
||||||
|
* <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading user data or writing
|
||||||
|
* encrypted data would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short encryptData(byte[] baBuffer, short sOffset, short sLength) throws ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminates the current Secure Channel Session.
|
||||||
|
*
|
||||||
|
* This method resets both the compulsory <em>Session Security Level</em> and the
|
||||||
|
* <em>Current Security Level</em> to {@link #NO_SECURITY_LEVEL} and resets all
|
||||||
|
* information relating to the current Secure Channel Session (e.g. internal
|
||||||
|
* states, session keys).<p>
|
||||||
|
*
|
||||||
|
* This method shall not fail and shall simply return if no Secure
|
||||||
|
* Channel Session has been initiated.<p>
|
||||||
|
|
||||||
|
* Notes:<ul> <li><em>It is recommended that Applications using this interface
|
||||||
|
* invoke this method in the implementation of their
|
||||||
|
* <code>Applet.deselect()</code> method.</em> </ul>
|
||||||
|
*/
|
||||||
|
public void resetSecurity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the <em>Current Security Level</em>.
|
||||||
|
*
|
||||||
|
* An Application shall invoke this method to ensure that its own specific
|
||||||
|
* security requirements are enforced by this interface. It shall also take
|
||||||
|
* into account that the Current Security Level may change during the Secure
|
||||||
|
* Channel Session (e.g. R_MAC may be enabled or disabled during a C_MAC
|
||||||
|
* session).<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
* <li><em>The Current Security Level, as returned by this method, may be
|
||||||
|
* different for an Application invoking the method and its associated
|
||||||
|
* Security Domain depending on the underlying security protocol and the
|
||||||
|
* authenticated off-card entity's Application Provider ID (e.g. it may be
|
||||||
|
* ANY_AUTHENTICATED for the application and AUTHENTICATED for its associated
|
||||||
|
* Security Domain, and vice versa).</em>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return The Current Security Level, which is a combination of one or more
|
||||||
|
* the following constants:<ul>
|
||||||
|
* <li>{@link #NO_SECURITY_LEVEL}
|
||||||
|
* <li>{@link #AUTHENTICATED}
|
||||||
|
* <li>{@link #ANY_AUTHENTICATED}
|
||||||
|
* <li>{@link #C_MAC}
|
||||||
|
* <li>{@link #C_DECRYPTION}
|
||||||
|
* <li>{@link #R_MAC}
|
||||||
|
* <li>{@link #R_ENCRYPTION}
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public byte getSecurityLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is an extension of the {@link SecureChannel} interface that
|
||||||
|
* defines one supplementary method to update the <em>Current Security Level</em>
|
||||||
|
* during a Secure Channel Session.<p>
|
||||||
|
*
|
||||||
|
* An Application that wishes to use the {@link SecureChannelx} interface shall
|
||||||
|
* obtain a reference to a {@link SecureChannel} instance and try to cast it to
|
||||||
|
* the {@link SecureChannelx} interface. Whether the objects returned by the
|
||||||
|
* {@link GPSystem#getSecureChannel} method also implement the {@link
|
||||||
|
* SecureChannelx} interface is implementation dependent, however, this may be
|
||||||
|
* expressed as a requirement in specific GlobalPlatform configuration
|
||||||
|
* documents.
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.1: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public interface SecureChannelx extends SecureChannel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Updates the <em>Current Security Level</em>.
|
||||||
|
*
|
||||||
|
* If this method is not supported by the implementation or the underlying
|
||||||
|
* protocol does not define any sensitive data encryption mechanism, it shall
|
||||||
|
* do nothing and simply throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* The Current Security Level cannot be set below the compulsory <em>Session
|
||||||
|
* Security Level</em>, but only equal or above. It may be increased or
|
||||||
|
* decreased during a Secure Channel Session as long as it is at least equal
|
||||||
|
* to the compulsory Session Security Level.<p>
|
||||||
|
*
|
||||||
|
* If the Current Security Level is {@link #NO_SECURITY_LEVEL} or the
|
||||||
|
* cryptographic keys required by the new Current Security Level are not
|
||||||
|
* available, then this method shall throw an exception (see below).<p>
|
||||||
|
*
|
||||||
|
* The new Current Security Level shall apply for all subsequent invocations
|
||||||
|
* of {@link SecureChannel#wrap} and {@link SecureChannel#unwrap} methods,
|
||||||
|
* except when there is no current Secure Channel Session.<p>
|
||||||
|
|
||||||
|
* @param bSecurityLevel The new Current Security Level, which shall a
|
||||||
|
* combination of one or more the following constants:<ul>
|
||||||
|
|
||||||
|
* <li>{@link #NO_SECURITY_LEVEL}
|
||||||
|
* <li>{@link #AUTHENTICATED}
|
||||||
|
* <li>{@link #ANY_AUTHENTICATED}
|
||||||
|
* <li>{@link #C_MAC}
|
||||||
|
* <li>{@link #C_DECRYPTION}
|
||||||
|
* <li>{@link #R_MAC}
|
||||||
|
* <li>{@link #R_ENCRYPTION}
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception ISOException with one of the following reason codes (other
|
||||||
|
* reason codes specific to the underlying security protocol may be
|
||||||
|
* returned):<ul>
|
||||||
|
*
|
||||||
|
* <li>'6982' if this method is not supported by the implementation.
|
||||||
|
*
|
||||||
|
* <li>'6985' if there is no Secure Channel Session currently open or if the
|
||||||
|
* new Current Security Level does not comply with (i.e. goes below) the
|
||||||
|
* compulsory Session Security Level.
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public void setSecurityLevel(byte bSecurityLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
|
import javacard.framework.ISOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface is an extension of the {@link SecureChannel} interface that
|
||||||
|
* defines one supplementary method overriding the {@link
|
||||||
|
* SecureChannel#processSecurity} method.<p>
|
||||||
|
*
|
||||||
|
* An Application that wishes to use the {@link SecureChannelx2} interface shall
|
||||||
|
* obtain a reference to a {@link SecureChannel} instance and try to cast it to
|
||||||
|
* the {@link SecureChannelx2} interface. Whether the objects returned by the
|
||||||
|
* {@link GPSystem#getSecureChannel} method also implement the {@link
|
||||||
|
* SecureChannelx2} interface is implementation dependent, however, this may be
|
||||||
|
* expressed as a requirement in specific GlobalPlatform configuration
|
||||||
|
* documents.
|
||||||
|
*
|
||||||
|
* @since <ul>
|
||||||
|
* <li>export file version 1.4: initial version.
|
||||||
|
* <li>export file version 1.6: reviewed overall description of this interface.
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public interface SecureChannelx2 extends SecureChannel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Processes security related APDU commands, that is, APDU commands relating
|
||||||
|
* to the underlying security protocol.<p>
|
||||||
|
*
|
||||||
|
* This method shall be used in the same way as the {@link
|
||||||
|
* SecureChannel#processSecurity} method, except that the incoming APDU
|
||||||
|
* command shall be read from, and any response data shall be written to the
|
||||||
|
* <code>baBuffer</code> byte array.<p>
|
||||||
|
*
|
||||||
|
* Notes:<ul>
|
||||||
|
*
|
||||||
|
* <li><em>The applet is implicitly responsible for receiving the data field
|
||||||
|
* of the incomping APDU command prior to invoking this method.</em>
|
||||||
|
*
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param baBuffer byte array containing the incoming APDU command.
|
||||||
|
* @param sInOffset offset of the incoming APDU command, i.e. offset of the
|
||||||
|
* class byte.
|
||||||
|
* @param sInLength length of the incoming APDU command, i.e length of the
|
||||||
|
* entire APDU command (header + data field).
|
||||||
|
* @param sOutOffset offset within <code>baBuffer</code> where response data
|
||||||
|
* (if any) shall be written.
|
||||||
|
*
|
||||||
|
* @return the number of bytes to be output (i.e. length of response data).
|
||||||
|
*
|
||||||
|
* @exception ISOException with a reason code reflecting some error detected
|
||||||
|
* by the underlying security protocol, or with one of the following reason
|
||||||
|
* codes if the APDU command is not recognized and does not relate to the
|
||||||
|
* underlying security protocol:<ul>
|
||||||
|
* <li>'6E00' if the class byte of the command is not recognized
|
||||||
|
* by this method.
|
||||||
|
* <li>'6D00' if the instruction byte of the command is not
|
||||||
|
* recognized by this method.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @exception SecurityException if <code>baBuffer</code> is not accessible in
|
||||||
|
* the caller's context e.g. <code>baBuffer</code> is not a <em>global</em> array nor
|
||||||
|
* an array belonging to the caller context.
|
||||||
|
* @exception NullPointerException if <code>baBuffer</code> is <code>null</code>.
|
||||||
|
* @exception ArrayIndexOutOfBoundsException if reading the incoming APDU
|
||||||
|
* command would cause access of data outside array bounds.
|
||||||
|
*/
|
||||||
|
public short processSecurity(byte[] baBuffer, short sInOffset, short sInLength, short sOutOffset) throws ISOException;
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Provides a framework of classes and interfaces related to core services
|
||||||
|
* defined for smart cards based on GlobalPlatform specifications.
|
||||||
|
* @version This documentation describes API elements and behaviors associated
|
||||||
|
* with version 1.6 of this package export file.
|
||||||
|
*/
|
||||||
|
package org.globalplatform;
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ if not "%JC_HOME%" == "" goto doit
|
|||||||
:doit
|
:doit
|
||||||
set _CLASSES=%JC_HOME%\lib\apduio.jar;%JC_HOME%\lib\apdutool.jar;%JC_HOME%\lib\jcwde.jar;%JC_HOME%\lib\converter.jar;%JC_HOME%\lib\scriptgen.jar;%JC_HOME%\lib\offcardverifier.jar;%JC_HOME%\lib\api.jar;%JC_HOME%\lib\installer.jar;%JC_HOME%\lib\capdump.jar;%JC_HOME%\samples\classes;%CLASSPATH%;
|
set _CLASSES=%JC_HOME%\lib\apduio.jar;%JC_HOME%\lib\apdutool.jar;%JC_HOME%\lib\jcwde.jar;%JC_HOME%\lib\converter.jar;%JC_HOME%\lib\scriptgen.jar;%JC_HOME%\lib\offcardverifier.jar;%JC_HOME%\lib\api.jar;%JC_HOME%\lib\installer.jar;%JC_HOME%\lib\capdump.jar;%JC_HOME%\samples\classes;%CLASSPATH%;
|
||||||
|
|
||||||
%JAVA_HOME%\bin\java -classpath %_CLASSES% com.sun.javacard.apdutool.Main %*
|
"%JAVA_HOME%\bin\java" -classpath %_CLASSES% com.sun.javacard.apdutool.Main %*
|
||||||
goto end
|
goto end
|
||||||
|
|
||||||
:end
|
:end
|
||||||
BIN
build_tools/Tools/jcdk222/bin/cref.eeprom
Normal file
BIN
build_tools/Tools/jcdk222/bin/cref.eeprom
Normal file
Binary file not shown.
@@ -18,7 +18,7 @@ if not "%JC_HOME%" == "" goto doit
|
|||||||
:doit
|
:doit
|
||||||
set _CLASSES=%JC_HOME%\lib\apduio.jar;%JC_HOME%\lib\apdutool.jar;%JC_HOME%\lib\jcwde.jar;%JC_HOME%\lib\converter.jar;%JC_HOME%\lib\scriptgen.jar;%JC_HOME%\lib\offcardverifier.jar;%JC_HOME%\lib\api.jar;%JC_HOME%\lib\installer.jar;%JC_HOME%\lib\capdump.jar;%JC_HOME%\samples\classes;%CLASSPATH%;
|
set _CLASSES=%JC_HOME%\lib\apduio.jar;%JC_HOME%\lib\apdutool.jar;%JC_HOME%\lib\jcwde.jar;%JC_HOME%\lib\converter.jar;%JC_HOME%\lib\scriptgen.jar;%JC_HOME%\lib\offcardverifier.jar;%JC_HOME%\lib\api.jar;%JC_HOME%\lib\installer.jar;%JC_HOME%\lib\capdump.jar;%JC_HOME%\samples\classes;%CLASSPATH%;
|
||||||
|
|
||||||
%JAVA_HOME%\bin\java -classpath %_CLASSES% com.sun.javacard.scriptgen.Main %*
|
"%JAVA_HOME%"\bin\java -classpath %_CLASSES% com.sun.javacard.scriptgen.Main %*
|
||||||
goto end
|
goto end
|
||||||
|
|
||||||
:end
|
:end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user