www.pudn.com > sepent2.zip > b0_serpent.c


 
/* This is an independent implementation of the Serpent encryption  */ 
/* algorithm designed by Ross Anderson, Eli Biham and Lars Knudsen  */ 
/* and offered as a candidate algorithm for the US NIST Advanced    */ 
/* Encryption Standard (AES) effort. The algorithm is subject to    */ 
/* Patent action by its designers but royalty free use will be      */ 
/* offered to all conforming implementations.                       */ 
/*                                                                  */ 
/* 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.                         */ 
/*                                                                  */ 
/* This implementation achieves a speed of over 25 Mbits/second on  */ 
/* a 200Mhz Pentium Pro machine but does so by unrolling all the    */ 
/* loops as well as fully inlining the S box and linear mixing code */ 
/* As a result the binary code size of the encryption code is large */ 
/* (about 16 kbytes on a Pentium Pro)                               */ 
/*                                                                  */ 
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 25th June 1998    */ 
/*                                                                  */ 
 
#include "../std_defs.h" 
#include "f_box.h" 
 
static char *alg_name = "SERPENT"; 
 
char *cipher_name() 
{ 
    return alg_name; 
} 
 
#ifndef _MSC_VER 
 
#define rotr(x,n)   (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) 
#define rotl(x,n)   (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) 
 
#else 
 
#include  
 
#pragma intrinsic(_lrotr,_lrotl) 
#define rotr(x,n)   _lrotr(x,n) 
#define rotl(x,n)   _lrotl(x,n) 
 
#endif 
 
#define k_xor(r,a,b,c,d)        \ 
{   (a) ^= l_key[4 * (r) +  8]; \ 
    (b) ^= l_key[4 * (r) +  9]; \ 
    (c) ^= l_key[4 * (r) + 10]; \ 
    (d) ^= l_key[4 * (r) + 11]; \ 
} 
 
#define k_set(r,a,b,c,d)        \ 
{   (a) = l_key[4 * (r) +  8];  \ 
    (b) = l_key[4 * (r) +  9];  \ 
    (c) = l_key[4 * (r) + 10];  \ 
    (d) = l_key[4 * (r) + 11];  \ 
} 
 
#define k_get(r,a,b,c,d)        \ 
{   l_key[4 * (r) +  8] = (a);  \ 
    l_key[4 * (r) +  9] = (b);  \ 
    l_key[4 * (r) + 10] = (c);  \ 
    l_key[4 * (r) + 11] = (d);  \ 
} 
 
/* the linear transformation and its inverse    */ 
 
#define rot(a,b,c,d)            \ 
{   (a) = rotl((a), 13);        \ 
    (c) = rotl((c), 3);         \ 
    (b) ^= (a) ^ (c);           \ 
    (d) ^= (c) ^ ((a) << 3);    \ 
    (b) = rotl((b), 1);         \ 
    (d) = rotl((d), 7);         \ 
    (a) ^= (b) ^ (d);           \ 
    (c) ^= (d) ^ ((b) << 7);    \ 
    (a) = rotl((a), 5);         \ 
    (c) = rotl((c), 22);        \ 
} 
 
#define irot(a,b,c,d)           \ 
{   (c) = rotr((c), 22);        \ 
    (a) = rotr((a), 5);         \ 
    (c) ^= (d) ^ ((b) << 7);    \ 
    (a) ^= (b) ^ (d);           \ 
    (d) = rotr((d), 7);         \ 
    (b) = rotr((b), 1);         \ 
    (d) ^= (c) ^ ((a) << 3);    \ 
    (b) ^= (a) ^ (c);           \ 
    (c) = rotr((c), 3);         \ 
    (a) = rotr((a), 13);        \ 
} 
 
u4byte  l_key[140]; /* storage for the key schedule         */ 
 
/* initialise the key schedule from the user supplied key   */ 
 
