aes-eax.c revision 214734
1195609Smp/*
259243Sobrien * AES-128 EAX
359243Sobrien *
459243Sobrien * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
559243Sobrien *
659243Sobrien * This program is free software; you can redistribute it and/or modify
759243Sobrien * it under the terms of the GNU General Public License version 2 as
859243Sobrien * published by the Free Software Foundation.
959243Sobrien *
1059243Sobrien * Alternatively, this software may be distributed under the terms of BSD
1159243Sobrien * license.
1259243Sobrien *
1359243Sobrien * See README and COPYING for more details.
1459243Sobrien */
1559243Sobrien
1659243Sobrien#include "includes.h"
17100616Smp
1859243Sobrien#include "common.h"
1959243Sobrien#include "aes.h"
2059243Sobrien#include "aes_wrap.h"
2159243Sobrien
2259243Sobrien/**
2359243Sobrien * aes_128_eax_encrypt - AES-128 EAX mode encryption
2459243Sobrien * @key: Key for encryption (16 bytes)
2559243Sobrien * @nonce: Nonce for counter mode
2659243Sobrien * @nonce_len: Nonce length in bytes
2759243Sobrien * @hdr: Header data to be authenticity protected
2859243Sobrien * @hdr_len: Length of the header data bytes
2959243Sobrien * @data: Data to encrypt in-place
3059243Sobrien * @data_len: Length of data in bytes
3159243Sobrien * @tag: 16-byte tag value
3259243Sobrien * Returns: 0 on success, -1 on failure
3359243Sobrien */
34100616Smpint aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
3559243Sobrien			const u8 *hdr, size_t hdr_len,
36195609Smp			u8 *data, size_t data_len, u8 *tag)
3759243Sobrien{
38100616Smp	u8 *buf;
3959243Sobrien	size_t buf_len;
4059243Sobrien	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
4159243Sobrien		data_mac[AES_BLOCK_SIZE];
4259243Sobrien	int i, ret = -1;
4359243Sobrien
4459243Sobrien	if (nonce_len > data_len)
4559243Sobrien		buf_len = nonce_len;
4659243Sobrien	else
4759243Sobrien		buf_len = data_len;
4859243Sobrien	if (hdr_len > buf_len)
4959243Sobrien		buf_len = hdr_len;
5059243Sobrien	buf_len += 16;
5159243Sobrien
5259243Sobrien	buf = os_malloc(buf_len);
5359243Sobrien	if (buf == NULL)
5459243Sobrien		return -1;
5559243Sobrien
5659243Sobrien	os_memset(buf, 0, 15);
5759243Sobrien
5859243Sobrien	buf[15] = 0;
5959243Sobrien	os_memcpy(buf + 16, nonce, nonce_len);
6059243Sobrien	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
6159243Sobrien		goto fail;
62167465Smp
63167465Smp	buf[15] = 1;
64167465Smp	os_memcpy(buf + 16, hdr, hdr_len);
65167465Smp	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
66167465Smp		goto fail;
67167465Smp
68167465Smp	if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
69167465Smp		goto fail;
70167465Smp	buf[15] = 2;
71167465Smp	os_memcpy(buf + 16, data, data_len);
72167465Smp	if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
73167465Smp		goto fail;
74167465Smp
75167465Smp	for (i = 0; i < AES_BLOCK_SIZE; i++)
76167465Smp		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
77167465Smp
78167465Smp	ret = 0;
7959243Sobrienfail:
8059243Sobrien	os_free(buf);
8159243Sobrien
8259243Sobrien	return ret;
8359243Sobrien}
8459243Sobrien
8559243Sobrien
86145479Smp/**
8759243Sobrien * aes_128_eax_decrypt - AES-128 EAX mode decryption
8859243Sobrien * @key: Key for decryption (16 bytes)
89167465Smp * @nonce: Nonce for counter mode
9059243Sobrien * @nonce_len: Nonce length in bytes
9159243Sobrien * @hdr: Header data to be authenticity protected
9259243Sobrien * @hdr_len: Length of the header data bytes
9359243Sobrien * @data: Data to encrypt in-place
9459243Sobrien * @data_len: Length of data in bytes
9559243Sobrien * @tag: 16-byte tag value
9659243Sobrien * Returns: 0 on success, -1 on failure, -2 if tag does not match
9759243Sobrien */
9859243Sobrienint aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
9959243Sobrien			const u8 *hdr, size_t hdr_len,
10059243Sobrien			u8 *data, size_t data_len, const u8 *tag)
10159243Sobrien{
10259243Sobrien	u8 *buf;
10359243Sobrien	size_t buf_len;
10459243Sobrien	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
10559243Sobrien		data_mac[AES_BLOCK_SIZE];
10659243Sobrien	int i;
10759243Sobrien
10859243Sobrien	if (nonce_len > data_len)
10959243Sobrien		buf_len = nonce_len;
11059243Sobrien	else
11159243Sobrien		buf_len = data_len;
11259243Sobrien	if (hdr_len > buf_len)
11359243Sobrien		buf_len = hdr_len;
11459243Sobrien	buf_len += 16;
11559243Sobrien
11659243Sobrien	buf = os_malloc(buf_len);
11759243Sobrien	if (buf == NULL)
11859243Sobrien		return -1;
11959243Sobrien
12059243Sobrien	os_memset(buf, 0, 15);
12159243Sobrien
12259243Sobrien	buf[15] = 0;
12359243Sobrien	os_memcpy(buf + 16, nonce, nonce_len);
12459243Sobrien	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
12559243Sobrien		os_free(buf);
12659243Sobrien		return -1;
12759243Sobrien	}
12859243Sobrien
12959243Sobrien	buf[15] = 1;
130167465Smp	os_memcpy(buf + 16, hdr, hdr_len);
13159243Sobrien	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
13259243Sobrien		os_free(buf);
13359243Sobrien		return -1;
13459243Sobrien	}
13559243Sobrien
13659243Sobrien	buf[15] = 2;
13759243Sobrien	os_memcpy(buf + 16, data, data_len);
13859243Sobrien	if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
13959243Sobrien		os_free(buf);
14059243Sobrien		return -1;
14159243Sobrien	}
14259243Sobrien
14359243Sobrien	os_free(buf);
14459243Sobrien
14559243Sobrien	for (i = 0; i < AES_BLOCK_SIZE; i++) {
14659243Sobrien		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
14759243Sobrien			return -2;
14859243Sobrien	}
14959243Sobrien
15059243Sobrien	return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
15159243Sobrien}
15259243Sobrien