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