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 * SPDX-License-Identifier: GPL-2.0-or-later
15 /* Use libgcrypt for cipher libraries. */
19 uint8_t L
[EAX_SIZEOF_KEY
];
20 uint8_t D
[EAX_SIZEOF_KEY
];
21 uint8_t Q
[EAX_SIZEOF_KEY
];
24 static eax_s instance
;
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(uint8_t *out
, const uint8_t *in
);
30 static void CTR(const uint8_t *ws
, uint8_t *pK
, uint8_t *pN
, uint16_t SizeN
);
31 static void CMAC(uint8_t *pK
, uint8_t *ws
, const uint8_t *pN
, uint16_t SizeN
);
32 static void dCMAC(uint8_t *pK
, uint8_t *ws
, const uint8_t *pN
, uint16_t SizeN
, const uint8_t *pC
, uint16_t SizeC
);
33 void AesEncrypt(unsigned char msg
[EAX_SIZEOF_KEY
], unsigned char key
[EAX_SIZEOF_KEY
]);
36 Decrypts cleartext data using EAX' mode (see ANSI Standard C12.22-2008).
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
49 bool Eax_Decrypt(uint8_t *pN
, uint8_t *pK
, uint8_t *pC
,
50 uint32_t SizeN
, uint32_t SizeK
, uint32_t SizeC
, MAC_T
*pMac
,
53 uint8_t wsn
[EAX_SIZEOF_KEY
];
54 uint8_t wsc
[EAX_SIZEOF_KEY
];
57 /* key size must match this implementation */
58 if (SizeK
!= EAX_SIZEOF_KEY
)
62 for (i
= 0; i
< EAX_SIZEOF_KEY
; i
++)
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
);
73 CMAC(pK
, wsn
, pN
, SizeN
);
76 * In authentication mode the inputs are: pN, pK (and associated sizes),
77 * the result is the 4 byte MAC.
79 if (Mode
== EAX_MODE_CLEARTEXT_AUTH
)
81 return (memcmp(pMac
, &wsn
[EAX_SIZEOF_KEY
-sizeof(*pMac
)], sizeof(*pMac
)) ? false : true);
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.
89 else if (Mode
== EAX_MODE_CIPHERTEXT_AUTH
)
92 return (memcmp(pMac
, &wsn
[EAX_SIZEOF_KEY
-sizeof(*pMac
)], sizeof(*pMac
)) ? false : true);
94 /* first copy the nonce into our working space */
95 BLK_CPY(wsc
, instance
.Q
);
96 CMAC(pK
, wsc
, pC
, SizeC
);
99 if (memcmp(pMac
, &wsc
[EAX_SIZEOF_KEY
-sizeof(*pMac
)], sizeof(*pMac
)) == 0)
101 CTR(wsn
, pK
, pC
, SizeC
);
108 /* set up D or Q from L */
109 static void Dbl(uint8_t *out
, const uint8_t *in
)
114 /* this might be a lot more efficient in assembly language */
115 for (i
=0; i
< EAX_SIZEOF_KEY
; i
++)
117 out
[i
] = ( in
[i
] << 1 ) | carry
;
118 carry
= (in
[i
] & 0x80) ? 1 : 0;
124 static void CMAC(uint8_t *pK
, uint8_t *ws
, const uint8_t *pN
, uint16_t SizeN
)
126 dCMAC(pK
, ws
, pN
, SizeN
, NULL
, 0);
129 static void dCMAC(uint8_t *pK
, uint8_t *ws
, const uint8_t *pN
, uint16_t SizeN
, const uint8_t *pC
, uint16_t SizeC
)
131 gcry_cipher_hd_t cipher_hd
;
134 uint16_t SizeT
= SizeN
+ SizeC
;
135 uint16_t worksize
= SizeT
;
137 /* worksize must be an integral multiple of 16 */
139 worksize
+= 0x10 - (worksize
& 0xf);
141 work
= (uint8_t *)g_malloc(worksize
);
145 memcpy(work
, pN
, SizeN
);
147 memcpy(&work
[SizeN
], pC
, SizeC
);
150 * pad the data if necessary, and XOR Q or D, depending on
151 * whether data was padded or not
153 if (worksize
!= SizeT
) {
155 for (ptr
= &work
[SizeT
+1]; ptr
< &work
[worksize
]; ptr
++)
157 ptr
= &work
[worksize
-0x10];
158 BLK_XOR(ptr
, instance
.Q
);
160 ptr
= &work
[worksize
-0x10];
161 BLK_XOR(ptr
, instance
.D
);
163 /* open the cipher */
164 if (gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CBC
,0)){/* GCRY_CIPHER_CBC_MAC)) { */
168 if (gcry_cipher_setkey(cipher_hd
, pK
, EAX_SIZEOF_KEY
)) {
170 gcry_cipher_close(cipher_hd
);
173 if (gcry_cipher_setiv(cipher_hd
, ws
, EAX_SIZEOF_KEY
)) {
175 gcry_cipher_close(cipher_hd
);
178 if (gcry_cipher_encrypt(cipher_hd
, work
, worksize
, work
, worksize
)) {
180 gcry_cipher_close(cipher_hd
);
183 memcpy(ws
, ptr
, EAX_SIZEOF_KEY
);
186 gcry_cipher_close(cipher_hd
);
190 static void CTR(const uint8_t *ws
, uint8_t *pK
, uint8_t *pN
, uint16_t SizeN
)
192 gcry_cipher_hd_t cipher_hd
;
193 uint8_t ctr
[EAX_SIZEOF_KEY
];
198 /* open the cipher */
199 if (gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CTR
, 0)) {
202 if (gcry_cipher_setkey(cipher_hd
, pK
, EAX_SIZEOF_KEY
)) {
203 gcry_cipher_close(cipher_hd
);
206 if (gcry_cipher_setctr(cipher_hd
, ctr
, EAX_SIZEOF_KEY
)) {
207 gcry_cipher_close(cipher_hd
);
210 if (gcry_cipher_encrypt(cipher_hd
, pN
, SizeN
, pN
, SizeN
)) {
211 gcry_cipher_close(cipher_hd
);
214 gcry_cipher_close(cipher_hd
);
218 void AesEncrypt(unsigned char msg
[EAX_SIZEOF_KEY
], unsigned char key
[EAX_SIZEOF_KEY
])
220 gcry_cipher_hd_t cipher_hd
;
222 /* open the cipher */
223 if (gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_ECB
, 0)) {
226 if (gcry_cipher_setkey(cipher_hd
, key
, EAX_SIZEOF_KEY
)) {
227 gcry_cipher_close(cipher_hd
);
230 if (gcry_cipher_encrypt(cipher_hd
, msg
, EAX_SIZEOF_KEY
, msg
, EAX_SIZEOF_KEY
)) {
231 gcry_cipher_close(cipher_hd
);
234 gcry_cipher_close(cipher_hd
);
239 * Editor modelines - https://www.wireshark.org/tools/modelines.html
244 * indent-tabs-mode: nil
247 * vi: set shiftwidth=4 tabstop=8 expandtab:
248 * :indentSize=4:tabSize=8:noTabs=true: