ARIA 최적화 구현 분석하기
지금 캡스톤 디자인의 목표가 ARIA의 White box구현인데 생각보다 코딩이 잘 안되서, ARIA 최적화를 분석 먼저하고 코딩을 진행하려고 한다.
소스 코드는 KISA에 공개된 코드이고 내용물안에 aria 050117.c라는 파일 안에 있는 것을 분석을 진행한다.
일단 기본적으로는 메크로를 이용한 코드여서 생각보다 눈에 잘안들어와서 블로그에 따로 정리를 해두려고 한다.
void Crypt(const Byte *i, int Nr, const Byte *rk, Byte *o) {
register Word t0, t1, t2, t3;
WordLoad(WO(i,0), t0); WordLoad(WO(i,1), t1);
WordLoad(WO(i,2), t2); WordLoad(WO(i,3), t3);
if (Nr > 12) {KXL FO KXL FE}
if (Nr > 14) {KXL FO KXL FE}
KXL FO KXL FE KXL FO KXL FE KXL FO KXL FE
KXL FO KXL FE KXL FO KXL FE KXL FO KXL
}
기본 암호화 함수의 틀이다. 처음 코드보고 이게 뭐지 했다. 내가 아는 C랑 생각보다 많이 달라서, 조금 뭔 코드가 이렇냐 생각을 했다. 하나하나 분석해보자
기본적으로 Word는 32bytes연산으로 구성되어있다. 그리고 KXL , F0 , FE연산으로 구현이 되어 있다. 그러면 암호화는 끝이다.
1. KXL
#define KXL { \
t0^=WO(rk,0); t1^=WO(rk,1); t2^=WO(rk,2); t3^=WO(rk,3); \
rk += 16; \
}
다음과 같이 구현이 되어 있다.
t0 변수들은 32bytes로 구성이 되어 있고 rk와 XOR해주는 AddRoundKey 부분이다 .
2. FO & FE
#define FO {SBL1_M(t0,t1,t2,t3) MM(t0,t1,t2,t3) P(t0,t1,t2,t3) MM(t0,t1,t2,t3)}
#define FE {SBL2_M(t0,t1,t2,t3) MM(t0,t1,t2,t3) P(t2,t3,t0,t1) MM(t0,t1,t2,t3)}
ARIA는 특이하게도 짝수 연산과 홀수 Round의 연산이 다르게 진행이 된다. 따라서 두개의 함수를 구성해준다.
2-1. SBL1_M & SBL1_M
#define SBL1_M(T0,T1,T2,T3) { \
T0=S1[BRF(T0,24)]^S2[BRF(T0,16)]^X1[BRF(T0,8)]^X2[BRF(T0,0)]; \
T1=S1[BRF(T1,24)]^S2[BRF(T1,16)]^X1[BRF(T1,8)]^X2[BRF(T1,0)]; \
T2=S1[BRF(T2,24)]^S2[BRF(T2,16)]^X1[BRF(T2,8)]^X2[BRF(T2,0)]; \
T3=S1[BRF(T3,24)]^S2[BRF(T3,16)]^X1[BRF(T3,8)]^X2[BRF(T3,0)]; \
}
#define SBL2_M(T0,T1,T2,T3) { \
T0=X1[BRF(T0,24)]^X2[BRF(T0,16)]^S1[BRF(T0,8)]^S2[BRF(T0,0)]; \
T1=X1[BRF(T1,24)]^X2[BRF(T1,16)]^S1[BRF(T1,8)]^S2[BRF(T1,0)]; \
T2=X1[BRF(T2,24)]^X2[BRF(T2,16)]^S1[BRF(T2,8)]^S2[BRF(T2,0)]; \
T3=X1[BRF(T3,24)]^X2[BRF(T3,16)]^S1[BRF(T3,8)]^S2[BRF(T3,0)]; \
}
ARIA는 4개의 Sbox를 사용하는 데, S1 , S2 그리고 S1,S2의 역원을 이용한다. 그래서 각 블록마다 다른 연산이 들어가야한다.
#define BRF(T,R) ((Byte)((T)>>(R)))
BRF는 다음과 같고 T를 Rbit 만큼 밀어주고 0xff 를 and연산을 해주는 것이다. 즉 S1에 들어가는 X는 8비트 이다.
그리고 S1과 같은 테이블은 다음과 같이 정의 되어있다.
#define AAA(V) 0x ## 00 ## V ## V ## V
#define BBB(V) 0x ## V ## 00 ## V ## V
#define CCC(V) 0x ## V ## V ## 00 ## V
#define DDD(V) 0x ## V ## V ## V ## 00
#define XX(NNN,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \
NNN(x0),NNN(x1),NNN(x2),NNN(x3),NNN(x4),NNN(x5),NNN(x6),NNN(x7), \
NNN(x8),NNN(x9),NNN(xa),NNN(xb),NNN(xc),NNN(xd),NNN(xe),NNN(xf)
즉 x1에 8비트 xx가 들어오면 0x00xxxxxx 같은 32비트 출력을 하게된다. S1과 같은 테이블은 32bit를 구현한게 4개 만들면된다.
S1 => 0x00 AA AA AA
S2 => 0xAA 00 AA AA
X1 => 0xAA AA 00 AA
X2 => 0xAA AA AA 00
그러면