Home | History | Annotate | Download | only in ocb
      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 ocb_init.c
     14    OCB implementation, initialize state, by Tom St Denis
     15 */
     16 #include "tomcrypt.h"
     17 
     18 #ifdef OCB_MODE
     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 an OCB context.
     40   @param ocb     [out] The destination of the OCB state
     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   @param nonce   The session nonce (length of the block size of the cipher)
     45   @return CRYPT_OK if successful
     46 */
     47 int ocb_init(ocb_state *ocb, int cipher,
     48              const unsigned char *key, unsigned long keylen, const unsigned char *nonce)
     49 {
     50    int poly, x, y, m, err;
     51 
     52    LTC_ARGCHK(ocb   != NULL);
     53    LTC_ARGCHK(key   != NULL);
     54    LTC_ARGCHK(nonce != NULL);
     55 
     56    /* valid cipher? */
     57    if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
     58       return err;
     59    }
     60 
     61    /* determine which polys to use */
     62    ocb->block_len = cipher_descriptor[cipher].block_length;
     63    for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) {
     64        if (polys[poly].len == ocb->block_len) {
     65           break;
     66        }
     67    }
     68    if (polys[poly].len != ocb->block_len) {
     69       return CRYPT_INVALID_ARG;
     70    }
     71 
     72    /* schedule the key */
     73    if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {
     74       return err;
     75    }
     76 
     77    /* find L = E[0] */
     78    zeromem(ocb->L, ocb->block_len);
     79    if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) {
     80       return err;
     81    }
     82 
     83    /* find R = E[N xor L] */
     84    for (x = 0; x < ocb->block_len; x++) {
     85        ocb->R[x] = ocb->L[x] ^ nonce[x];
     86    }
     87    if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) {
     88       return err;
     89    }
     90 
     91    /* find Ls[i] = L << i for i == 0..31 */
     92    XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len);
     93    for (x = 1; x < 32; x++) {
     94        m = ocb->Ls[x-1][0] >> 7;
     95        for (y = 0; y < ocb->block_len-1; y++) {
     96            ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255;
     97        }
     98        ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255;
     99 
    100        if (m == 1) {
    101           for (y = 0; y < ocb->block_len; y++) {
    102               ocb->Ls[x][y] ^= polys[poly].poly_mul[y];
    103           }
    104        }
    105     }
    106 
    107     /* find Lr = L / x */
    108     m = ocb->L[ocb->block_len-1] & 1;
    109 
    110     /* shift right */
    111     for (x = ocb->block_len - 1; x > 0; x--) {
    112         ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255;
    113     }
    114     ocb->Lr[0] = ocb->L[0] >> 1;
    115 
    116     if (m == 1) {
    117        for (x = 0; x < ocb->block_len; x++) {
    118            ocb->Lr[x] ^= polys[poly].poly_div[x];
    119        }
    120     }
    121 
    122     /* set Li, checksum */
    123     zeromem(ocb->Li,       ocb->block_len);
    124     zeromem(ocb->checksum, ocb->block_len);
    125 
    126     /* set other params */
    127     ocb->block_index = 1;
    128     ocb->cipher      = cipher;
    129 
    130     return CRYPT_OK;
    131 }
    132 
    133 #endif
    134 
    135 /* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/ocb_init.c,v $ */
    136 /* $Revision: 1.5 $ */
    137 /* $Date: 2006/03/31 14:15:35 $ */
    138