1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * AES-128 EAX
3e5b75505Sopenharmony_ci *
4e5b75505Sopenharmony_ci * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
5e5b75505Sopenharmony_ci *
6e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
7e5b75505Sopenharmony_ci * See README for more details.
8e5b75505Sopenharmony_ci */
9e5b75505Sopenharmony_ci
10e5b75505Sopenharmony_ci#include "includes.h"
11e5b75505Sopenharmony_ci
12e5b75505Sopenharmony_ci#include "common.h"
13e5b75505Sopenharmony_ci#include "aes.h"
14e5b75505Sopenharmony_ci#include "aes_wrap.h"
15e5b75505Sopenharmony_ci
16e5b75505Sopenharmony_ci/**
17e5b75505Sopenharmony_ci * aes_128_eax_encrypt - AES-128 EAX mode encryption
18e5b75505Sopenharmony_ci * @key: Key for encryption (16 bytes)
19e5b75505Sopenharmony_ci * @nonce: Nonce for counter mode
20e5b75505Sopenharmony_ci * @nonce_len: Nonce length in bytes
21e5b75505Sopenharmony_ci * @hdr: Header data to be authenticity protected
22e5b75505Sopenharmony_ci * @hdr_len: Length of the header data bytes
23e5b75505Sopenharmony_ci * @data: Data to encrypt in-place
24e5b75505Sopenharmony_ci * @data_len: Length of data in bytes
25e5b75505Sopenharmony_ci * @tag: 16-byte tag value
26e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure
27e5b75505Sopenharmony_ci */
28e5b75505Sopenharmony_ciint aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
29e5b75505Sopenharmony_ci			const u8 *hdr, size_t hdr_len,
30e5b75505Sopenharmony_ci			u8 *data, size_t data_len, u8 *tag)
31e5b75505Sopenharmony_ci{
32e5b75505Sopenharmony_ci	u8 *buf;
33e5b75505Sopenharmony_ci	size_t buf_len;
34e5b75505Sopenharmony_ci	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
35e5b75505Sopenharmony_ci		data_mac[AES_BLOCK_SIZE];
36e5b75505Sopenharmony_ci	int i, ret = -1;
37e5b75505Sopenharmony_ci
38e5b75505Sopenharmony_ci	if (nonce_len > data_len)
39e5b75505Sopenharmony_ci		buf_len = nonce_len;
40e5b75505Sopenharmony_ci	else
41e5b75505Sopenharmony_ci		buf_len = data_len;
42e5b75505Sopenharmony_ci	if (hdr_len > buf_len)
43e5b75505Sopenharmony_ci		buf_len = hdr_len;
44e5b75505Sopenharmony_ci	buf_len += 16;
45e5b75505Sopenharmony_ci
46e5b75505Sopenharmony_ci	buf = os_malloc(buf_len);
47e5b75505Sopenharmony_ci	if (buf == NULL)
48e5b75505Sopenharmony_ci		return -1;
49e5b75505Sopenharmony_ci
50e5b75505Sopenharmony_ci	os_memset(buf, 0, 15);
51e5b75505Sopenharmony_ci
52e5b75505Sopenharmony_ci	buf[15] = 0;
53e5b75505Sopenharmony_ci	os_memcpy(buf + 16, nonce, nonce_len);
54e5b75505Sopenharmony_ci	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
55e5b75505Sopenharmony_ci		goto fail;
56e5b75505Sopenharmony_ci
57e5b75505Sopenharmony_ci	buf[15] = 1;
58e5b75505Sopenharmony_ci	os_memcpy(buf + 16, hdr, hdr_len);
59e5b75505Sopenharmony_ci	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
60e5b75505Sopenharmony_ci		goto fail;
61e5b75505Sopenharmony_ci
62e5b75505Sopenharmony_ci	if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
63e5b75505Sopenharmony_ci		goto fail;
64e5b75505Sopenharmony_ci	buf[15] = 2;
65e5b75505Sopenharmony_ci	os_memcpy(buf + 16, data, data_len);
66e5b75505Sopenharmony_ci	if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
67e5b75505Sopenharmony_ci		goto fail;
68e5b75505Sopenharmony_ci
69e5b75505Sopenharmony_ci	for (i = 0; i < AES_BLOCK_SIZE; i++)
70e5b75505Sopenharmony_ci		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
71e5b75505Sopenharmony_ci
72e5b75505Sopenharmony_ci	ret = 0;
73e5b75505Sopenharmony_cifail:
74e5b75505Sopenharmony_ci	bin_clear_free(buf, buf_len);
75e5b75505Sopenharmony_ci
76e5b75505Sopenharmony_ci	return ret;
77e5b75505Sopenharmony_ci}
78e5b75505Sopenharmony_ci
79e5b75505Sopenharmony_ci
80e5b75505Sopenharmony_ci/**
81e5b75505Sopenharmony_ci * aes_128_eax_decrypt - AES-128 EAX mode decryption
82e5b75505Sopenharmony_ci * @key: Key for decryption (16 bytes)
83e5b75505Sopenharmony_ci * @nonce: Nonce for counter mode
84e5b75505Sopenharmony_ci * @nonce_len: Nonce length in bytes
85e5b75505Sopenharmony_ci * @hdr: Header data to be authenticity protected
86e5b75505Sopenharmony_ci * @hdr_len: Length of the header data bytes
87e5b75505Sopenharmony_ci * @data: Data to encrypt in-place
88e5b75505Sopenharmony_ci * @data_len: Length of data in bytes
89e5b75505Sopenharmony_ci * @tag: 16-byte tag value
90e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure, -2 if tag does not match
91e5b75505Sopenharmony_ci */
92e5b75505Sopenharmony_ciint aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
93e5b75505Sopenharmony_ci			const u8 *hdr, size_t hdr_len,
94e5b75505Sopenharmony_ci			u8 *data, size_t data_len, const u8 *tag)
95e5b75505Sopenharmony_ci{
96e5b75505Sopenharmony_ci	u8 *buf;
97e5b75505Sopenharmony_ci	size_t buf_len;
98e5b75505Sopenharmony_ci	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
99e5b75505Sopenharmony_ci		data_mac[AES_BLOCK_SIZE];
100e5b75505Sopenharmony_ci	int i;
101e5b75505Sopenharmony_ci
102e5b75505Sopenharmony_ci	if (nonce_len > data_len)
103e5b75505Sopenharmony_ci		buf_len = nonce_len;
104e5b75505Sopenharmony_ci	else
105e5b75505Sopenharmony_ci		buf_len = data_len;
106e5b75505Sopenharmony_ci	if (hdr_len > buf_len)
107e5b75505Sopenharmony_ci		buf_len = hdr_len;
108e5b75505Sopenharmony_ci	buf_len += 16;
109e5b75505Sopenharmony_ci
110e5b75505Sopenharmony_ci	buf = os_malloc(buf_len);
111e5b75505Sopenharmony_ci	if (buf == NULL)
112e5b75505Sopenharmony_ci		return -1;
113e5b75505Sopenharmony_ci
114e5b75505Sopenharmony_ci	os_memset(buf, 0, 15);
115e5b75505Sopenharmony_ci
116e5b75505Sopenharmony_ci	buf[15] = 0;
117e5b75505Sopenharmony_ci	os_memcpy(buf + 16, nonce, nonce_len);
118e5b75505Sopenharmony_ci	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
119e5b75505Sopenharmony_ci		os_free(buf);
120e5b75505Sopenharmony_ci		return -1;
121e5b75505Sopenharmony_ci	}
122e5b75505Sopenharmony_ci
123e5b75505Sopenharmony_ci	buf[15] = 1;
124e5b75505Sopenharmony_ci	os_memcpy(buf + 16, hdr, hdr_len);
125e5b75505Sopenharmony_ci	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
126e5b75505Sopenharmony_ci		os_free(buf);
127e5b75505Sopenharmony_ci		return -1;
128e5b75505Sopenharmony_ci	}
129e5b75505Sopenharmony_ci
130e5b75505Sopenharmony_ci	buf[15] = 2;
131e5b75505Sopenharmony_ci	os_memcpy(buf + 16, data, data_len);
132e5b75505Sopenharmony_ci	if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
133e5b75505Sopenharmony_ci		os_free(buf);
134e5b75505Sopenharmony_ci		return -1;
135e5b75505Sopenharmony_ci	}
136e5b75505Sopenharmony_ci
137e5b75505Sopenharmony_ci	os_free(buf);
138e5b75505Sopenharmony_ci
139e5b75505Sopenharmony_ci	for (i = 0; i < AES_BLOCK_SIZE; i++) {
140e5b75505Sopenharmony_ci		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
141e5b75505Sopenharmony_ci			return -2;
142e5b75505Sopenharmony_ci	}
143e5b75505Sopenharmony_ci
144e5b75505Sopenharmony_ci	return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
145e5b75505Sopenharmony_ci}
146