www.pudn.com > loki.zip > loki.c


 
/* This is an independent implementation of the encryption algorithm:   */ 
/*                                                                      */ 
/*         LOKI97 by Brown and Pieprzyk                                 */ 
/*                                                                      */ 
/* which is a candidate algorithm in the Advanced Encryption Standard   */ 
/* programme of the US National Institute of Standards and Technology.  */ 
/*                                                                      */ 
/* Copyright in this implementation is held by Dr B R Gladman but I     */ 
/* hereby give permission for its free direct or derivative use subject */ 
/* to acknowledgment of its origin and compliance with any conditions   */ 
/* that the originators of the algorithm place on its exploitation.     */ 
/*                                                                      */ 
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999     */ 
 
/* Timing data for LOKI97 (loki.c) 
 
Core timing without I/O endian conversion: 
 
128 bit key: 
Key Setup:    7430 cycles 
Encrypt:      2134 cycles =    12.0 mbits/sec 
Decrypt:      2192 cycles =    11.7 mbits/sec 
Mean:         2163 cycles =    11.8 mbits/sec 
 
192 bit key: 
Key Setup:    7303 cycles 
Encrypt:      2138 cycles =    12.0 mbits/sec 
Decrypt:      2189 cycles =    11.7 mbits/sec 
Mean:         2164 cycles =    11.8 mbits/sec 
 
256 bit key: 
Key Setup:    7166 cycles 
Encrypt:      2131 cycles =    12.0 mbits/sec 
Decrypt:      2184 cycles =    11.7 mbits/sec 
Mean:         2158 cycles =    11.9 mbits/sec 
 
Full timing with I/O endian conversion: 
 
128 bit key: 
Key Setup:    7582 cycles 
Encrypt:      2174 cycles =    11.8 mbits/sec 
Decrypt:      2235 cycles =    11.5 mbits/sec 
Mean:         2205 cycles =    11.6 mbits/sec 
 
192 bit key: 
Key Setup:    7477 cycles 
Encrypt:      2167 cycles =    11.8 mbits/sec 
Decrypt:      2223 cycles =    11.5 mbits/sec 
Mean:         2195 cycles =    11.7 mbits/sec 
 
256 bit key: 
Key Setup:    7365 cycles 
Encrypt:      2177 cycles =    11.8 mbits/sec 
Decrypt:      2194 cycles =    11.7 mbits/sec 
Mean:         2186 cycles =    11.7 mbits/sec 
 
*/ 
 
#define BYTE_SWAP 
 
#ifdef CORE_TIME 
#  undef BYTE_SWAP 
#endif 
 
#include "../std_defs.h" 
 
static char *alg_name[] = { "loki", "loki.c", "loki97" }; 
 
char **cipher_name() 
{ 
    return alg_name; 
}; 
 
#define S1_SIZE     13 
#define S1_LEN      (1 << S1_SIZE) 
#define S1_MASK     (S1_LEN - 1) 
#define S1_HMASK    (S1_MASK & ~0xff) 
#define S1_POLY     0x2911 
 
#define S2_SIZE     11 
#define S2_LEN      (1 << S2_SIZE) 
#define S2_MASK     (S2_LEN - 1) 
#define S2_HMASK    (S2_MASK & ~0xff) 
#define S2_POLY     0x0aa7 
 
u4byte  delta[2] = { 0x7f4a7c15, 0x9e3779b9 }; 
 
u1byte  sb1[S1_LEN];    // GF(2^11) S box 
u1byte  sb2[S2_LEN];    // GF(2^11) S box 
u4byte  prm[256][2]; 
u4byte  init_done = 0; 
 
u4byte  l_key[96]; 
 
#define add_eq(x,y)     (x)[1] += (y)[1] + (((x)[0] += (y)[0]) < (y)[0] ? 1 : 0) 
#define sub_eq(x,y)     xs = (x)[0]; (x)[1] -= (y)[1] + (((x)[0] -= (y)[0]) > xs ? 1 : 0)    
 
u4byte ff_mult(u4byte a, u4byte b, u4byte tpow, u4byte mpol) 
{   u4byte  r, s, m; 
 
    r = s = 0; m = (1 << tpow);  
 
    while(b) 
    { 
        if(b & 1) 
         
            s ^= a; 
             
        b >>= 1; a <<= 1; 
         
        if(a & m) 
         
            a ^= mpol; 
    } 
 
    return s; 
}; 
 
