2 * Encryption and decryption routines implementing the EAX' encryption mode
3 * Copyright 2010, Edward J. Beroset, edward.j.beroset@us.elster.com
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 /* Use libgcrypt for cipher libraries. */
30 #include <wsutil/wsgcrypt.h>
34 guint8 L
[EAX_SIZEOF_KEY
];
35 guint8 D
[EAX_SIZEOF_KEY
];
36 guint8 Q
[EAX_SIZEOF_KEY
];
39 static eax_s instance
;
41 /* these are defined as macros so they'll be easy to redo in assembly if desired */
42 #define BLK_CPY(dst, src) { memcpy(dst, src, EAX_SIZEOF_KEY); }
43 #define BLK_XOR(dst, src) { int z; for (z=0; z < EAX_SIZEOF_KEY; z++) dst[z] ^= src[z]; }
44 static void Dbl(guint8
*out
, const guint8
*in
);
45 static void CTR(const guint8
*ws
, guint8
*pK
, guint8
*pN
, guint16 SizeN
);
46 static void CMAC(guint8
*pK
, guint8
*ws
, const guint8
*pN
, guint16 SizeN
);
47 static void dCMAC(guint8
*pK
, guint8
*ws
, const guint8
*pN
, guint16 SizeN
, const guint8
*pC
, guint16 SizeC
);
48 void AesEncrypt(unsigned char msg
[EAX_SIZEOF_KEY
], unsigned char key
[EAX_SIZEOF_KEY
]);
51 Decrypts cleartext data using EAX' mode (see ANSI Standard C12.22-2008).
53 @param[in] pN pointer to cleartext (canonified form)
54 @param[in] pK pointer to secret key
55 @param[in,out] pC pointer to ciphertext
56 @param[in] SizeN byte length of cleartext (pN) buffer
57 @param[in] SizeK byte length of secret key (pK)
58 @param[in] SizeC byte length of ciphertext (pC) buffer
59 @param[in] pMac four-byte Message Authentication Code
60 @param[in] Mode EAX_MODE_CLEARTEXT_AUTH or EAX_MODE_CIPHERTEXT_AUTH
61 @return TRUE if message has been authenticated; FALSE if not
62 authenticated, invalid Mode or error
64 gboolean
Eax_Decrypt(guint8
*pN
, guint8
*pK
, guint8
*pC
,
65 guint32 SizeN
, guint32 SizeK
, guint32 SizeC
, MAC_T
*pMac
,
68 guint8 wsn
[EAX_SIZEOF_KEY
];
69 guint8 wsc
[EAX_SIZEOF_KEY
];
72 /* key size must match this implementation */
73 if (SizeK
!= EAX_SIZEOF_KEY
)
77 for (i
= 0; i
< EAX_SIZEOF_KEY
; i
++)
79 AesEncrypt(instance
.L
, pK
);
80 Dbl(instance
.D
, instance
.L
);
81 Dbl(instance
.Q
, instance
.D
);
82 /* the key is set up */
83 /* first copy the nonce into our working space */
84 BLK_CPY(wsn
, instance
.D
);
85 if (Mode
== EAX_MODE_CLEARTEXT_AUTH
) {
86 dCMAC(pK
, wsn
, pN
, SizeN
, pC
, SizeC
);
88 CMAC(pK
, wsn
, pN
, SizeN
);
91 * In authentication mode the inputs are: pN, pK (and associated sizes),
92 * the result is the 4 byte MAC.
94 if (Mode
== EAX_MODE_CLEARTEXT_AUTH
)
96 return (memcmp(pMac
, &wsn
[EAX_SIZEOF_KEY
-sizeof(*pMac
)], sizeof(*pMac
)) ? FALSE
: TRUE
);
101 * In cipher mode the inputs are: pN, pK, pP (and associated sizes),
102 * the results are pC (and its size) along with the 4 byte MAC.
104 else if (Mode
== EAX_MODE_CIPHERTEXT_AUTH
)
107 return (memcmp(pMac
, &wsn
[EAX_SIZEOF_KEY
-sizeof(*pMac
)], sizeof(*pMac
)) ? FALSE
: TRUE
);
109 /* first copy the nonce into our working space */
110 BLK_CPY(wsc
, instance
.Q
);
111 CMAC(pK
, wsc
, pC
, SizeC
);
114 if (memcmp(pMac
, &wsc
[EAX_SIZEOF_KEY
-sizeof(*pMac
)], sizeof(*pMac
)) == 0)
116 CTR(wsn
, pK
, pC
, SizeC
);
123 /* set up D or Q from L */
124 static void Dbl(guint8
*out
, const guint8
*in
)
129 /* this might be a lot more efficient in assembly language */
130 for (i
=0; i
< EAX_SIZEOF_KEY
; i
++)
132 out
[i
] = ( in
[i
] << 1 ) | carry
;
133 carry
= (in
[i
] & 0x80) ? 1 : 0;
139 static void CMAC(guint8
*pK
, guint8
*ws
, const guint8
*pN
, guint16 SizeN
)
141 dCMAC(pK
, ws
, pN
, SizeN
, NULL
, 0);
144 static void dCMAC(guint8
*pK
, guint8
*ws
, const guint8
*pN
, guint16 SizeN
, const guint8
*pC
, guint16 SizeC
)
146 gcry_cipher_hd_t cipher_hd
;
149 guint16 SizeT
= SizeN
+ SizeC
;
150 guint16 worksize
= SizeT
;
152 /* worksize must be an integral multiple of 16 */
154 worksize
+= 0x10 - (worksize
& 0xf);
156 work
= (guint8
*)g_malloc(worksize
);
160 memcpy(work
, pN
, SizeN
);
162 memcpy(&work
[SizeN
], pC
, SizeC
);
165 * pad the data if necessary, and XOR Q or D, depending on
166 * whether data was padded or not
168 if (worksize
!= SizeT
) {
170 for (ptr
= &work
[SizeT
+1]; ptr
< &work
[worksize
]; ptr
++)
172 ptr
= &work
[worksize
-0x10];
173 BLK_XOR(ptr
, instance
.Q
);
175 ptr
= &work
[worksize
-0x10];
176 BLK_XOR(ptr
, instance
.D
);
178 /* open the cipher */
179 if (gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CBC
,0)){/* GCRY_CIPHER_CBC_MAC)) { */
183 if (gcry_cipher_setkey(cipher_hd
, pK
, EAX_SIZEOF_KEY
)) {
185 gcry_cipher_close(cipher_hd
);
188 if (gcry_cipher_setiv(cipher_hd
, ws
, EAX_SIZEOF_KEY
)) {
190 gcry_cipher_close(cipher_hd
);
193 if (gcry_cipher_encrypt(cipher_hd
, work
, worksize
, work
, worksize
)) {
195 gcry_cipher_close(cipher_hd
);
198 memcpy(ws
, ptr
, EAX_SIZEOF_KEY
);
201 gcry_cipher_close(cipher_hd
);
205 static void CTR(const guint8
*ws
, guint8
*pK
, guint8
*pN
, guint16 SizeN
)
207 gcry_cipher_hd_t cipher_hd
;
208 guint8 ctr
[EAX_SIZEOF_KEY
];
213 /* open the cipher */
214 if (gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CTR
, 0)) {
217 if (gcry_cipher_setkey(cipher_hd
, pK
, EAX_SIZEOF_KEY
)) {
218 gcry_cipher_close(cipher_hd
);
221 if (gcry_cipher_setctr(cipher_hd
, ctr
, EAX_SIZEOF_KEY
)) {
222 gcry_cipher_close(cipher_hd
);
225 if (gcry_cipher_encrypt(cipher_hd
, pN
, SizeN
, pN
, SizeN
)) {
226 gcry_cipher_close(cipher_hd
);
229 gcry_cipher_close(cipher_hd
);
233 void AesEncrypt(unsigned char msg
[EAX_SIZEOF_KEY
], unsigned char key
[EAX_SIZEOF_KEY
])
235 gcry_cipher_hd_t cipher_hd
;
237 /* open the cipher */
238 if (gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_ECB
, 0)) {
241 if (gcry_cipher_setkey(cipher_hd
, key
, EAX_SIZEOF_KEY
)) {
242 gcry_cipher_close(cipher_hd
);
245 if (gcry_cipher_encrypt(cipher_hd
, msg
, EAX_SIZEOF_KEY
, msg
, EAX_SIZEOF_KEY
)) {
246 gcry_cipher_close(cipher_hd
);
249 gcry_cipher_close(cipher_hd
);
252 #endif /* HAVE_LIBGCRYPT */