Home | History | Annotate | Download | only in pmac
      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 #include "tomcrypt.h"
     12 
     13 /**
     14    @file pmac_init.c
     15    PMAC implementation, initialize state, by Tom St Denis
     16 */
     17 
     18 #ifdef LTC_PMAC
     19 
     20 static const struct {
     21     int           len;
     22     unsigned char poly_div[MAXBLOCKSIZE],
     23                   poly_mul[MAXBLOCKSIZE];
     24 } polys[] = {
     25 {
     26     8,
     27     { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
     28     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
     29 }, {
     30     16,
     31     { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     32       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
     33     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     34       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
     35 }
     36 };
     37 
     38 /**
     39    Initialize a PMAC state
     40    @param pmac      The PMAC state to initialize
     41    @param cipher    The index of the desired cipher
     42    @param key       The secret key
     43    @param keylen    The length of the secret key (octets)
     44    @return CRYPT_OK if successful
     45 */
     46 int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen)
     47 {
     48    int poly, x, y, m, err;
     49    unsigned char *L;
     50 
     51    LTC_ARGCHK(pmac  != NULL);
     52    LTC_ARGCHK(key   != NULL);
     53 
     54    /* valid cipher? */
     55    if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
     56       return err;
     57    }
     58 
     59    /* determine which polys to use */
     60    pmac->block_len = cipher_descriptor[cipher].block_length;
     61    for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) {
     62        if (polys[poly].len == pmac->block_len) {
     63           break;
     64        }
     65    }
     66    if (polys[poly].len != pmac->block_len) {
     67       return CRYPT_INVALID_ARG;
     68    }
     69 
     70 #ifdef LTC_FAST
     71    if (pmac->block_len % sizeof(LTC_FAST_TYPE)) {
     72       return CRYPT_INVALID_ARG;
     73    }
     74 #endif
     75 
     76 
     77    /* schedule the key */
     78    if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) {
     79       return err;
     80    }
     81 
     82    /* allocate L */
     83    L = XMALLOC(pmac->block_len);
     84    if (L == NULL) {
     85       return CRYPT_MEM;
     86    }
     87 
     88    /* find L = E[0] */
     89    zeromem(L, pmac->block_len);
     90    if ((err = cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key)) != CRYPT_OK) {
     91       goto error;
     92    }
     93 
     94    /* find Ls[i] = L << i for i == 0..31 */
     95    XMEMCPY(pmac->Ls[0], L, pmac->block_len);
     96    for (x = 1; x < 32; x++) {
     97        m = pmac->Ls[x-1][0] >> 7;
     98        for (y = 0; y < pmac->block_len-1; y++) {
     99            pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255;
    100        }
    101        pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255;
    102 
    103        if (m == 1) {
    104           for (y = 0; y < pmac->block_len; y++) {
    105               pmac->Ls[x][y] ^= polys[poly].poly_mul[y];
    106           }
    107        }
    108     }
    109 
    110     /* find Lr = L / x */
    111     m = L[pmac->block_len-1] & 1;
    112 
    113     /* shift right */
    114     for (x = pmac->block_len - 1; x > 0; x--) {
    115         pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255;
    116     }
    117     pmac->Lr[0] = L[0] >> 1;
    118 
    119     if (m == 1) {
    120        for (x = 0; x < pmac->block_len; x++) {
    121            pmac->Lr[x] ^= polys[poly].poly_div[x];
    122        }
    123     }
    124 
    125     /* zero buffer, counters, etc... */
    126     pmac->block_index = 1;
    127     pmac->cipher_idx  = cipher;
    128     pmac->buflen      = 0;
    129     zeromem(pmac->block,    sizeof(pmac->block));
    130     zeromem(pmac->Li,       sizeof(pmac->Li));
    131     zeromem(pmac->checksum, sizeof(pmac->checksum));
    132     err = CRYPT_OK;
    133 error:
    134 #ifdef LTC_CLEAN_STACK
    135     zeromem(L, pmac->block_len);
    136 #endif
    137 
    138     XFREE(L);
    139 
    140     return err;
    141 }
    142 
    143 #endif
    144 
    145 /* $Source: /cvs/libtom/libtomcrypt/src/mac/pmac/pmac_init.c,v $ */
    146 /* $Revision: 1.7 $ */
    147 /* $Date: 2006/11/03 00:39:49 $ */
    148