1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
12 GCM implementation, process message data, by Tom St Denis
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
27 int gcm_process(gcm_state *gcm,
28 unsigned char *pt, unsigned long ptlen,
36 LTC_ARGCHK(gcm != NULL);
38 LTC_ARGCHK(pt != NULL);
39 LTC_ARGCHK(ct != NULL);
42 if (gcm->buflen > 16 || gcm->buflen < 0) {
43 return CRYPT_INVALID_ARG;
46 if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
50 /* 0xFFFFFFFE0 = ((2^39)-256)/8 */
51 if (gcm->pttotlen / 8 + (ulong64)gcm->buflen + (ulong64)ptlen >= CONST64(0xFFFFFFFE0)) {
52 return CRYPT_INVALID_ARG;
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;
61 if (gcm->mode == LTC_GCM_MODE_AAD) {
62 /* let's process the AAD */
64 gcm->totlen += gcm->buflen * CONST64(8);
65 gcm_mult_h(gcm, gcm->X);
68 /* increment counter */
69 for (y = 15; y >= 12; y--) {
70 if (++gcm->Y[y] & 255) { break; }
72 /* encrypt the counter */
73 if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
78 gcm->mode = LTC_GCM_MODE_TEXT;
81 if (gcm->mode != LTC_GCM_MODE_TEXT) {
82 return CRYPT_INVALID_ARG;
87 if (gcm->buflen == 0) {
88 if (direction == GCM_ENCRYPT) {
89 for (x = 0; x < (ptlen & ~15); x += 16) {
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]));
97 gcm_mult_h(gcm, gcm->X);
98 /* increment counter */
99 for (y = 15; y >= 12; y--) {
100 if (++gcm->Y[y] & 255) { break; }
102 if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
107 for (x = 0; x < (ptlen & ~15); x += 16) {
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]));
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; }
120 if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
129 for (; x < ptlen; x++) {
130 if (gcm->buflen == 16) {
131 gcm->pttotlen += 128;
132 gcm_mult_h(gcm, gcm->X);
134 /* increment counter */
135 for (y = 15; y >= 12; y--) {
136 if (++gcm->Y[y] & 255) { break; }
138 if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) {
144 if (direction == GCM_ENCRYPT) {
145 b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen];
148 pt[x] = ct[x] ^ gcm->buf[gcm->buflen];
150 gcm->X[gcm->buflen++] ^= b;
158 /* ref: $Format:%D$ */
159 /* git commit: $Format:%H$ */
160 /* commit time: $Format:%ai$ */