comparison src/encauth/gcm/gcm_process.c @ 192:9cc34777b479 libtomcrypt

propagate from branch 'au.asn.ucc.matt.ltc-orig' (head 9ba8f01f44320e9cb9f19881105ae84f84a43ea9) to branch 'au.asn.ucc.matt.dropbear.ltc' (head dbf51c569bc34956ad948e4cc87a0eeb2170b768)
author Matt Johnston <matt@ucc.asn.au>
date Sun, 08 May 2005 06:36:47 +0000
parents 1c15b283127b
children 39d5d58461d6
comparison
equal deleted inserted replaced
164:cd1143579f00 192:9cc34777b479
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 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11
12 /**
13 @file gcm_process.c
14 GCM implementation, process message data, by Tom St Denis
15 */
16 #include "tomcrypt.h"
17
18 #ifdef GCM_MODE
19
20 /**
21 Process plaintext/ciphertext through GCM
22 @param gcm The GCM state
23 @param pt The plaintext
24 @param ptlen The plaintext length (ciphertext length is the same)
25 @param ct The ciphertext
26 @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
27 @return CRYPT_OK on success
28 */
29 int gcm_process(gcm_state *gcm,
30 unsigned char *pt, unsigned long ptlen,
31 unsigned char *ct,
32 int direction)
33 {
34 unsigned long x, y;
35 unsigned char b;
36 int err;
37
38 LTC_ARGCHK(gcm != NULL);
39 if (ptlen > 0) {
40 LTC_ARGCHK(pt != NULL);
41 LTC_ARGCHK(ct != NULL);
42 }
43
44 if (gcm->buflen > 16 || gcm->buflen < 0) {
45 return CRYPT_INVALID_ARG;
46 }
47
48 if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
49 return err;
50 }
51
52 /* in AAD mode? */
53 if (gcm->mode == GCM_MODE_AAD) {
54 /* let's process the AAD */
55 if (gcm->buflen) {
56 gcm->totlen += gcm->buflen * CONST64(8);
57 gcm_mult_h(gcm, gcm->X);
58 }
59
60 /* increment counter */
61 for (y = 15; y >= 12; y--) {
62 if (++gcm->Y[y]) { break; }
63 }
64 /* encrypt the counter */
65 cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K);
66
67 gcm->buflen = 0;
68 gcm->mode = GCM_MODE_TEXT;
69 }
70
71 if (gcm->mode != GCM_MODE_TEXT) {
72 return CRYPT_INVALID_ARG;
73 }
74
75 x = 0;
76 #ifdef LTC_FAST
77 if (gcm->buflen == 0) {
78 if (direction == GCM_ENCRYPT) {
79 for (x = 0; x < (ptlen & ~15); x += 16) {
80 /* ctr encrypt */
81 for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
82 *((LTC_FAST_TYPE*)(&ct[x + y])) = *((LTC_FAST_TYPE*)(&pt[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y]));
83 *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y]));
84 }
85 /* GMAC it */
86 gcm->pttotlen += 128;
87 gcm_mult_h(gcm, gcm->X);
88 /* increment counter */
89 for (y = 15; y >= 12; y--) {
90 if (++gcm->Y[y]) { break; }
91 }
92 cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K);
93 }
94 } else {
95 for (x = 0; x < (ptlen & ~15); x += 16) {
96 /* ctr encrypt */
97 for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
98 *((LTC_FAST_TYPE*)(&gcm->X[y])) ^= *((LTC_FAST_TYPE*)(&ct[x+y]));
99 *((LTC_FAST_TYPE*)(&pt[x + y])) = *((LTC_FAST_TYPE*)(&ct[x+y])) ^ *((LTC_FAST_TYPE*)(&gcm->buf[y]));
100 }
101 /* GMAC it */
102 gcm->pttotlen += 128;
103 gcm_mult_h(gcm, gcm->X);
104 /* increment counter */
105 for (y = 15; y >= 12; y--) {
106 if (++gcm->Y[y]) { break; }
107 }
108 cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K);
109 }
110 }
111 }
112 #endif
113
114 /* process text */
115 for (; x < ptlen; x++) {
116 if (gcm->buflen == 16) {
117 gcm->pttotlen += 128;
118 gcm_mult_h(gcm, gcm->X);
119
120 /* increment counter */
121 for (y = 15; y >= 12; y--) {
122 if (++gcm->Y[y]) { break; }
123 }
124 cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K);
125 gcm->buflen = 0;
126 }
127
128 if (direction == GCM_ENCRYPT) {
129 b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen];
130 } else {
131 b = ct[x];
132 pt[x] = ct[x] ^ gcm->buf[gcm->buflen];
133 }
134 gcm->X[gcm->buflen++] ^= b;
135 }
136
137 return CRYPT_OK;
138 }
139
140
141
142 #endif
143