match_strval > try_val_to_str
[wireshark-wip.git] / wsutil / eax.c
blob217c107909897b5198046eb18b22c01260c8b1cf
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
5 * $Id$
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.
25 #include "config.h"
26 #include <stdlib.h>
27 #ifdef HAVE_LIBGCRYPT
28 #include <string.h>
29 /* Use libgcrypt for cipher libraries. */
30 #include <wsutil/wsgcrypt.h>
31 #include "eax.h"
33 typedef struct {
34 guint8 L[EAX_SIZEOF_KEY];
35 guint8 D[EAX_SIZEOF_KEY];
36 guint8 Q[EAX_SIZEOF_KEY];
37 } eax_s;
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]);
50 /*!
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,
66 guint8 Mode)
68 guint8 wsn[EAX_SIZEOF_KEY];
69 guint8 wsc[EAX_SIZEOF_KEY];
70 int i;
72 /* key size must match this implementation */
73 if (SizeK != EAX_SIZEOF_KEY)
74 return FALSE;
76 /* the key is new */
77 for (i = 0; i < EAX_SIZEOF_KEY; i++)
78 instance.L[i] = 0;
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);
87 } else {
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)
106 if (SizeC == 0)
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);
112 BLK_XOR(wsc, wsn);
114 if (memcmp(pMac, &wsc[EAX_SIZEOF_KEY-sizeof(*pMac)], sizeof(*pMac)) == 0)
116 CTR(wsn, pK, pC, SizeC);
117 return TRUE;
120 return FALSE;
123 /* set up D or Q from L */
124 static void Dbl(guint8 *out, const guint8 *in)
126 int i;
127 guint8 carry = 0;
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;
135 if (carry)
136 out[0] ^= 0x87;
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;
147 guint8 *work;
148 guint8 *ptr;
149 guint16 SizeT = SizeN + SizeC;
150 guint16 worksize = SizeT;
152 /* worksize must be an integral multiple of 16 */
153 if (SizeT & 0xf) {
154 worksize += 0x10 - (worksize & 0xf);
156 work = (guint8 *)g_malloc(worksize);
157 if (work == NULL) {
158 return;
160 memcpy(work, pN, SizeN);
161 if (pC != NULL) {
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) {
169 work[SizeT] = 0x80;
170 for (ptr = &work[SizeT+1]; ptr < &work[worksize]; ptr++)
171 *ptr = 0;
172 ptr= &work[worksize-0x10];
173 BLK_XOR(ptr, instance.Q);
174 } else {
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)) { */
180 g_free(work);
181 return;
183 if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
184 g_free(work);
185 gcry_cipher_close(cipher_hd);
186 return;
188 if (gcry_cipher_setiv(cipher_hd, ws, EAX_SIZEOF_KEY)) {
189 g_free(work);
190 gcry_cipher_close(cipher_hd);
191 return;
193 if (gcry_cipher_encrypt(cipher_hd, work, worksize, work, worksize)) {
194 g_free(work);
195 gcry_cipher_close(cipher_hd);
196 return;
198 memcpy(ws, ptr, EAX_SIZEOF_KEY);
200 g_free(work);
201 gcry_cipher_close(cipher_hd);
202 return;
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];
210 BLK_CPY(ctr, ws);
211 ctr[12] &= 0x7f;
212 ctr[14] &= 0x7f;
213 /* open the cipher */
214 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
215 return;
217 if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
218 gcry_cipher_close(cipher_hd);
219 return;
221 if (gcry_cipher_setctr(cipher_hd, ctr, EAX_SIZEOF_KEY)) {
222 gcry_cipher_close(cipher_hd);
223 return;
225 if (gcry_cipher_encrypt(cipher_hd, pN, SizeN, pN, SizeN)) {
226 gcry_cipher_close(cipher_hd);
227 return;
229 gcry_cipher_close(cipher_hd);
230 return;
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)) {
239 return;
241 if (gcry_cipher_setkey(cipher_hd, key, EAX_SIZEOF_KEY)) {
242 gcry_cipher_close(cipher_hd);
243 return;
245 if (gcry_cipher_encrypt(cipher_hd, msg, EAX_SIZEOF_KEY, msg, EAX_SIZEOF_KEY)) {
246 gcry_cipher_close(cipher_hd);
247 return;
249 gcry_cipher_close(cipher_hd);
250 return;
252 #endif /* HAVE_LIBGCRYPT */