Home | History | Annotate | Download | only in gcm
      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 gcm_process.c
     14    GCM implementation, process message data, by Tom St Denis
     15 */
     16 #include "tomcrypt.h"
     17 
     18 #ifdef GCM_MODE
     19 
     20 /**
     21   Process plaintext/ciphertext through GCM
     22   @param gcm       The GCM state
     23   @param pt        The plaintext
     24   @param ptlen     The plaintext length (ciphertext length is the same)
     25   @param ct        The ciphertext
     26   @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
     27   @return CRYPT_OK on success
     28  */
     29 int gcm_process(gcm_state *gcm,
     30                      unsigned char *pt,     unsigned long ptlen,
     31                      unsigned char *ct,
     32                      int direction)
     33 {
     34    unsigned long x;
     35    int           y, err;
     36    unsigned char b;
     37 
     38    LTC_ARGCHK(gcm != NULL);
     39    if (ptlen > 0) {
     40       LTC_ARGCHK(pt  != NULL);
     41       LTC_ARGCHK(ct  != NULL);
     42    }
     43 
     44    if (gcm->buflen > 16 || gcm->buflen < 0) {
     45       return CRYPT_INVALID_ARG;
     46    }
     47 
     48    if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
     49       return err;
     50    }
     51 
     52    /* in AAD mode? */
     53    if (gcm->mode == GCM_MODE_AAD) {
     54       /* let's process the AAD */
     55       if (gcm->buflen) {
     56          gcm->totlen += gcm->buflen * CONST64(8);
     57          gcm_mult_h(gcm, gcm->X);
     58       }
     59 
     60       /* increment counter */
     61       for (y = 15; y >= 12; y--) {
     62           if (++gcm->Y[y] & 255) { break; }
     63       }
     64       /* encrypt the counter */
     65       if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
     66          return err;
     67       }
     68 
     69       gcm->buflen = 0;
     70       gcm->mode   = GCM_MODE_TEXT;
     71    }
     72 
     73    if (gcm->mode != GCM_MODE_TEXT) {
     74       return CRYPT_INVALID_ARG;
     75    }
     76 
     77    x = 0;
     78 #ifdef LTC_FAST
     79    if (gcm->buflen == 0) {
     80       if (direction == GCM_ENCRYPT) {
     81          for (x = 0; x < (ptlen & ~15); x += 16) {
     82              /* ctr encrypt */
     83              for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
     84                  *((LTC_FAST_TYPE*)(&ct[x + y])) = *((LTC_FAST_TYPE*)(&pt[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y]));
     85                  *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y]));
     86              }
     87              /* GMAC it */
     88              gcm->pttotlen += 128;
     89              gcm_mult_h(gcm, gcm->X);
     90              /* increment counter */
     91              for (y = 15; y >= 12; y--) {
     92                  if (++gcm->Y[y] & 255) { break; }
     93              }
     94              if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
     95                 return err;
     96              }
     97          }
     98       } else {
     99          for (x = 0; x < (ptlen & ~15); x += 16) {
    100              /* ctr encrypt */
    101              for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
    102                  *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y]));
    103                  *((LTC_FAST_TYPE*)(&pt[x + y])) = *((LTC_FAST_TYPE*)(&ct[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y]));
    104              }
    105              /* GMAC it */
    106              gcm->pttotlen += 128;
    107              gcm_mult_h(gcm, gcm->X);
    108              /* increment counter */
    109              for (y = 15; y >= 12; y--) {
    110                  if (++gcm->Y[y] & 255) { break; }
    111              }
    112              if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
    113                 return err;
    114              }
    115          }
    116      }
    117    }
    118 #endif
    119 
    120    /* process text */
    121    for (; x < ptlen; x++) {
    122        if (gcm->buflen == 16) {
    123           gcm->pttotlen += 128;
    124           gcm_mult_h(gcm, gcm->X);
    125 
    126           /* increment counter */
    127           for (y = 15; y >= 12; y--) {
    128               if (++gcm->Y[y] & 255) { break; }
    129           }
    130           if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
    131              return err;
    132           }
    133           gcm->buflen = 0;
    134        }
    135 
    136        if (direction == GCM_ENCRYPT) {
    137           b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen];
    138        } else {
    139           b = ct[x];
    140           pt[x] = ct[x] ^ gcm->buf[gcm->buflen];
    141        }
    142        gcm->X[gcm->buflen++] ^= b;
    143    }
    144 
    145    return CRYPT_OK;
    146 }
    147 
    148 #endif
    149 
    150 /* $Source: /cvs/libtom/libtomcrypt/src/encauth/gcm/gcm_process.c,v $ */
    151 /* $Revision: 1.14 $ */
    152 /* $Date: 2006/11/19 19:33:36 $ */
    153