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