Branch data 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 : 737 : static void gf_mulx(u8 *pad)
17 : : {
18 : : int i, carry;
19 : :
20 : 737 : carry = pad[0] & 0x80;
21 [ + + ]: 11792 : for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22 : 11055 : pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23 : 737 : pad[AES_BLOCK_SIZE - 1] <<= 1;
24 [ + + ]: 737 : if (carry)
25 : 437 : pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26 : 737 : }
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 : 379 : 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 : 379 : ctx = aes_encrypt_init(key, 16);
51 [ - + ]: 379 : if (ctx == NULL)
52 : 0 : return -1;
53 : 379 : os_memset(cbc, 0, AES_BLOCK_SIZE);
54 : :
55 : 379 : total_len = 0;
56 [ + + ]: 866 : for (e = 0; e < num_elem; e++)
57 : 487 : total_len += len[e];
58 : 379 : left = total_len;
59 : :
60 : 379 : e = 0;
61 : 379 : pos = addr[0];
62 : 379 : end = pos + len[0];
63 : :
64 [ + + ]: 3014 : while (left >= AES_BLOCK_SIZE) {
65 [ + + ]: 44795 : for (i = 0; i < AES_BLOCK_SIZE; i++) {
66 : 42160 : cbc[i] ^= *pos++;
67 [ + + ]: 42160 : if (pos >= end) {
68 : 129 : e++;
69 : 129 : pos = addr[e];
70 : 129 : end = pos + len[e];
71 : : }
72 : : }
73 [ + + ]: 2635 : if (left > AES_BLOCK_SIZE)
74 : 2614 : aes_encrypt(ctx, cbc, cbc);
75 : 2635 : left -= AES_BLOCK_SIZE;
76 : : }
77 : :
78 : 379 : os_memset(pad, 0, AES_BLOCK_SIZE);
79 : 379 : aes_encrypt(ctx, pad, pad);
80 : 379 : gf_mulx(pad);
81 : :
82 [ + + ][ - + ]: 379 : if (left || total_len == 0) {
83 [ + + ]: 2723 : for (i = 0; i < left; i++) {
84 : 2365 : cbc[i] ^= *pos++;
85 [ + + ]: 2365 : if (pos >= end) {
86 : 358 : e++;
87 : 358 : pos = addr[e];
88 : 358 : end = pos + len[e];
89 : : }
90 : : }
91 : 358 : cbc[left] ^= 0x80;
92 : 358 : gf_mulx(pad);
93 : : }
94 : :
95 [ + + ]: 6443 : for (i = 0; i < AES_BLOCK_SIZE; i++)
96 : 6064 : pad[i] ^= cbc[i];
97 : 379 : aes_encrypt(ctx, pad, mac);
98 : 379 : aes_encrypt_deinit(ctx);
99 : 379 : 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 : 271 : int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
116 : : {
117 : 271 : return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
118 : : }
|