Line data Source code
1 : /*
2 : * One-key CBC MAC (OMAC1) hash with AES-128
3 : *
4 : * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
5 : *
6 : * This software may be distributed under the terms of the BSD license.
7 : * See README for more details.
8 : */
9 :
10 : #include "includes.h"
11 :
12 : #include "common.h"
13 : #include "aes.h"
14 : #include "aes_wrap.h"
15 :
16 2322 : static void gf_mulx(u8 *pad)
17 : {
18 : int i, carry;
19 :
20 2322 : carry = pad[0] & 0x80;
21 37152 : for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22 34830 : pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23 2322 : pad[AES_BLOCK_SIZE - 1] <<= 1;
24 2322 : if (carry)
25 1276 : pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26 2322 : }
27 :
28 :
29 : /**
30 : * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
31 : * @key: 128-bit key for the hash operation
32 : * @num_elem: Number of elements in the data vector
33 : * @addr: Pointers to the data areas
34 : * @len: Lengths of the data blocks
35 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
36 : * Returns: 0 on success, -1 on failure
37 : *
38 : * This is a mode for using block cipher (AES in this case) for authentication.
39 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
40 : * (SP) 800-38B.
41 : */
42 1212 : int omac1_aes_128_vector(const u8 *key, size_t num_elem,
43 : const u8 *addr[], const size_t *len, u8 *mac)
44 : {
45 : void *ctx;
46 : u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
47 : const u8 *pos, *end;
48 : size_t i, e, left, total_len;
49 :
50 1212 : ctx = aes_encrypt_init(key, 16);
51 1212 : if (ctx == NULL)
52 0 : return -1;
53 1212 : os_memset(cbc, 0, AES_BLOCK_SIZE);
54 :
55 1212 : total_len = 0;
56 2861 : for (e = 0; e < num_elem; e++)
57 1649 : total_len += len[e];
58 1212 : left = total_len;
59 :
60 1212 : e = 0;
61 1212 : pos = addr[0];
62 1212 : end = pos + len[0];
63 :
64 9649 : while (left >= AES_BLOCK_SIZE) {
65 122825 : for (i = 0; i < AES_BLOCK_SIZE; i++) {
66 115600 : cbc[i] ^= *pos++;
67 115600 : if (pos >= end) {
68 539 : e++;
69 539 : pos = addr[e];
70 539 : end = pos + len[e];
71 : }
72 : }
73 7225 : if (left > AES_BLOCK_SIZE)
74 7123 : aes_encrypt(ctx, cbc, cbc);
75 7225 : left -= AES_BLOCK_SIZE;
76 : }
77 :
78 1212 : os_memset(pad, 0, AES_BLOCK_SIZE);
79 1212 : aes_encrypt(ctx, pad, pad);
80 1212 : gf_mulx(pad);
81 :
82 1212 : if (left || total_len == 0) {
83 8690 : for (i = 0; i < left; i++) {
84 7580 : cbc[i] ^= *pos++;
85 7580 : if (pos >= end) {
86 1110 : e++;
87 1110 : pos = addr[e];
88 1110 : end = pos + len[e];
89 : }
90 : }
91 1110 : cbc[left] ^= 0x80;
92 1110 : gf_mulx(pad);
93 : }
94 :
95 20604 : for (i = 0; i < AES_BLOCK_SIZE; i++)
96 19392 : pad[i] ^= cbc[i];
97 1212 : aes_encrypt(ctx, pad, mac);
98 1212 : aes_encrypt_deinit(ctx);
99 1212 : return 0;
100 : }
101 :
102 :
103 : /**
104 : * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
105 : * @key: 128-bit key for the hash operation
106 : * @data: Data buffer for which a MAC is determined
107 : * @data_len: Length of data buffer in bytes
108 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
109 : * Returns: 0 on success, -1 on failure
110 : *
111 : * This is a mode for using block cipher (AES in this case) for authentication.
112 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
113 : * (SP) 800-38B.
114 : */
115 775 : int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
116 : {
117 775 : return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
118 : }
|