You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

344 lines
8.9 KiB
Java

package gtpa.brs.security;
import gtpa.brs.security.KISA_SEED;
public class KISA_SEED_CCM
{
private static int BLOCK_SIZE_SEED = 16;
private static void SHIFTR8(int[] x)
{
x[3] = ((x[3] >> 8) & 0x00FFFFFF) ^ ((x[2] << 24) & 0xFF000000);
x[2] = ((x[2] >> 8) & 0x00FFFFFF) ^ ((x[1] << 24) & 0xFF000000);
x[1] = ((x[1] >> 8) & 0x00FFFFFF) ^ ((x[0] << 24) & 0xFF000000);
x[0] = ((x[0] >> 8) & 0x00FFFFFF);
}
private static void SHIFTR16(int[] x)
{
x[3] = ((x[3] >> 16) & 0x0000FFFF) ^ ((x[2] << 16) & 0xFFFF0000);
x[2] = ((x[2] >> 16) & 0x0000FFFF) ^ ((x[1] << 16) & 0xFFFF0000);
x[1] = ((x[1] >> 16) & 0x0000FFFF) ^ ((x[0] << 16) & 0xFFFF0000);
x[0] = ((x[0] >> 16) & 0x0000FFFF);
}
private static void XOR128(int[] R, int[] A, int[] B)
{
R[0] = A[0] ^ B[0];
R[1] = A[1] ^ B[1];
R[2] = A[2] ^ B[2];
R[3] = A[3] ^ B[3];
}
private static void INCREASE(int[] ctr)
{
if (ctr[3] == 0xFFFFFFFF)
{
ctr[2]++;
ctr[3] = 0;
}
else
{
ctr[3]++;
}
}
private static void ZERO128(int[] a) { a[0] = 0x00000000; a[1] = 0x00000000; a[2] = 0x00000000; a[3] = 0x00000000; }
private static void Byte2Word(int[] dst, byte[] src, int src_offset, int srcLen)
{
int i = 0;
int remain = 0;
for (i = 0; i < srcLen; i++)
{
remain = i & 3;
if (remain == 0)
dst[i >> 2] = ((src[src_offset + i] & 0x0FF) << 24);
else if (remain == 1)
dst[i >> 2] ^= ((src[src_offset + i] & 0x0FF) << 16);
else if (remain == 2)
dst[i >> 2] ^= ((src[src_offset + i] & 0x0FF) << 8);
else
dst[i >> 2] ^= ( src[src_offset + i] & 0x0FF);
}
}
private static void Word2Byte(byte[] dst, int dst_offset, int[] src, int srcLen)
{
int i = 0;
int remain = 0;
for (i = 0; i < srcLen; i++)
{
remain = i & 3;
if (remain == 0)
dst[dst_offset + i] = (byte)(src[i >> 2] >> 24);
else if (remain == 1)
dst[dst_offset + i] = (byte)(src[i >> 2] >> 16);
else if (remain == 2)
dst[dst_offset + i] = (byte)(src[i >> 2] >> 8);
else
dst[dst_offset + i] = (byte) src[i >> 2];
}
}
public int SEED_CCM_Encryption(
byte[] ct,
byte[] pt, int ptLen,
int macLen,
byte[] nonce, int nonceLen,
byte[] aad, int aadLen,
byte[] mKey)
{
int[] CTR_in = new int[4];
int[] CTR_out = new int[4];
int[] CBC_in = new int[4];
int[] CBC_out = new int[4];
int[] MAC = new int[4];
int[] tmp = new int[8];
int[] rKey = new int[100];
int i, flag, tmpLen = 0;
gtpa.brs.security.KISA_SEED seed = new gtpa.brs.security.KISA_SEED();
if (macLen > BLOCK_SIZE_SEED)
return 1;
seed.SEED_KeySched(mKey, rKey);
Byte2Word(CTR_in, nonce, 0, nonceLen);
SHIFTR8(CTR_in);
flag = 14 - nonceLen;
CTR_in[0] ^= (flag << 24);
seed.SEED_Encrypt(MAC, CTR_in, rKey);
for (i = 0; i < ptLen; i += BLOCK_SIZE_SEED)
{
INCREASE(CTR_in);
ZERO128(tmp);
if ((ptLen - i) < BLOCK_SIZE_SEED)
Byte2Word(tmp, pt, i, ptLen - i);
else
Byte2Word(tmp, pt, i, BLOCK_SIZE_SEED);
seed.SEED_Encrypt(CTR_out, CTR_in, rKey);
XOR128(tmp, CTR_out, tmp);
if ((ptLen - i) < BLOCK_SIZE_SEED)
Word2Byte(ct, i, tmp, ptLen - i);
else
Word2Byte(ct, i, tmp, BLOCK_SIZE_SEED);
}
Byte2Word(CBC_in, nonce, 0, nonceLen);
SHIFTR8(CBC_in);
if (aadLen > 0)
flag = 0x00000040;
else
flag = 0x00000000;
flag ^= ((macLen - 2) >> 1) << 3;
flag ^= 14 - nonceLen;
CBC_in[0] ^= (flag << 24);
CBC_in[3] ^= ptLen;
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
if (aadLen > 0)
{
if (aadLen > 14)
tmpLen = 14;
else
tmpLen = aadLen;
ZERO128(CBC_in);
Byte2Word(CBC_in, aad, 0, tmpLen);
SHIFTR16(CBC_in);
CBC_in[0] ^= ((aadLen << 16) & 0xFFFF0000);
XOR128(CBC_in, CBC_in, CBC_out);
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
for (i = tmpLen; i < aadLen; i += BLOCK_SIZE_SEED)
{
ZERO128(CBC_in);
if ((aadLen - i) < BLOCK_SIZE_SEED)
Byte2Word(CBC_in, aad, i, aadLen - i);
else
Byte2Word(CBC_in, aad, i, BLOCK_SIZE_SEED);
XOR128(CBC_in, CBC_in, CBC_out);
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
}
}
for (i = 0; i < ptLen; i += BLOCK_SIZE_SEED)
{
ZERO128(tmp);
if ((ptLen - i) < BLOCK_SIZE_SEED)
Byte2Word(tmp, pt, i, ptLen - i);
else
Byte2Word(tmp, pt, i, BLOCK_SIZE_SEED);
XOR128(CBC_in, tmp, CBC_out);
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
}
XOR128(MAC, MAC, CBC_out);
Word2Byte(ct, ptLen, MAC, macLen);
return ptLen + macLen;
}
public int SEED_CCM_Decryption(
byte[] pt,
byte[] ct, int ctLen,
int macLen,
byte[] nonce, int nonceLen,
byte[] aad, int aadLen,
byte[] mKey)
{
int[] CTR_in = new int[4];
int[] CTR_out = new int[4];
int[] CBC_in = new int[4];
int[] CBC_out = new int[4];
int[] MAC = new int[4];
byte[] tMAC = new byte[16];
int[] tmp = new int[8];
int[] rKey = new int[32];
int i, j, flag, tmpLen = 0;
gtpa.brs.security.KISA_SEED seed = new KISA_SEED();
if (macLen > BLOCK_SIZE_SEED)
return 1;
seed.SEED_KeySched(mKey, rKey);
Byte2Word(CTR_in, nonce, 0, nonceLen);
SHIFTR8(CTR_in);
flag = 14 - nonceLen;
CTR_in[0] ^= (flag << 24);
seed.SEED_Encrypt(MAC, CTR_in, rKey);
for (i = 0; i < ctLen - macLen; i += BLOCK_SIZE_SEED)
{
INCREASE(CTR_in);
ZERO128(tmp);
if ((ctLen - macLen - i) < BLOCK_SIZE_SEED)
Byte2Word(tmp, ct, i, ctLen - macLen - i);
else
Byte2Word(tmp, ct, i, BLOCK_SIZE_SEED);
seed.SEED_Encrypt(CTR_out, CTR_in, rKey);
XOR128(tmp, CTR_out, tmp);
if ((ctLen - macLen - i) < BLOCK_SIZE_SEED)
Word2Byte(pt, i, tmp, ctLen - macLen - i);
else
Word2Byte(pt, i, tmp, BLOCK_SIZE_SEED);
}
Byte2Word(CBC_in, nonce, 0, nonceLen);
SHIFTR8(CBC_in);
if (aadLen > 0)
flag = 0x00000040;
else
flag = 0x00000000;
flag ^= ((macLen - 2) >> 1) << 3;
flag ^= 14 - nonceLen;
CBC_in[0] ^= (flag << 24);
CBC_in[3] ^= ctLen - macLen;
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
if (aadLen > 0)
{
if (aadLen > 14)
tmpLen = 14;
else
tmpLen = aadLen;
ZERO128(CBC_in);
Byte2Word(CBC_in, aad, 0, tmpLen);
SHIFTR16(CBC_in);
CBC_in[0] ^= (aadLen << 16);
XOR128(CBC_in, CBC_in, CBC_out);
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
for (i = tmpLen; i < aadLen; i += BLOCK_SIZE_SEED)
{
ZERO128(CBC_in);
if ((aadLen - i) < BLOCK_SIZE_SEED)
Byte2Word(CBC_in, aad, i, aadLen - i);
else
Byte2Word(CBC_in, aad, i, BLOCK_SIZE_SEED);
XOR128(CBC_in, CBC_in, CBC_out);
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
}
}
for (i = 0; i < ctLen - macLen; i += BLOCK_SIZE_SEED)
{
ZERO128(tmp);
if ((ctLen - macLen - i) < BLOCK_SIZE_SEED)
Byte2Word(tmp, pt, i, ctLen - macLen - i);
else
Byte2Word(tmp, pt, i, BLOCK_SIZE_SEED);
XOR128(CBC_in, tmp, CBC_out);
seed.SEED_Encrypt(CBC_out, CBC_in, rKey);
}
XOR128(MAC, MAC, CBC_out);
Word2Byte(tMAC, 0, MAC, macLen);
for (i = 0; i < macLen; i++)
{
if (tMAC[i] != ct[ctLen - macLen + i])
{
for (j = 0; j < ctLen - macLen; j++)
pt[j] = 0;
return 1;
}
}
return ctLen - macLen;
}
}