diff options
-rw-r--r-- | net/mac80211/aes_cmac.c | 126 | ||||
-rw-r--r-- | net/mac80211/aes_cmac.h | 11 | ||||
-rw-r--r-- | net/mac80211/key.h | 2 |
3 files changed, 32 insertions, 107 deletions
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index d0bd5fff5f0a..2fb65588490c 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -22,126 +22,50 @@ | |||
22 | #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ | 22 | #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ |
23 | #define AAD_LEN 20 | 23 | #define AAD_LEN 20 |
24 | 24 | ||
25 | static const u8 zero[CMAC_TLEN_256]; | ||
25 | 26 | ||
26 | void gf_mulx(u8 *pad) | 27 | void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, |
27 | { | ||
28 | int i, carry; | ||
29 | |||
30 | carry = pad[0] & 0x80; | ||
31 | for (i = 0; i < AES_BLOCK_SIZE - 1; i++) | ||
32 | pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); | ||
33 | pad[AES_BLOCK_SIZE - 1] <<= 1; | ||
34 | if (carry) | ||
35 | pad[AES_BLOCK_SIZE - 1] ^= 0x87; | ||
36 | } | ||
37 | |||
38 | void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, | ||
39 | const u8 *addr[], const size_t *len, u8 *mac, | ||
40 | size_t mac_len) | ||
41 | { | ||
42 | u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; | ||
43 | const u8 *pos, *end; | ||
44 | size_t i, e, left, total_len; | ||
45 | |||
46 | memset(cbc, 0, AES_BLOCK_SIZE); | ||
47 | |||
48 | total_len = 0; | ||
49 | for (e = 0; e < num_elem; e++) | ||
50 | total_len += len[e]; | ||
51 | left = total_len; | ||
52 | |||
53 | e = 0; | ||
54 | pos = addr[0]; | ||
55 | end = pos + len[0]; | ||
56 | |||
57 | while (left >= AES_BLOCK_SIZE) { | ||
58 | for (i = 0; i < AES_BLOCK_SIZE; i++) { | ||
59 | cbc[i] ^= *pos++; | ||
60 | if (pos >= end) { | ||
61 | e++; | ||
62 | pos = addr[e]; | ||
63 | end = pos + len[e]; | ||
64 | } | ||
65 | } | ||
66 | if (left > AES_BLOCK_SIZE) | ||
67 | crypto_cipher_encrypt_one(tfm, cbc, cbc); | ||
68 | left -= AES_BLOCK_SIZE; | ||
69 | } | ||
70 | |||
71 | memset(pad, 0, AES_BLOCK_SIZE); | ||
72 | crypto_cipher_encrypt_one(tfm, pad, pad); | ||
73 | gf_mulx(pad); | ||
74 | |||
75 | if (left || total_len == 0) { | ||
76 | for (i = 0; i < left; i++) { | ||
77 | cbc[i] ^= *pos++; | ||
78 | if (pos >= end) { | ||
79 | e++; | ||
80 | pos = addr[e]; | ||
81 | end = pos + len[e]; | ||
82 | } | ||
83 | } | ||
84 | cbc[left] ^= 0x80; | ||
85 | gf_mulx(pad); | ||
86 | } | ||
87 | |||
88 | for (i = 0; i < AES_BLOCK_SIZE; i++) | ||
89 | pad[i] ^= cbc[i]; | ||
90 | crypto_cipher_encrypt_one(tfm, pad, pad); | ||
91 | memcpy(mac, pad, mac_len); | ||
92 | } | ||
93 | |||
94 | |||
95 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, | ||
96 | const u8 *data, size_t data_len, u8 *mic) | 28 | const u8 *data, size_t data_len, u8 *mic) |
97 | { | 29 | { |
98 | const u8 *addr[3]; | 30 | SHASH_DESC_ON_STACK(desc, tfm); |
99 | size_t len[3]; | 31 | u8 out[AES_BLOCK_SIZE]; |
100 | u8 zero[CMAC_TLEN]; | ||
101 | 32 | ||
102 | memset(zero, 0, CMAC_TLEN); | 33 | desc->tfm = tfm; |
103 | addr[0] = aad; | ||
104 | len[0] = AAD_LEN; | ||
105 | addr[1] = data; | ||
106 | len[1] = data_len - CMAC_TLEN; | ||
107 | addr[2] = zero; | ||
108 | len[2] = CMAC_TLEN; | ||
109 | 34 | ||
110 | aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); | 35 | crypto_shash_init(desc); |
36 | crypto_shash_update(desc, aad, AAD_LEN); | ||
37 | crypto_shash_update(desc, data, data_len - CMAC_TLEN); | ||
38 | crypto_shash_finup(desc, zero, CMAC_TLEN, out); | ||
39 | |||
40 | memcpy(mic, out, CMAC_TLEN); | ||
111 | } | 41 | } |
112 | 42 | ||
113 | void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, | 43 | void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, |
114 | const u8 *data, size_t data_len, u8 *mic) | 44 | const u8 *data, size_t data_len, u8 *mic) |
115 | { | 45 | { |
116 | const u8 *addr[3]; | 46 | SHASH_DESC_ON_STACK(desc, tfm); |
117 | size_t len[3]; | ||
118 | u8 zero[CMAC_TLEN_256]; | ||
119 | 47 | ||
120 | memset(zero, 0, CMAC_TLEN_256); | 48 | desc->tfm = tfm; |
121 | addr[0] = aad; | ||
122 | len[0] = AAD_LEN; | ||
123 | addr[1] = data; | ||
124 | len[1] = data_len - CMAC_TLEN_256; | ||
125 | addr[2] = zero; | ||
126 | len[2] = CMAC_TLEN_256; | ||
127 | 49 | ||
128 | aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); | 50 | crypto_shash_init(desc); |
51 | crypto_shash_update(desc, aad, AAD_LEN); | ||
52 | crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); | ||
53 | crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic); | ||
129 | } | 54 | } |
130 | 55 | ||
131 | struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], | 56 | struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], |
132 | size_t key_len) | 57 | size_t key_len) |
133 | { | 58 | { |
134 | struct crypto_cipher *tfm; | 59 | struct crypto_shash *tfm; |
135 | 60 | ||
136 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 61 | tfm = crypto_alloc_shash("cmac(aes)", 0, 0); |
137 | if (!IS_ERR(tfm)) | 62 | if (!IS_ERR(tfm)) |
138 | crypto_cipher_setkey(tfm, key, key_len); | 63 | crypto_shash_setkey(tfm, key, key_len); |
139 | 64 | ||
140 | return tfm; | 65 | return tfm; |
141 | } | 66 | } |
142 | 67 | ||
143 | 68 | void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm) | |
144 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) | ||
145 | { | 69 | { |
146 | crypto_free_cipher(tfm); | 70 | crypto_free_shash(tfm); |
147 | } | 71 | } |
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h index 3702041f44fd..fef531f42003 100644 --- a/net/mac80211/aes_cmac.h +++ b/net/mac80211/aes_cmac.h | |||
@@ -10,13 +10,14 @@ | |||
10 | #define AES_CMAC_H | 10 | #define AES_CMAC_H |
11 | 11 | ||
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | #include <crypto/hash.h> | ||
13 | 14 | ||
14 | struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], | 15 | struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], |
15 | size_t key_len); | 16 | size_t key_len); |
16 | void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, | 17 | void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, |
17 | const u8 *data, size_t data_len, u8 *mic); | 18 | const u8 *data, size_t data_len, u8 *mic); |
18 | void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, | 19 | void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, |
19 | const u8 *data, size_t data_len, u8 *mic); | 20 | const u8 *data, size_t data_len, u8 *mic); |
20 | void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); | 21 | void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm); |
21 | 22 | ||
22 | #endif /* AES_CMAC_H */ | 23 | #endif /* AES_CMAC_H */ |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 4aa20cef0859..ebdb80b85dc3 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -93,7 +93,7 @@ struct ieee80211_key { | |||
93 | } ccmp; | 93 | } ccmp; |
94 | struct { | 94 | struct { |
95 | u8 rx_pn[IEEE80211_CMAC_PN_LEN]; | 95 | u8 rx_pn[IEEE80211_CMAC_PN_LEN]; |
96 | struct crypto_cipher *tfm; | 96 | struct crypto_shash *tfm; |
97 | u32 replays; /* dot11RSNAStatsCMACReplays */ | 97 | u32 replays; /* dot11RSNAStatsCMACReplays */ |
98 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ | 98 | u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ |
99 | } aes_cmac; | 99 | } aes_cmac; |