1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * One-key CBC MAC (OMAC1) hash with AES
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_cistatic void gf_mulx(u8 *pad)
17e5b75505Sopenharmony_ci{
18e5b75505Sopenharmony_ci	int i, carry;
19e5b75505Sopenharmony_ci
20e5b75505Sopenharmony_ci	carry = pad[0] & 0x80;
21e5b75505Sopenharmony_ci	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22e5b75505Sopenharmony_ci		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23e5b75505Sopenharmony_ci	pad[AES_BLOCK_SIZE - 1] <<= 1;
24e5b75505Sopenharmony_ci	if (carry)
25e5b75505Sopenharmony_ci		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26e5b75505Sopenharmony_ci}
27e5b75505Sopenharmony_ci
28e5b75505Sopenharmony_ci
29e5b75505Sopenharmony_ci/**
30e5b75505Sopenharmony_ci * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES
31e5b75505Sopenharmony_ci * @key: Key for the hash operation
32e5b75505Sopenharmony_ci * @key_len: Key length in octets
33e5b75505Sopenharmony_ci * @num_elem: Number of elements in the data vector
34e5b75505Sopenharmony_ci * @addr: Pointers to the data areas
35e5b75505Sopenharmony_ci * @len: Lengths of the data blocks
36e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
37e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure
38e5b75505Sopenharmony_ci *
39e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication.
40e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
41e5b75505Sopenharmony_ci * (SP) 800-38B.
42e5b75505Sopenharmony_ci */
43e5b75505Sopenharmony_ciint omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
44e5b75505Sopenharmony_ci		     const u8 *addr[], const size_t *len, u8 *mac)
45e5b75505Sopenharmony_ci{
46e5b75505Sopenharmony_ci	void *ctx;
47e5b75505Sopenharmony_ci	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
48e5b75505Sopenharmony_ci	const u8 *pos, *end;
49e5b75505Sopenharmony_ci	size_t i, e, left, total_len;
50e5b75505Sopenharmony_ci
51e5b75505Sopenharmony_ci	if (TEST_FAIL())
52e5b75505Sopenharmony_ci		return -1;
53e5b75505Sopenharmony_ci
54e5b75505Sopenharmony_ci	ctx = aes_encrypt_init(key, key_len);
55e5b75505Sopenharmony_ci	if (ctx == NULL)
56e5b75505Sopenharmony_ci		return -1;
57e5b75505Sopenharmony_ci	os_memset(cbc, 0, AES_BLOCK_SIZE);
58e5b75505Sopenharmony_ci
59e5b75505Sopenharmony_ci	total_len = 0;
60e5b75505Sopenharmony_ci	for (e = 0; e < num_elem; e++)
61e5b75505Sopenharmony_ci		total_len += len[e];
62e5b75505Sopenharmony_ci	left = total_len;
63e5b75505Sopenharmony_ci
64e5b75505Sopenharmony_ci	e = 0;
65e5b75505Sopenharmony_ci	pos = addr[0];
66e5b75505Sopenharmony_ci	end = pos + len[0];
67e5b75505Sopenharmony_ci
68e5b75505Sopenharmony_ci	while (left >= AES_BLOCK_SIZE) {
69e5b75505Sopenharmony_ci		for (i = 0; i < AES_BLOCK_SIZE; i++) {
70e5b75505Sopenharmony_ci			cbc[i] ^= *pos++;
71e5b75505Sopenharmony_ci			if (pos >= end) {
72e5b75505Sopenharmony_ci				/*
73e5b75505Sopenharmony_ci				 * Stop if there are no more bytes to process
74e5b75505Sopenharmony_ci				 * since there are no more entries in the array.
75e5b75505Sopenharmony_ci				 */
76e5b75505Sopenharmony_ci				if (i + 1 == AES_BLOCK_SIZE &&
77e5b75505Sopenharmony_ci				    left == AES_BLOCK_SIZE)
78e5b75505Sopenharmony_ci					break;
79e5b75505Sopenharmony_ci				e++;
80e5b75505Sopenharmony_ci				pos = addr[e];
81e5b75505Sopenharmony_ci				end = pos + len[e];
82e5b75505Sopenharmony_ci			}
83e5b75505Sopenharmony_ci		}
84e5b75505Sopenharmony_ci		if (left > AES_BLOCK_SIZE)
85e5b75505Sopenharmony_ci			aes_encrypt(ctx, cbc, cbc);
86e5b75505Sopenharmony_ci		left -= AES_BLOCK_SIZE;
87e5b75505Sopenharmony_ci	}
88e5b75505Sopenharmony_ci
89e5b75505Sopenharmony_ci	os_memset(pad, 0, AES_BLOCK_SIZE);
90e5b75505Sopenharmony_ci	aes_encrypt(ctx, pad, pad);
91e5b75505Sopenharmony_ci	gf_mulx(pad);
92e5b75505Sopenharmony_ci
93e5b75505Sopenharmony_ci	if (left || total_len == 0) {
94e5b75505Sopenharmony_ci		for (i = 0; i < left; i++) {
95e5b75505Sopenharmony_ci			cbc[i] ^= *pos++;
96e5b75505Sopenharmony_ci			if (pos >= end) {
97e5b75505Sopenharmony_ci				/*
98e5b75505Sopenharmony_ci				 * Stop if there are no more bytes to process
99e5b75505Sopenharmony_ci				 * since there are no more entries in the array.
100e5b75505Sopenharmony_ci				 */
101e5b75505Sopenharmony_ci				if (i + 1 == left)
102e5b75505Sopenharmony_ci					break;
103e5b75505Sopenharmony_ci				e++;
104e5b75505Sopenharmony_ci				pos = addr[e];
105e5b75505Sopenharmony_ci				end = pos + len[e];
106e5b75505Sopenharmony_ci			}
107e5b75505Sopenharmony_ci		}
108e5b75505Sopenharmony_ci		cbc[left] ^= 0x80;
109e5b75505Sopenharmony_ci		gf_mulx(pad);
110e5b75505Sopenharmony_ci	}
111e5b75505Sopenharmony_ci
112e5b75505Sopenharmony_ci	for (i = 0; i < AES_BLOCK_SIZE; i++)
113e5b75505Sopenharmony_ci		pad[i] ^= cbc[i];
114e5b75505Sopenharmony_ci	aes_encrypt(ctx, pad, mac);
115e5b75505Sopenharmony_ci	aes_encrypt_deinit(ctx);
116e5b75505Sopenharmony_ci	return 0;
117e5b75505Sopenharmony_ci}
118e5b75505Sopenharmony_ci
119e5b75505Sopenharmony_ci
120e5b75505Sopenharmony_ci/**
121e5b75505Sopenharmony_ci * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
122e5b75505Sopenharmony_ci * @key: 128-bit key for the hash operation
123e5b75505Sopenharmony_ci * @num_elem: Number of elements in the data vector
124e5b75505Sopenharmony_ci * @addr: Pointers to the data areas
125e5b75505Sopenharmony_ci * @len: Lengths of the data blocks
126e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
127e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure
128e5b75505Sopenharmony_ci *
129e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication.
130e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
131e5b75505Sopenharmony_ci * (SP) 800-38B.
132e5b75505Sopenharmony_ci */
133e5b75505Sopenharmony_ciint omac1_aes_128_vector(const u8 *key, size_t num_elem,
134e5b75505Sopenharmony_ci			 const u8 *addr[], const size_t *len, u8 *mac)
135e5b75505Sopenharmony_ci{
136e5b75505Sopenharmony_ci	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
137e5b75505Sopenharmony_ci}
138e5b75505Sopenharmony_ci
139e5b75505Sopenharmony_ci
140e5b75505Sopenharmony_ci/**
141e5b75505Sopenharmony_ci * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
142e5b75505Sopenharmony_ci * @key: 128-bit key for the hash operation
143e5b75505Sopenharmony_ci * @data: Data buffer for which a MAC is determined
144e5b75505Sopenharmony_ci * @data_len: Length of data buffer in bytes
145e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
146e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure
147e5b75505Sopenharmony_ci *
148e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication.
149e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
150e5b75505Sopenharmony_ci * (SP) 800-38B.
151e5b75505Sopenharmony_ci */
152e5b75505Sopenharmony_ciint omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
153e5b75505Sopenharmony_ci{
154e5b75505Sopenharmony_ci	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
155e5b75505Sopenharmony_ci}
156e5b75505Sopenharmony_ci
157e5b75505Sopenharmony_ci
158e5b75505Sopenharmony_ci/**
159e5b75505Sopenharmony_ci * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
160e5b75505Sopenharmony_ci * @key: 256-bit key for the hash operation
161e5b75505Sopenharmony_ci * @data: Data buffer for which a MAC is determined
162e5b75505Sopenharmony_ci * @data_len: Length of data buffer in bytes
163e5b75505Sopenharmony_ci * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
164e5b75505Sopenharmony_ci * Returns: 0 on success, -1 on failure
165e5b75505Sopenharmony_ci *
166e5b75505Sopenharmony_ci * This is a mode for using block cipher (AES in this case) for authentication.
167e5b75505Sopenharmony_ci * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
168e5b75505Sopenharmony_ci * (SP) 800-38B.
169e5b75505Sopenharmony_ci */
170e5b75505Sopenharmony_ciint omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
171e5b75505Sopenharmony_ci{
172e5b75505Sopenharmony_ci	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
173e5b75505Sopenharmony_ci}
174