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