1 /* eax.c
2 * Encryption and decryption routines implementing the EAX' encryption mode
3 * Copyright 2010, Edward J. Beroset, edward.j.beroset@us.elster.com
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11 #include "config.h"
12 #include <stdlib.h>
13 #include <string.h>
14 /* Use libgcrypt for cipher libraries. */
15 #include <wsutil/wsgcrypt.h>
16 #include "eax.h"
17
18 typedef struct {
19 guint8 L[EAX_SIZEOF_KEY];
20 guint8 D[EAX_SIZEOF_KEY];
21 guint8 Q[EAX_SIZEOF_KEY];
22 } eax_s;
23
24 static eax_s instance;
25
26 /* these are defined as macros so they'll be easy to redo in assembly if desired */
27 #define BLK_CPY(dst, src) { memcpy(dst, src, EAX_SIZEOF_KEY); }
28 #define BLK_XOR(dst, src) { int z; for (z=0; z < EAX_SIZEOF_KEY; z++) dst[z] ^= src[z]; }
29 static void Dbl(guint8 *out, const guint8 *in);
30 static void CTR(const guint8 *ws, guint8 *pK, guint8 *pN, guint16 SizeN);
31 static void CMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN);
32 static void dCMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN, const guint8 *pC, guint16 SizeC);
33 void AesEncrypt(unsigned char msg[EAX_SIZEOF_KEY], unsigned char key[EAX_SIZEOF_KEY]);
34
35 /*!
36 Decrypts cleartext data using EAX' mode (see ANSI Standard C12.22-2008).
37
38 @param[in] pN pointer to cleartext (canonified form)
39 @param[in] pK pointer to secret key
40 @param[in,out] pC pointer to ciphertext
41 @param[in] SizeN byte length of cleartext (pN) buffer
42 @param[in] SizeK byte length of secret key (pK)
43 @param[in] SizeC byte length of ciphertext (pC) buffer
44 @param[in] pMac four-byte Message Authentication Code
45 @param[in] Mode EAX_MODE_CLEARTEXT_AUTH or EAX_MODE_CIPHERTEXT_AUTH
46 @return TRUE if message has been authenticated; FALSE if not
47 authenticated, invalid Mode or error
48 */
Eax_Decrypt(guint8 * pN,guint8 * pK,guint8 * pC,guint32 SizeN,guint32 SizeK,guint32 SizeC,MAC_T * pMac,guint8 Mode)49 gboolean Eax_Decrypt(guint8 *pN, guint8 *pK, guint8 *pC,
50 guint32 SizeN, guint32 SizeK, guint32 SizeC, MAC_T *pMac,
51 guint8 Mode)
52 {
53 guint8 wsn[EAX_SIZEOF_KEY];
54 guint8 wsc[EAX_SIZEOF_KEY];
55 int i;
56
57 /* key size must match this implementation */
58 if (SizeK != EAX_SIZEOF_KEY)
59 return FALSE;
60
61 /* the key is new */
62 for (i = 0; i < EAX_SIZEOF_KEY; i++)
63 instance.L[i] = 0;
64 AesEncrypt(instance.L, pK);
65 Dbl(instance.D, instance.L);
66 Dbl(instance.Q, instance.D);
67 /* the key is set up */
68 /* first copy the nonce into our working space */
69 BLK_CPY(wsn, instance.D);
70 if (Mode == EAX_MODE_CLEARTEXT_AUTH) {
71 dCMAC(pK, wsn, pN, SizeN, pC, SizeC);
72 } else {
73 CMAC(pK, wsn, pN, SizeN);
74 }
75 /*
76 * In authentication mode the inputs are: pN, pK (and associated sizes),
77 * the result is the 4 byte MAC.
78 */
79 if (Mode == EAX_MODE_CLEARTEXT_AUTH)
80 {
81 return (memcmp(pMac, &wsn[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) ? FALSE : TRUE);
82
83 }
84
85 /*
86 * In cipher mode the inputs are: pN, pK, pP (and associated sizes),
87 * the results are pC (and its size) along with the 4 byte MAC.
88 */
89 else if (Mode == EAX_MODE_CIPHERTEXT_AUTH)
90 {
91 if (SizeC == 0)
92 return (memcmp(pMac, &wsn[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) ? FALSE : TRUE);
93 {
94 /* first copy the nonce into our working space */
95 BLK_CPY(wsc, instance.Q);
96 CMAC(pK, wsc, pC, SizeC);
97 BLK_XOR(wsc, wsn);
98 }
99 if (memcmp(pMac, &wsc[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) == 0)
100 {
101 CTR(wsn, pK, pC, SizeC);
102 return TRUE;
103 }
104 }
105 return FALSE;
106 }
107
108 /* set up D or Q from L */
Dbl(guint8 * out,const guint8 * in)109 static void Dbl(guint8 *out, const guint8 *in)
110 {
111 int i;
112 guint8 carry = 0;
113
114 /* this might be a lot more efficient in assembly language */
115 for (i=0; i < EAX_SIZEOF_KEY; i++)
116 {
117 out[i] = ( in[i] << 1 ) | carry;
118 carry = (in[i] & 0x80) ? 1 : 0;
119 }
120 if (carry)
121 out[0] ^= 0x87;
122 }
123
CMAC(guint8 * pK,guint8 * ws,const guint8 * pN,guint16 SizeN)124 static void CMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN)
125 {
126 dCMAC(pK, ws, pN, SizeN, NULL, 0);
127 }
128
dCMAC(guint8 * pK,guint8 * ws,const guint8 * pN,guint16 SizeN,const guint8 * pC,guint16 SizeC)129 static void dCMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN, const guint8 *pC, guint16 SizeC)
130 {
131 gcry_cipher_hd_t cipher_hd;
132 guint8 *work;
133 guint8 *ptr;
134 guint16 SizeT = SizeN + SizeC;
135 guint16 worksize = SizeT;
136
137 /* worksize must be an integral multiple of 16 */
138 if (SizeT & 0xf) {
139 worksize += 0x10 - (worksize & 0xf);
140 }
141 work = (guint8 *)g_malloc(worksize);
142 if (work == NULL) {
143 return;
144 }
145 memcpy(work, pN, SizeN);
146 if (pC != NULL) {
147 memcpy(&work[SizeN], pC, SizeC);
148 }
149 /*
150 * pad the data if necessary, and XOR Q or D, depending on
151 * whether data was padded or not
152 */
153 if (worksize != SizeT) {
154 work[SizeT] = 0x80;
155 for (ptr = &work[SizeT+1]; ptr < &work[worksize]; ptr++)
156 *ptr = 0;
157 ptr= &work[worksize-0x10];
158 BLK_XOR(ptr, instance.Q);
159 } else {
160 ptr = &work[worksize-0x10];
161 BLK_XOR(ptr, instance.D);
162 }
163 /* open the cipher */
164 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC,0)){/* GCRY_CIPHER_CBC_MAC)) { */
165 g_free(work);
166 return;
167 }
168 if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
169 g_free(work);
170 gcry_cipher_close(cipher_hd);
171 return;
172 }
173 if (gcry_cipher_setiv(cipher_hd, ws, EAX_SIZEOF_KEY)) {
174 g_free(work);
175 gcry_cipher_close(cipher_hd);
176 return;
177 }
178 if (gcry_cipher_encrypt(cipher_hd, work, worksize, work, worksize)) {
179 g_free(work);
180 gcry_cipher_close(cipher_hd);
181 return;
182 }
183 memcpy(ws, ptr, EAX_SIZEOF_KEY);
184
185 g_free(work);
186 gcry_cipher_close(cipher_hd);
187 return;
188 }
189
CTR(const guint8 * ws,guint8 * pK,guint8 * pN,guint16 SizeN)190 static void CTR(const guint8 *ws, guint8 *pK, guint8 *pN, guint16 SizeN)
191 {
192 gcry_cipher_hd_t cipher_hd;
193 guint8 ctr[EAX_SIZEOF_KEY];
194
195 BLK_CPY(ctr, ws);
196 ctr[12] &= 0x7f;
197 ctr[14] &= 0x7f;
198 /* open the cipher */
199 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
200 return;
201 }
202 if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
203 gcry_cipher_close(cipher_hd);
204 return;
205 }
206 if (gcry_cipher_setctr(cipher_hd, ctr, EAX_SIZEOF_KEY)) {
207 gcry_cipher_close(cipher_hd);
208 return;
209 }
210 if (gcry_cipher_encrypt(cipher_hd, pN, SizeN, pN, SizeN)) {
211 gcry_cipher_close(cipher_hd);
212 return;
213 }
214 gcry_cipher_close(cipher_hd);
215 return;
216 }
217
AesEncrypt(unsigned char msg[EAX_SIZEOF_KEY],unsigned char key[EAX_SIZEOF_KEY])218 void AesEncrypt(unsigned char msg[EAX_SIZEOF_KEY], unsigned char key[EAX_SIZEOF_KEY])
219 {
220 gcry_cipher_hd_t cipher_hd;
221
222 /* open the cipher */
223 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0)) {
224 return;
225 }
226 if (gcry_cipher_setkey(cipher_hd, key, EAX_SIZEOF_KEY)) {
227 gcry_cipher_close(cipher_hd);
228 return;
229 }
230 if (gcry_cipher_encrypt(cipher_hd, msg, EAX_SIZEOF_KEY, msg, EAX_SIZEOF_KEY)) {
231 gcry_cipher_close(cipher_hd);
232 return;
233 }
234 gcry_cipher_close(cipher_hd);
235 return;
236 }
237
238 /*
239 * Editor modelines - https://www.wireshark.org/tools/modelines.html
240 *
241 * Local variables:
242 * c-basic-offset: 4
243 * tab-width: 8
244 * indent-tabs-mode: nil
245 * End:
246 *
247 * vi: set shiftwidth=4 tabstop=8 expandtab:
248 * :indentSize=4:tabSize=8:noTabs=true:
249 */
250