xref: /netbsd-src/external/bsd/wpa/dist/src/crypto/aes-eax.c (revision bb610346a8016c1ae01add70588fb99ab87e6bab)
18dbcf02cSchristos /*
28dbcf02cSchristos  * AES-128 EAX
38dbcf02cSchristos  *
48dbcf02cSchristos  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
58dbcf02cSchristos  *
6e604d861Schristos  * This software may be distributed under the terms of the BSD license.
7e604d861Schristos  * See README for more details.
88dbcf02cSchristos  */
98dbcf02cSchristos 
108dbcf02cSchristos #include "includes.h"
118dbcf02cSchristos 
128dbcf02cSchristos #include "common.h"
138dbcf02cSchristos #include "aes.h"
148dbcf02cSchristos #include "aes_wrap.h"
158dbcf02cSchristos 
168dbcf02cSchristos /**
178dbcf02cSchristos  * aes_128_eax_encrypt - AES-128 EAX mode encryption
188dbcf02cSchristos  * @key: Key for encryption (16 bytes)
198dbcf02cSchristos  * @nonce: Nonce for counter mode
208dbcf02cSchristos  * @nonce_len: Nonce length in bytes
218dbcf02cSchristos  * @hdr: Header data to be authenticity protected
228dbcf02cSchristos  * @hdr_len: Length of the header data bytes
238dbcf02cSchristos  * @data: Data to encrypt in-place
248dbcf02cSchristos  * @data_len: Length of data in bytes
258dbcf02cSchristos  * @tag: 16-byte tag value
268dbcf02cSchristos  * Returns: 0 on success, -1 on failure
278dbcf02cSchristos  */
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)288dbcf02cSchristos int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
298dbcf02cSchristos 			const u8 *hdr, size_t hdr_len,
308dbcf02cSchristos 			u8 *data, size_t data_len, u8 *tag)
318dbcf02cSchristos {
328dbcf02cSchristos 	u8 *buf;
338dbcf02cSchristos 	size_t buf_len;
348dbcf02cSchristos 	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
358dbcf02cSchristos 		data_mac[AES_BLOCK_SIZE];
368dbcf02cSchristos 	int i, ret = -1;
378dbcf02cSchristos 
388dbcf02cSchristos 	if (nonce_len > data_len)
398dbcf02cSchristos 		buf_len = nonce_len;
408dbcf02cSchristos 	else
418dbcf02cSchristos 		buf_len = data_len;
428dbcf02cSchristos 	if (hdr_len > buf_len)
438dbcf02cSchristos 		buf_len = hdr_len;
448dbcf02cSchristos 	buf_len += 16;
458dbcf02cSchristos 
468dbcf02cSchristos 	buf = os_malloc(buf_len);
478dbcf02cSchristos 	if (buf == NULL)
488dbcf02cSchristos 		return -1;
498dbcf02cSchristos 
508dbcf02cSchristos 	os_memset(buf, 0, 15);
518dbcf02cSchristos 
528dbcf02cSchristos 	buf[15] = 0;
538dbcf02cSchristos 	os_memcpy(buf + 16, nonce, nonce_len);
548dbcf02cSchristos 	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
558dbcf02cSchristos 		goto fail;
568dbcf02cSchristos 
578dbcf02cSchristos 	buf[15] = 1;
588dbcf02cSchristos 	os_memcpy(buf + 16, hdr, hdr_len);
598dbcf02cSchristos 	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
608dbcf02cSchristos 		goto fail;
618dbcf02cSchristos 
628dbcf02cSchristos 	if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
638dbcf02cSchristos 		goto fail;
648dbcf02cSchristos 	buf[15] = 2;
658dbcf02cSchristos 	os_memcpy(buf + 16, data, data_len);
668dbcf02cSchristos 	if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
678dbcf02cSchristos 		goto fail;
688dbcf02cSchristos 
698dbcf02cSchristos 	for (i = 0; i < AES_BLOCK_SIZE; i++)
708dbcf02cSchristos 		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
718dbcf02cSchristos 
728dbcf02cSchristos 	ret = 0;
738dbcf02cSchristos fail:
74*bb610346Schristos 	bin_clear_free(buf, buf_len);
758dbcf02cSchristos 
768dbcf02cSchristos 	return ret;
778dbcf02cSchristos }
788dbcf02cSchristos 
798dbcf02cSchristos 
808dbcf02cSchristos /**
818dbcf02cSchristos  * aes_128_eax_decrypt - AES-128 EAX mode decryption
828dbcf02cSchristos  * @key: Key for decryption (16 bytes)
838dbcf02cSchristos  * @nonce: Nonce for counter mode
848dbcf02cSchristos  * @nonce_len: Nonce length in bytes
858dbcf02cSchristos  * @hdr: Header data to be authenticity protected
868dbcf02cSchristos  * @hdr_len: Length of the header data bytes
878dbcf02cSchristos  * @data: Data to encrypt in-place
888dbcf02cSchristos  * @data_len: Length of data in bytes
898dbcf02cSchristos  * @tag: 16-byte tag value
908dbcf02cSchristos  * Returns: 0 on success, -1 on failure, -2 if tag does not match
918dbcf02cSchristos  */
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)928dbcf02cSchristos int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
938dbcf02cSchristos 			const u8 *hdr, size_t hdr_len,
948dbcf02cSchristos 			u8 *data, size_t data_len, const u8 *tag)
958dbcf02cSchristos {
968dbcf02cSchristos 	u8 *buf;
978dbcf02cSchristos 	size_t buf_len;
988dbcf02cSchristos 	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
998dbcf02cSchristos 		data_mac[AES_BLOCK_SIZE];
1008dbcf02cSchristos 	int i;
1018dbcf02cSchristos 
1028dbcf02cSchristos 	if (nonce_len > data_len)
1038dbcf02cSchristos 		buf_len = nonce_len;
1048dbcf02cSchristos 	else
1058dbcf02cSchristos 		buf_len = data_len;
1068dbcf02cSchristos 	if (hdr_len > buf_len)
1078dbcf02cSchristos 		buf_len = hdr_len;
1088dbcf02cSchristos 	buf_len += 16;
1098dbcf02cSchristos 
1108dbcf02cSchristos 	buf = os_malloc(buf_len);
1118dbcf02cSchristos 	if (buf == NULL)
1128dbcf02cSchristos 		return -1;
1138dbcf02cSchristos 
1148dbcf02cSchristos 	os_memset(buf, 0, 15);
1158dbcf02cSchristos 
1168dbcf02cSchristos 	buf[15] = 0;
1178dbcf02cSchristos 	os_memcpy(buf + 16, nonce, nonce_len);
1188dbcf02cSchristos 	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
1198dbcf02cSchristos 		os_free(buf);
1208dbcf02cSchristos 		return -1;
1218dbcf02cSchristos 	}
1228dbcf02cSchristos 
1238dbcf02cSchristos 	buf[15] = 1;
1248dbcf02cSchristos 	os_memcpy(buf + 16, hdr, hdr_len);
1258dbcf02cSchristos 	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
1268dbcf02cSchristos 		os_free(buf);
1278dbcf02cSchristos 		return -1;
1288dbcf02cSchristos 	}
1298dbcf02cSchristos 
1308dbcf02cSchristos 	buf[15] = 2;
1318dbcf02cSchristos 	os_memcpy(buf + 16, data, data_len);
1328dbcf02cSchristos 	if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
1338dbcf02cSchristos 		os_free(buf);
1348dbcf02cSchristos 		return -1;
1358dbcf02cSchristos 	}
1368dbcf02cSchristos 
1378dbcf02cSchristos 	os_free(buf);
1388dbcf02cSchristos 
1398dbcf02cSchristos 	for (i = 0; i < AES_BLOCK_SIZE; i++) {
1408dbcf02cSchristos 		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
1418dbcf02cSchristos 			return -2;
1428dbcf02cSchristos 	}
1438dbcf02cSchristos 
1448dbcf02cSchristos 	return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
1458dbcf02cSchristos }
146