13ff40c12SJohn Marino /*
23ff40c12SJohn Marino  * AES-128 EAX
33ff40c12SJohn Marino  *
43ff40c12SJohn Marino  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
53ff40c12SJohn Marino  *
63ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
73ff40c12SJohn Marino  * See README for more details.
83ff40c12SJohn Marino  */
93ff40c12SJohn Marino 
103ff40c12SJohn Marino #include "includes.h"
113ff40c12SJohn Marino 
123ff40c12SJohn Marino #include "common.h"
133ff40c12SJohn Marino #include "aes.h"
143ff40c12SJohn Marino #include "aes_wrap.h"
153ff40c12SJohn Marino 
163ff40c12SJohn Marino /**
173ff40c12SJohn Marino  * aes_128_eax_encrypt - AES-128 EAX mode encryption
183ff40c12SJohn Marino  * @key: Key for encryption (16 bytes)
193ff40c12SJohn Marino  * @nonce: Nonce for counter mode
203ff40c12SJohn Marino  * @nonce_len: Nonce length in bytes
213ff40c12SJohn Marino  * @hdr: Header data to be authenticity protected
223ff40c12SJohn Marino  * @hdr_len: Length of the header data bytes
233ff40c12SJohn Marino  * @data: Data to encrypt in-place
243ff40c12SJohn Marino  * @data_len: Length of data in bytes
253ff40c12SJohn Marino  * @tag: 16-byte tag value
263ff40c12SJohn Marino  * Returns: 0 on success, -1 on failure
273ff40c12SJohn Marino  */
aes_128_eax_encrypt(const u8 * key,const u8 * nonce,size_t nonce_len,const u8 * hdr,size_t hdr_len,u8 * data,size_t data_len,u8 * tag)283ff40c12SJohn Marino int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
293ff40c12SJohn Marino 			const u8 *hdr, size_t hdr_len,
303ff40c12SJohn Marino 			u8 *data, size_t data_len, u8 *tag)
313ff40c12SJohn Marino {
323ff40c12SJohn Marino 	u8 *buf;
333ff40c12SJohn Marino 	size_t buf_len;
343ff40c12SJohn Marino 	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
353ff40c12SJohn Marino 		data_mac[AES_BLOCK_SIZE];
363ff40c12SJohn Marino 	int i, ret = -1;
373ff40c12SJohn Marino 
383ff40c12SJohn Marino 	if (nonce_len > data_len)
393ff40c12SJohn Marino 		buf_len = nonce_len;
403ff40c12SJohn Marino 	else
413ff40c12SJohn Marino 		buf_len = data_len;
423ff40c12SJohn Marino 	if (hdr_len > buf_len)
433ff40c12SJohn Marino 		buf_len = hdr_len;
443ff40c12SJohn Marino 	buf_len += 16;
453ff40c12SJohn Marino 
463ff40c12SJohn Marino 	buf = os_malloc(buf_len);
473ff40c12SJohn Marino 	if (buf == NULL)
483ff40c12SJohn Marino 		return -1;
493ff40c12SJohn Marino 
503ff40c12SJohn Marino 	os_memset(buf, 0, 15);
513ff40c12SJohn Marino 
523ff40c12SJohn Marino 	buf[15] = 0;
533ff40c12SJohn Marino 	os_memcpy(buf + 16, nonce, nonce_len);
543ff40c12SJohn Marino 	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
553ff40c12SJohn Marino 		goto fail;
563ff40c12SJohn Marino 
573ff40c12SJohn Marino 	buf[15] = 1;
583ff40c12SJohn Marino 	os_memcpy(buf + 16, hdr, hdr_len);
593ff40c12SJohn Marino 	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
603ff40c12SJohn Marino 		goto fail;
613ff40c12SJohn Marino 
623ff40c12SJohn Marino 	if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
633ff40c12SJohn Marino 		goto fail;
643ff40c12SJohn Marino 	buf[15] = 2;
653ff40c12SJohn Marino 	os_memcpy(buf + 16, data, data_len);
663ff40c12SJohn Marino 	if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
673ff40c12SJohn Marino 		goto fail;
683ff40c12SJohn Marino 
693ff40c12SJohn Marino 	for (i = 0; i < AES_BLOCK_SIZE; i++)
703ff40c12SJohn Marino 		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
713ff40c12SJohn Marino 
723ff40c12SJohn Marino 	ret = 0;
733ff40c12SJohn Marino fail:
74*a1157835SDaniel Fojt 	bin_clear_free(buf, buf_len);
753ff40c12SJohn Marino 
763ff40c12SJohn Marino 	return ret;
773ff40c12SJohn Marino }
783ff40c12SJohn Marino 
793ff40c12SJohn Marino 
803ff40c12SJohn Marino /**
813ff40c12SJohn Marino  * aes_128_eax_decrypt - AES-128 EAX mode decryption
823ff40c12SJohn Marino  * @key: Key for decryption (16 bytes)
833ff40c12SJohn Marino  * @nonce: Nonce for counter mode
843ff40c12SJohn Marino  * @nonce_len: Nonce length in bytes
853ff40c12SJohn Marino  * @hdr: Header data to be authenticity protected
863ff40c12SJohn Marino  * @hdr_len: Length of the header data bytes
873ff40c12SJohn Marino  * @data: Data to encrypt in-place
883ff40c12SJohn Marino  * @data_len: Length of data in bytes
893ff40c12SJohn Marino  * @tag: 16-byte tag value
903ff40c12SJohn Marino  * Returns: 0 on success, -1 on failure, -2 if tag does not match
913ff40c12SJohn Marino  */
aes_128_eax_decrypt(const u8 * key,const u8 * nonce,size_t nonce_len,const u8 * hdr,size_t hdr_len,u8 * data,size_t data_len,const u8 * tag)923ff40c12SJohn Marino int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
933ff40c12SJohn Marino 			const u8 *hdr, size_t hdr_len,
943ff40c12SJohn Marino 			u8 *data, size_t data_len, const u8 *tag)
953ff40c12SJohn Marino {
963ff40c12SJohn Marino 	u8 *buf;
973ff40c12SJohn Marino 	size_t buf_len;
983ff40c12SJohn Marino 	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
993ff40c12SJohn Marino 		data_mac[AES_BLOCK_SIZE];
1003ff40c12SJohn Marino 	int i;
1013ff40c12SJohn Marino 
1023ff40c12SJohn Marino 	if (nonce_len > data_len)
1033ff40c12SJohn Marino 		buf_len = nonce_len;
1043ff40c12SJohn Marino 	else
1053ff40c12SJohn Marino 		buf_len = data_len;
1063ff40c12SJohn Marino 	if (hdr_len > buf_len)
1073ff40c12SJohn Marino 		buf_len = hdr_len;
1083ff40c12SJohn Marino 	buf_len += 16;
1093ff40c12SJohn Marino 
1103ff40c12SJohn Marino 	buf = os_malloc(buf_len);
1113ff40c12SJohn Marino 	if (buf == NULL)
1123ff40c12SJohn Marino 		return -1;
1133ff40c12SJohn Marino 
1143ff40c12SJohn Marino 	os_memset(buf, 0, 15);
1153ff40c12SJohn Marino 
1163ff40c12SJohn Marino 	buf[15] = 0;
1173ff40c12SJohn Marino 	os_memcpy(buf + 16, nonce, nonce_len);
1183ff40c12SJohn Marino 	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
1193ff40c12SJohn Marino 		os_free(buf);
1203ff40c12SJohn Marino 		return -1;
1213ff40c12SJohn Marino 	}
1223ff40c12SJohn Marino 
1233ff40c12SJohn Marino 	buf[15] = 1;
1243ff40c12SJohn Marino 	os_memcpy(buf + 16, hdr, hdr_len);
1253ff40c12SJohn Marino 	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
1263ff40c12SJohn Marino 		os_free(buf);
1273ff40c12SJohn Marino 		return -1;
1283ff40c12SJohn Marino 	}
1293ff40c12SJohn Marino 
1303ff40c12SJohn Marino 	buf[15] = 2;
1313ff40c12SJohn Marino 	os_memcpy(buf + 16, data, data_len);
1323ff40c12SJohn Marino 	if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
1333ff40c12SJohn Marino 		os_free(buf);
1343ff40c12SJohn Marino 		return -1;
1353ff40c12SJohn Marino 	}
1363ff40c12SJohn Marino 
1373ff40c12SJohn Marino 	os_free(buf);
1383ff40c12SJohn Marino 
1393ff40c12SJohn Marino 	for (i = 0; i < AES_BLOCK_SIZE; i++) {
1403ff40c12SJohn Marino 		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
1413ff40c12SJohn Marino 			return -2;
1423ff40c12SJohn Marino 	}
1433ff40c12SJohn Marino 
1443ff40c12SJohn Marino 	return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
1453ff40c12SJohn Marino }
146