u4byte *set_key(u4byte key_blk[], u4byte key_len) 
{ 
    u4byte  i,lk,a,b,c,d,e,f,g,h; 
 
    if(key_len < 0 || key_len > 256) 
 
        return (u4byte*)0; 
 
    i = 0;  
     
    while(i < (key_len + 31) / 32) 
    { 
        l_key[i] = key_blk[i]; i++; 
    } 
 
    if(key_len < 256) 
    { 
        while(i < 8) 
 
            l_key[i++] = 0; 
 
        i = key_len / 32; lk = 1 << key_len % 32;  
 
        l_key[i] = l_key[i] & (lk - 1) | lk; 
    } 
 
    for(i = 0; i < 132; ++i) 
    { 
        lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5]  
                                ^ l_key[i + 7] ^ 0x9e3779b9 ^ i; 
 
        l_key[i + 8] = (lk << 11) | (lk >> 21);  
    } 
 
    k_set( 0,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( 0,e,f,g,h); 
    k_set( 1,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( 1,e,f,g,h); 
    k_set( 2,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get( 2,e,f,g,h); 
    k_set( 3,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get( 3,e,f,g,h); 
    k_set( 4,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get( 4,e,f,g,h); 
    k_set( 5,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get( 5,e,f,g,h); 
    k_set( 6,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get( 6,e,f,g,h); 
    k_set( 7,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get( 7,e,f,g,h); 
    k_set( 8,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( 8,e,f,g,h); 
    k_set( 9,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( 9,e,f,g,h); 
    k_set(10,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(10,e,f,g,h); 
    k_set(11,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(11,e,f,g,h); 
    k_set(12,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(12,e,f,g,h); 
    k_set(13,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(13,e,f,g,h); 
    k_set(14,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(14,e,f,g,h); 
    k_set(15,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(15,e,f,g,h); 
    k_set(16,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(16,e,f,g,h); 
    k_set(17,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get(17,e,f,g,h); 
    k_set(18,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(18,e,f,g,h); 
    k_set(19,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(19,e,f,g,h); 
    k_set(20,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(20,e,f,g,h); 
    k_set(21,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(21,e,f,g,h); 
    k_set(22,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(22,e,f,g,h); 
    k_set(23,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(23,e,f,g,h); 
    k_set(24,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(24,e,f,g,h); 
    k_set(25,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get(25,e,f,g,h); 
    k_set(26,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(26,e,f,g,h); 
    k_set(27,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(27,e,f,g,h); 
    k_set(28,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(28,e,f,g,h); 
    k_set(29,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(29,e,f,g,h); 
    k_set(30,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(30,e,f,g,h); 
    k_set(31,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(31,e,f,g,h); 
    k_set(32,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(32,e,f,g,h); 
 
    return l_key; 
}; 
 
/* encrypt a block of text  */ 
 
void encrypt(u4byte in_blk[], u4byte out_blk[]) 
{ 
    u4byte  a,b,c,d,e,f,g,h; 
     
    a = in_blk[0];b = in_blk[1];c = in_blk[2];d = in_blk[3]; 
     
    k_xor( 0,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor( 1,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor( 2,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor( 3,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor( 4,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor( 5,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor( 6,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor( 7,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor( 8,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor( 9,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(10,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(11,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(12,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(13,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(14,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(15,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(16,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(17,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(18,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(19,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(20,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(21,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(22,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(23,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(24,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(25,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(26,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(27,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(28,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(29,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);  
    k_xor(30,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);  
    k_xor(31,e,f,g,h); sb7(e,f,g,h,a,b,c,d); k_xor(32,a,b,c,d);  
     
    out_blk[0] = a; out_blk[1] = b; out_blk[2] = c; out_blk[3] = d; 
}; 
 
/* decrypt a block of text  */ 
 
void decrypt(u4byte in_blk[], u4byte out_blk[]) 
{ 
    u4byte  a,b,c,d,e,f,g,h; 
     
    a = in_blk[0];b = in_blk[1];c = in_blk[2];d = in_blk[3]; 
 
    k_xor(32,a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(31,e,f,g,h); 
    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(30,a,b,c,d); 
    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(29,e,f,g,h); 
    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(28,a,b,c,d); 
    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(27,e,f,g,h); 
    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(26,a,b,c,d); 
    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(25,e,f,g,h); 
    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(24,a,b,c,d); 
    irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(23,e,f,g,h); 
    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(22,a,b,c,d); 
    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(21,e,f,g,h); 
    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(20,a,b,c,d); 
    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(19,e,f,g,h); 
    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(18,a,b,c,d); 
    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(17,e,f,g,h); 
    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(16,a,b,c,d); 
    irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(15,e,f,g,h); 
    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(14,a,b,c,d); 
    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(13,e,f,g,h); 
    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(12,a,b,c,d); 
    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(11,e,f,g,h); 
    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(10,a,b,c,d); 
    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 9,e,f,g,h); 
    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 8,a,b,c,d); 
    irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor( 7,e,f,g,h); 
    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor( 6,a,b,c,d); 
    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor( 5,e,f,g,h); 
    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor( 4,a,b,c,d); 
    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor( 3,e,f,g,h); 
    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor( 2,a,b,c,d); 
    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 1,e,f,g,h); 
    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 0,a,b,c,d); 
     
    out_blk[0] = a; out_blk[1] = b; out_blk[2] = c; out_blk[3] = d; 
};