void init_tables(void) 
{   u4byte  i, j, v; 
 
    // initialise S box 1 
 
    for(i = 0; i < S1_LEN; ++i) 
    { 
        j = v = i ^ S1_MASK; v = ff_mult(v, j, S1_SIZE, S1_POLY); 
        sb1[i] = (u1byte)ff_mult(v, j, S1_SIZE, S1_POLY); 
    }  
    // initialise S box 2 
 
    for(i = 0; i < S2_LEN; ++i) 
    { 
        j = v = i ^ S2_MASK; v = ff_mult(v, j, S2_SIZE, S2_POLY); 
        sb2[i] = (u1byte)ff_mult(v, j, S2_SIZE, S2_POLY); 
    } 
 
    // initialise permutation table 
 
    for(i = 0; i < 256; ++i) 
    { 
        prm[i][0] = ((i &  1) << 7) | ((i &  2) << 14) | ((i &  4) << 21) | ((i &   8) << 28); 
        prm[i][1] = ((i & 16) << 3) | ((i & 32) << 10) | ((i & 64) << 17) | ((i & 128) << 24); 
    } 
}; 
 
void f_fun(u4byte res[2], const u4byte in[2], const u4byte key[2]) 
{   u4byte  i, tt[2], pp[2]; 
 
    tt[0] = in[0] & ~key[0] | in[1] & key[0]; 
    tt[1] = in[1] & ~key[0] | in[0] & key[0]; 
 
    i = sb1[((tt[1] >> 24) | (tt[0] << 8)) & S1_MASK]; 
    pp[0]  = prm[i][0] >> 7; pp[1]  = prm[i][1] >> 7; 
    i = sb2[(tt[1] >> 16) & S2_MASK]; 
    pp[0] |= prm[i][0] >> 6; pp[1] |= prm[i][1] >> 6; 
    i = sb1[(tt[1] >>  8) & S1_MASK]; 
    pp[0] |= prm[i][0] >> 5; pp[1] |= prm[i][1] >> 5; 
    i = sb2[tt[1] & S2_MASK];  
    pp[0] |= prm[i][0] >> 4; pp[1] |= prm[i][1] >> 4; 
    i = sb2[((tt[0] >> 24) | (tt[1] << 8)) & S2_MASK]; 
    pp[0] |= prm[i][0] >> 3; pp[1] |= prm[i][1] >> 3; 
    i = sb1[(tt[0] >> 16) & S1_MASK];  
    pp[0] |= prm[i][0] >> 2; pp[1] |= prm[i][1] >> 2; 
    i = sb2[(tt[0] >>  8) & S2_MASK];       
    pp[0] |= prm[i][0] >> 1; pp[1] |= prm[i][1] >> 1; 
    i = sb1[tt[0] & S1_MASK];           
    pp[0] |= prm[i][0];      pp[1] |= prm[i][1]; 
 
    res[0] ^=  sb1[byte(pp[0], 0) | (key[1] <<  8) & S1_HMASK] 
            | (sb1[byte(pp[0], 1) | (key[1] <<  3) & S1_HMASK] << 8) 
            | (sb2[byte(pp[0], 2) | (key[1] >>  2) & S2_HMASK] << 16) 
            | (sb2[byte(pp[0], 3) | (key[1] >>  5) & S2_HMASK] << 24); 
    res[1] ^=  sb1[byte(pp[1], 0) | (key[1] >>  8) & S1_HMASK] 
            | (sb1[byte(pp[1], 1) | (key[1] >> 13) & S1_HMASK] << 8) 
            | (sb2[byte(pp[1], 2) | (key[1] >> 18) & S2_HMASK] << 16) 
            | (sb2[byte(pp[1], 3) | (key[1] >> 21) & S2_HMASK] << 24); 
}; 
 
