2 * Encryption and decryption routines implementing the EAX' encryption mode
3 * Copyright 2010, Edward J. Beroset, edward.j.beroset@us.elster.com
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 /* Use libgcrypt for cipher libraries. */
28 #include <wsutil/wsgcrypt.h>
32 guint8 L[EAX_SIZEOF_KEY];
33 guint8 D[EAX_SIZEOF_KEY];
34 guint8 Q[EAX_SIZEOF_KEY];
37 static eax_s instance;
39 /* these are defined as macros so they'll be easy to redo in assembly if desired */
40 #define BLK_CPY(dst, src) { memcpy(dst, src, EAX_SIZEOF_KEY); }
41 #define BLK_XOR(dst, src) { int z; for (z=0; z < EAX_SIZEOF_KEY; z++) dst[z] ^= src[z]; }
42 static void Dbl(guint8 *out, const guint8 *in);
43 static void CTR(const guint8 *ws, guint8 *pK, guint8 *pN, guint16 SizeN);
44 static void CMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN);
45 static void dCMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN, const guint8 *pC, guint16 SizeC);
46 void AesEncrypt(unsigned char msg[EAX_SIZEOF_KEY], unsigned char key[EAX_SIZEOF_KEY]);
49 Decrypts cleartext data using EAX' mode (see ANSI Standard C12.22-2008).
51 @param[in] pN pointer to cleartext (canonified form)
52 @param[in] pK pointer to secret key
53 @param[in,out] pC pointer to ciphertext
54 @param[in] SizeN byte length of cleartext (pN) buffer
55 @param[in] SizeK byte length of secret key (pK)
56 @param[in] SizeC byte length of ciphertext (pC) buffer
57 @param[in] pMac four-byte Message Authentication Code
58 @param[in] Mode EAX_MODE_CLEARTEXT_AUTH or EAX_MODE_CIPHERTEXT_AUTH
59 @return TRUE if message has been authenticated; FALSE if not
60 authenticated, invalid Mode or error
62 gboolean Eax_Decrypt(guint8 *pN, guint8 *pK, guint8 *pC,
63 guint32 SizeN, guint32 SizeK, guint32 SizeC, MAC_T *pMac,
66 guint8 wsn[EAX_SIZEOF_KEY];
67 guint8 wsc[EAX_SIZEOF_KEY];
70 /* key size must match this implementation */
71 if (SizeK != EAX_SIZEOF_KEY)
75 for (i = 0; i < EAX_SIZEOF_KEY; i++)
77 AesEncrypt(instance.L, pK);
78 Dbl(instance.D, instance.L);
79 Dbl(instance.Q, instance.D);
80 /* the key is set up */
81 /* first copy the nonce into our working space */
82 BLK_CPY(wsn, instance.D);
83 if (Mode == EAX_MODE_CLEARTEXT_AUTH) {
84 dCMAC(pK, wsn, pN, SizeN, pC, SizeC);
86 CMAC(pK, wsn, pN, SizeN);
89 * In authentication mode the inputs are: pN, pK (and associated sizes),
90 * the result is the 4 byte MAC.
92 if (Mode == EAX_MODE_CLEARTEXT_AUTH)
94 return (memcmp(pMac, &wsn[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) ? FALSE : TRUE);
99 * In cipher mode the inputs are: pN, pK, pP (and associated sizes),
100 * the results are pC (and its size) along with the 4 byte MAC.
102 else if (Mode == EAX_MODE_CIPHERTEXT_AUTH)
105 return (memcmp(pMac, &wsn[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) ? FALSE : TRUE);
107 /* first copy the nonce into our working space */
108 BLK_CPY(wsc, instance.Q);
109 CMAC(pK, wsc, pC, SizeC);
112 if (memcmp(pMac, &wsc[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) == 0)
114 CTR(wsn, pK, pC, SizeC);
121 /* set up D or Q from L */
122 static void Dbl(guint8 *out, const guint8 *in)
127 /* this might be a lot more efficient in assembly language */
128 for (i=0; i < EAX_SIZEOF_KEY; i++)
130 out[i] = ( in[i] << 1 ) | carry;
131 carry = (in[i] & 0x80) ? 1 : 0;
137 static void CMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN)
139 dCMAC(pK, ws, pN, SizeN, NULL, 0);
142 static void dCMAC(guint8 *pK, guint8 *ws, const guint8 *pN, guint16 SizeN, const guint8 *pC, guint16 SizeC)
144 gcry_cipher_hd_t cipher_hd;
147 guint16 SizeT = SizeN + SizeC;
148 guint16 worksize = SizeT;
150 /* worksize must be an integral multiple of 16 */
152 worksize += 0x10 - (worksize & 0xf);
154 work = (guint8 *)g_malloc(worksize);
158 memcpy(work, pN, SizeN);
160 memcpy(&work[SizeN], pC, SizeC);
163 * pad the data if necessary, and XOR Q or D, depending on
164 * whether data was padded or not
166 if (worksize != SizeT) {
168 for (ptr = &work[SizeT+1]; ptr < &work[worksize]; ptr++)
170 ptr= &work[worksize-0x10];
171 BLK_XOR(ptr, instance.Q);
173 ptr = &work[worksize-0x10];
174 BLK_XOR(ptr, instance.D);
176 /* open the cipher */
177 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC,0)){/* GCRY_CIPHER_CBC_MAC)) { */
181 if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
183 gcry_cipher_close(cipher_hd);
186 if (gcry_cipher_setiv(cipher_hd, ws, EAX_SIZEOF_KEY)) {
188 gcry_cipher_close(cipher_hd);
191 if (gcry_cipher_encrypt(cipher_hd, work, worksize, work, worksize)) {
193 gcry_cipher_close(cipher_hd);
196 memcpy(ws, ptr, EAX_SIZEOF_KEY);
199 gcry_cipher_close(cipher_hd);
203 static void CTR(const guint8 *ws, guint8 *pK, guint8 *pN, guint16 SizeN)
205 gcry_cipher_hd_t cipher_hd;
206 guint8 ctr[EAX_SIZEOF_KEY];
211 /* open the cipher */
212 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
215 if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
216 gcry_cipher_close(cipher_hd);
219 if (gcry_cipher_setctr(cipher_hd, ctr, EAX_SIZEOF_KEY)) {
220 gcry_cipher_close(cipher_hd);
223 if (gcry_cipher_encrypt(cipher_hd, pN, SizeN, pN, SizeN)) {
224 gcry_cipher_close(cipher_hd);
227 gcry_cipher_close(cipher_hd);
231 void AesEncrypt(unsigned char msg[EAX_SIZEOF_KEY], unsigned char key[EAX_SIZEOF_KEY])
233 gcry_cipher_hd_t cipher_hd;
235 /* open the cipher */
236 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0)) {
239 if (gcry_cipher_setkey(cipher_hd, key, EAX_SIZEOF_KEY)) {
240 gcry_cipher_close(cipher_hd);
243 if (gcry_cipher_encrypt(cipher_hd, msg, EAX_SIZEOF_KEY, msg, EAX_SIZEOF_KEY)) {
244 gcry_cipher_close(cipher_hd);
247 gcry_cipher_close(cipher_hd);
250 #endif /* HAVE_LIBGCRYPT */
253 * Editor modelines - http://www.wireshark.org/tools/modelines.html
258 * indent-tabs-mode: nil
261 * vi: set shiftwidth=4 tabstop=8 expandtab:
262 * :indentSize=4:tabSize=8:noTabs=true: