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