• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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  */
gcm_process(gcm_state * gcm,unsigned char * pt,unsigned long ptlen,unsigned char * ct,int direction)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