Home | History | Annotate | Download | only in whirl
      1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
      2  *
      3  * LibTomCrypt is a library that provides various cryptographic
      4  * algorithms in a highly modular and flexible manner.
      5  *
      6  * The library is free for all purposes without any express
      7  * guarantee it works.
      8  *
      9  * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com
     10  */
     11 
     12 /**
     13    @file whirl.c
     14    WHIRLPOOL (using their new sbox) hash function by Tom St Denis
     15 */
     16 
     17 #include "tomcrypt.h"
     18 
     19 #ifdef WHIRLPOOL
     20 
     21 const struct ltc_hash_descriptor whirlpool_desc =
     22 {
     23     "whirlpool",
     24     11,
     25     64,
     26     64,
     27 
     28    /* OID */
     29    { 1, 0, 10118, 3, 0, 55 },
     30    6,
     31 
     32     &whirlpool_init,
     33     &whirlpool_process,
     34     &whirlpool_done,
     35     &whirlpool_test,
     36     NULL
     37 };
     38 
     39 /* the sboxes */
     40 #include "whirltab.c"
     41 
     42 /* get a_{i,j} */
     43 #define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255)
     44 
     45 /* shortcut macro to perform three functions at once */
     46 #define theta_pi_gamma(a, i)             \
     47     SB0(GB(a, i-0, 7)) ^                 \
     48     SB1(GB(a, i-1, 6)) ^                 \
     49     SB2(GB(a, i-2, 5)) ^                 \
     50     SB3(GB(a, i-3, 4)) ^                 \
     51     SB4(GB(a, i-4, 3)) ^                 \
     52     SB5(GB(a, i-5, 2)) ^                 \
     53     SB6(GB(a, i-6, 1)) ^                 \
     54     SB7(GB(a, i-7, 0))
     55 
     56 #ifdef LTC_CLEAN_STACK
     57 static int _whirlpool_compress(hash_state *md, unsigned char *buf)
     58 #else
     59 static int whirlpool_compress(hash_state *md, unsigned char *buf)
     60 #endif
     61 {
     62    ulong64 K[2][8], T[3][8];
     63    int x, y;
     64 
     65    /* load the block/state */
     66    for (x = 0; x < 8; x++) {
     67       K[0][x] = md->whirlpool.state[x];
     68 
     69       LOAD64H(T[0][x], buf + (8 * x));
     70       T[2][x]  = T[0][x];
     71       T[0][x] ^= K[0][x];
     72    }
     73 
     74    /* do rounds 1..10 */
     75    for (x = 0; x < 10; x += 2) {
     76        /* odd round */
     77        /* apply main transform to K[0] into K[1] */
     78        for (y = 0; y < 8; y++) {
     79            K[1][y] = theta_pi_gamma(K[0], y);
     80        }
     81        /* xor the constant */
     82        K[1][0] ^= cont[x];
     83 
     84        /* apply main transform to T[0] into T[1] */
     85        for (y = 0; y < 8; y++) {
     86            T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y];
     87        }
     88 
     89        /* even round */
     90        /* apply main transform to K[1] into K[0] */
     91        for (y = 0; y < 8; y++) {
     92            K[0][y] = theta_pi_gamma(K[1], y);
     93        }
     94        /* xor the constant */
     95        K[0][0] ^= cont[x+1];
     96 
     97        /* apply main transform to T[1] into T[0] */
     98        for (y = 0; y < 8; y++) {
     99            T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y];
    100        }
    101    }
    102 
    103    /* store state */
    104    for (x = 0; x < 8; x++) {
    105       md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
    106    }
    107 
    108    return CRYPT_OK;
    109 }
    110 
    111 
    112 #ifdef LTC_CLEAN_STACK
    113 static int whirlpool_compress(hash_state *md, unsigned char *buf)
    114 {
    115    int err;
    116    err = _whirlpool_compress(md, buf);
    117    burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
    118    return err;
    119 }
    120 #endif
    121 
    122 
    123 /**
    124    Initialize the hash state
    125    @param md   The hash state you wish to initialize
    126    @return CRYPT_OK if successful
    127 */
    128 int whirlpool_init(hash_state * md)
    129 {
    130    LTC_ARGCHK(md != NULL);
    131    zeromem(&md->whirlpool, sizeof(md->whirlpool));
    132    return CRYPT_OK;
    133 }
    134 
    135 /**
    136    Process a block of memory though the hash
    137    @param md     The hash state
    138    @param in     The data to hash
    139    @param inlen  The length of the data (octets)
    140    @return CRYPT_OK if successful
    141 */
    142 HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64)
    143 
    144 /**
    145    Terminate the hash to get the digest
    146    @param md  The hash state
    147    @param out [out] The destination of the hash (64 bytes)
    148    @return CRYPT_OK if successful
    149 */
    150 int whirlpool_done(hash_state * md, unsigned char *out)
    151 {
    152     int i;
    153 
    154     LTC_ARGCHK(md  != NULL);
    155     LTC_ARGCHK(out != NULL);
    156 
    157     if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) {
    158        return CRYPT_INVALID_ARG;
    159     }
    160 
    161     /* increase the length of the message */
    162     md->whirlpool.length += md->whirlpool.curlen * 8;
    163 
    164     /* append the '1' bit */
    165     md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80;
    166 
    167     /* if the length is currently above 32 bytes we append zeros
    168      * then compress.  Then we can fall back to padding zeros and length
    169      * encoding like normal.
    170      */
    171     if (md->whirlpool.curlen > 32) {
    172         while (md->whirlpool.curlen < 64) {
    173             md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
    174         }
    175         whirlpool_compress(md, md->whirlpool.buf);
    176         md->whirlpool.curlen = 0;
    177     }
    178 
    179     /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths)  */
    180     while (md->whirlpool.curlen < 56) {
    181         md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
    182     }
    183 
    184     /* store length */
    185     STORE64H(md->whirlpool.length, md->whirlpool.buf+56);
    186     whirlpool_compress(md, md->whirlpool.buf);
    187 
    188     /* copy output */
    189     for (i = 0; i < 8; i++) {
    190         STORE64H(md->whirlpool.state[i], out+(8*i));
    191     }
    192 #ifdef LTC_CLEAN_STACK
    193     zeromem(md, sizeof(*md));
    194 #endif
    195     return CRYPT_OK;
    196 }
    197 
    198 /**
    199   Self-test the hash
    200   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
    201 */
    202 int  whirlpool_test(void)
    203 {
    204  #ifndef LTC_TEST
    205     return CRYPT_NOP;
    206  #else
    207   static const struct {
    208       int len;
    209       unsigned char msg[128], hash[64];
    210   } tests[] = {
    211 
    212   /* NULL Message */
    213 {
    214   0,
    215   { 0x00 },
    216   { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
    217     0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
    218     0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
    219     0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }
    220 },
    221 
    222 
    223    /* 448-bits of 0 bits */
    224 {
    225 
    226   56,
    227   { 0x00 },
    228   { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03,
    229     0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70,
    230     0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61,
    231     0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 }
    232 },
    233 
    234    /* 520-bits of 0 bits */
    235 {
    236   65,
    237   { 0x00 },
    238   { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D,
    239     0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4,
    240     0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF,
    241     0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 }
    242 },
    243 
    244    /* 512-bits, leading set */
    245 {
    246   64,
    247   { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    248     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    249     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    250     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    251   { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A,
    252     0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94,
    253     0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6,
    254     0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB }
    255 },
    256 
    257    /* 512-bits, leading set of second byte */
    258 {
    259   64,
    260   { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    261     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    262     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    263     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    264   { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E,
    265     0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F,
    266     0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35,
    267     0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 }
    268 },
    269 
    270    /* 512-bits, leading set of last byte */
    271 {
    272   64,
    273   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    274     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    275     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    276     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
    277   { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6,
    278     0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F,
    279     0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B,
    280     0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 }
    281 },
    282 
    283 };
    284 
    285   int i;
    286   unsigned char tmp[64];
    287   hash_state md;
    288 
    289   for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
    290       whirlpool_init(&md);
    291       whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len);
    292       whirlpool_done(&md, tmp);
    293       if (XMEMCMP(tmp, tests[i].hash, 64) != 0) {
    294 #if 0
    295          printf("\nFailed test %d\n", i);
    296          for (i = 0; i < 64; ) {
    297             printf("%02x ", tmp[i]);
    298             if (!(++i & 15)) printf("\n");
    299          }
    300 #endif
    301          return CRYPT_FAIL_TESTVECTOR;
    302       }
    303   }
    304   return CRYPT_OK;
    305  #endif
    306 }
    307 
    308 
    309 #endif
    310 
    311 
    312 /* $Source: /cvs/libtom/libtomcrypt/src/hashes/whirl/whirl.c,v $ */
    313 /* $Revision: 1.8 $ */
    314 /* $Date: 2006/11/01 09:28:17 $ */
    315