u4byte *set_key(const u4byte in_key[], const u4byte key_len) 
{   u4byte  i, k1[2], k2[2], k3[2], k4[2], del[2], tt[2], sk[2]; 
 
    if(!init_done) 
    { 
        init_tables(); init_done = 1; 
    } 
 
    k4[0] = io_swap(in_key[1]); k4[1] = io_swap(in_key[0]); 
    k3[0] = io_swap(in_key[3]); k3[1] = io_swap(in_key[2]); 
 
    switch ((key_len + 63) / 64) 
    { 
    case 2: 
        k2[0] = 0; k2[1] = 0; f_fun(k2, k3, k4); 
        k1[0] = 0; k1[1] = 0; f_fun(k1, k4, k3); 
        break; 
    case 3: 
        k2[0] = io_swap(in_key[5]); k2[1] = io_swap(in_key[4]); 
        k1[0] = 0; k1[1] = 0; f_fun(k1, k4, k3); 
        break; 
    case 4:  
        k2[0] = io_swap(in_key[5]); k2[1] = io_swap(in_key[4]); 
        k1[0] = io_swap(in_key[7]); k1[1] = io_swap(in_key[6]); 
    } 
 
    del[0] = delta[0]; del[1] = delta[1]; 
 
    for(i = 0; i < 48; ++i) 
    { 
        tt[0] = k1[0]; tt[1] = k1[1];  
        add_eq(tt, k3); add_eq(tt, del); add_eq(del, delta); 
        sk[0] = k4[0]; sk[1] = k4[1]; 
        k4[0] = k3[0]; k4[1] = k3[1]; 
        k3[0] = k2[0]; k3[1] = k2[1]; 
        k2[0] = k1[0]; k2[1] = k1[1]; 
        k1[0] = sk[0]; k1[1] = sk[1]; 
        f_fun(k1, tt, k3); 
        l_key[i + i] = k1[0]; l_key[i + i + 1] = k1[1]; 
    } 
 
    return l_key; 
}; 
 
#define r_fun(l,r,k)        \ 
    add_eq((l),(k));        \ 
    f_fun((r),(l),(k) + 2); \ 
    add_eq((l), (k) + 4) 
 
void encrypt(const u4byte in_blk[4], u4byte out_blk[4]) 
{   u4byte  blk[4]; 
 
    blk[3] = io_swap(in_blk[0]); blk[2] = io_swap(in_blk[1]); 
    blk[1] = io_swap(in_blk[2]); blk[0] = io_swap(in_blk[3]); 
 
    r_fun(blk, blk + 2, l_key +  0); 
    r_fun(blk + 2, blk, l_key +  6); 
    r_fun(blk, blk + 2, l_key + 12); 
    r_fun(blk + 2, blk, l_key + 18); 
    r_fun(blk, blk + 2, l_key + 24); 
    r_fun(blk + 2, blk, l_key + 30); 
    r_fun(blk, blk + 2, l_key + 36); 
    r_fun(blk + 2, blk, l_key + 42); 
    r_fun(blk, blk + 2, l_key + 48); 
    r_fun(blk + 2, blk, l_key + 54); 
    r_fun(blk, blk + 2, l_key + 60); 
    r_fun(blk + 2, blk, l_key + 66); 
    r_fun(blk, blk + 2, l_key + 72); 
    r_fun(blk + 2, blk, l_key + 78); 
    r_fun(blk, blk + 2, l_key + 84); 
    r_fun(blk + 2, blk, l_key + 90); 
 
    out_blk[3] = io_swap(blk[2]); out_blk[2] = io_swap(blk[3]); 
    out_blk[1] = io_swap(blk[0]); out_blk[0] = io_swap(blk[1]); 
}; 
 
#define ir_fun(l,r,k)       \ 
    sub_eq((l),(k) + 4);    \ 
    f_fun((r),(l),(k) + 2); \ 
    sub_eq((l),(k)) 
 
void decrypt(const u4byte in_blk[4], u4byte out_blk[4]) 
{   u4byte  blk[4], xs; 
 
    blk[3] = io_swap(in_blk[0]); blk[2] = io_swap(in_blk[1]); 
    blk[1] = io_swap(in_blk[2]); blk[0] = io_swap(in_blk[3]); 
 
    ir_fun(blk, blk + 2, l_key + 90);  
    ir_fun(blk + 2, blk, l_key + 84); 
    ir_fun(blk, blk + 2, l_key + 78);  
    ir_fun(blk + 2, blk, l_key + 72); 
    ir_fun(blk, blk + 2, l_key + 66);  
    ir_fun(blk + 2, blk, l_key + 60); 
    ir_fun(blk, blk + 2, l_key + 54);  
    ir_fun(blk + 2, blk, l_key + 48); 
    ir_fun(blk, blk + 2, l_key + 42);  
    ir_fun(blk + 2, blk, l_key + 36); 
    ir_fun(blk, blk + 2, l_key + 30);  
    ir_fun(blk + 2, blk, l_key + 24); 
    ir_fun(blk, blk + 2, l_key + 18);  
    ir_fun(blk + 2, blk, l_key + 12); 
    ir_fun(blk, blk + 2, l_key +  6);  
    ir_fun(blk + 2, blk, l_key); 
 
    out_blk[3] = io_swap(blk[2]); out_blk[2] = io_swap(blk[3]); 
    out_blk[1] = io_swap(blk[0]); out_blk[0] = io_swap(blk[1]);    
};