diff options
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_ccmp.c')
-rw-r--r-- | net/ieee80211/ieee80211_crypt_ccmp.c | 47 |
1 files changed, 16 insertions, 31 deletions
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index 11d15573b26a..8fc13f45971e 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <net/ieee80211.h> | 25 | #include <net/ieee80211.h> |
26 | 26 | ||
27 | |||
28 | #include <linux/crypto.h> | 27 | #include <linux/crypto.h> |
29 | #include <asm/scatterlist.h> | 28 | #include <asm/scatterlist.h> |
30 | 29 | ||
@@ -55,7 +54,7 @@ struct ieee80211_ccmp_data { | |||
55 | 54 | ||
56 | /* scratch buffers for virt_to_page() (crypto API) */ | 55 | /* scratch buffers for virt_to_page() (crypto API) */ |
57 | u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], | 56 | u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], |
58 | tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; | 57 | tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; |
59 | u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; | 58 | u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; |
60 | }; | 59 | }; |
61 | 60 | ||
@@ -75,7 +74,7 @@ static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, | |||
75 | crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN); | 74 | crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN); |
76 | } | 75 | } |
77 | 76 | ||
78 | static void * ieee80211_ccmp_init(int key_idx) | 77 | static void *ieee80211_ccmp_init(int key_idx) |
79 | { | 78 | { |
80 | struct ieee80211_ccmp_data *priv; | 79 | struct ieee80211_ccmp_data *priv; |
81 | 80 | ||
@@ -94,7 +93,7 @@ static void * ieee80211_ccmp_init(int key_idx) | |||
94 | 93 | ||
95 | return priv; | 94 | return priv; |
96 | 95 | ||
97 | fail: | 96 | fail: |
98 | if (priv) { | 97 | if (priv) { |
99 | if (priv->tfm) | 98 | if (priv->tfm) |
100 | crypto_free_tfm(priv->tfm); | 99 | crypto_free_tfm(priv->tfm); |
@@ -104,7 +103,6 @@ fail: | |||
104 | return NULL; | 103 | return NULL; |
105 | } | 104 | } |
106 | 105 | ||
107 | |||
108 | static void ieee80211_ccmp_deinit(void *priv) | 106 | static void ieee80211_ccmp_deinit(void *priv) |
109 | { | 107 | { |
110 | struct ieee80211_ccmp_data *_priv = priv; | 108 | struct ieee80211_ccmp_data *_priv = priv; |
@@ -113,19 +111,16 @@ static void ieee80211_ccmp_deinit(void *priv) | |||
113 | kfree(priv); | 111 | kfree(priv); |
114 | } | 112 | } |
115 | 113 | ||
116 | 114 | static inline void xor_block(u8 * b, u8 * a, size_t len) | |
117 | static inline void xor_block(u8 *b, u8 *a, size_t len) | ||
118 | { | 115 | { |
119 | int i; | 116 | int i; |
120 | for (i = 0; i < len; i++) | 117 | for (i = 0; i < len; i++) |
121 | b[i] ^= a[i]; | 118 | b[i] ^= a[i]; |
122 | } | 119 | } |
123 | 120 | ||
124 | |||
125 | static void ccmp_init_blocks(struct crypto_tfm *tfm, | 121 | static void ccmp_init_blocks(struct crypto_tfm *tfm, |
126 | struct ieee80211_hdr *hdr, | 122 | struct ieee80211_hdr *hdr, |
127 | u8 *pn, size_t dlen, u8 *b0, u8 *auth, | 123 | u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) |
128 | u8 *s0) | ||
129 | { | 124 | { |
130 | u8 *pos, qc = 0; | 125 | u8 *pos, qc = 0; |
131 | size_t aad_len; | 126 | size_t aad_len; |
@@ -142,7 +137,7 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, | |||
142 | if (a4_included) | 137 | if (a4_included) |
143 | aad_len += 6; | 138 | aad_len += 6; |
144 | if (qc_included) { | 139 | if (qc_included) { |
145 | pos = (u8 *) &hdr->addr4; | 140 | pos = (u8 *) & hdr->addr4; |
146 | if (a4_included) | 141 | if (a4_included) |
147 | pos += 6; | 142 | pos += 6; |
148 | qc = *pos & 0x0f; | 143 | qc = *pos & 0x0f; |
@@ -169,14 +164,14 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, | |||
169 | * QC (if present) | 164 | * QC (if present) |
170 | */ | 165 | */ |
171 | pos = (u8 *) hdr; | 166 | pos = (u8 *) hdr; |
172 | aad[0] = 0; /* aad_len >> 8 */ | 167 | aad[0] = 0; /* aad_len >> 8 */ |
173 | aad[1] = aad_len & 0xff; | 168 | aad[1] = aad_len & 0xff; |
174 | aad[2] = pos[0] & 0x8f; | 169 | aad[2] = pos[0] & 0x8f; |
175 | aad[3] = pos[1] & 0xc7; | 170 | aad[3] = pos[1] & 0xc7; |
176 | memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); | 171 | memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); |
177 | pos = (u8 *) &hdr->seq_ctl; | 172 | pos = (u8 *) & hdr->seq_ctl; |
178 | aad[22] = pos[0] & 0x0f; | 173 | aad[22] = pos[0] & 0x0f; |
179 | aad[23] = 0; /* all bits masked */ | 174 | aad[23] = 0; /* all bits masked */ |
180 | memset(aad + 24, 0, 8); | 175 | memset(aad + 24, 0, 8); |
181 | if (a4_included) | 176 | if (a4_included) |
182 | memcpy(aad + 24, hdr->addr4, ETH_ALEN); | 177 | memcpy(aad + 24, hdr->addr4, ETH_ALEN); |
@@ -196,7 +191,6 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, | |||
196 | ieee80211_ccmp_aes_encrypt(tfm, b0, s0); | 191 | ieee80211_ccmp_aes_encrypt(tfm, b0, s0); |
197 | } | 192 | } |
198 | 193 | ||
199 | |||
200 | static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | 194 | static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) |
201 | { | 195 | { |
202 | struct ieee80211_ccmp_data *key = priv; | 196 | struct ieee80211_ccmp_data *key = priv; |
@@ -209,8 +203,7 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
209 | u8 *s0 = key->tx_s0; | 203 | u8 *s0 = key->tx_s0; |
210 | 204 | ||
211 | if (skb_headroom(skb) < CCMP_HDR_LEN || | 205 | if (skb_headroom(skb) < CCMP_HDR_LEN || |
212 | skb_tailroom(skb) < CCMP_MIC_LEN || | 206 | skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len) |
213 | skb->len < hdr_len) | ||
214 | return -1; | 207 | return -1; |
215 | 208 | ||
216 | data_len = skb->len - hdr_len; | 209 | data_len = skb->len - hdr_len; |
@@ -230,13 +223,13 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
230 | *pos++ = key->tx_pn[5]; | 223 | *pos++ = key->tx_pn[5]; |
231 | *pos++ = key->tx_pn[4]; | 224 | *pos++ = key->tx_pn[4]; |
232 | *pos++ = 0; | 225 | *pos++ = 0; |
233 | *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; | 226 | *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */ ; |
234 | *pos++ = key->tx_pn[3]; | 227 | *pos++ = key->tx_pn[3]; |
235 | *pos++ = key->tx_pn[2]; | 228 | *pos++ = key->tx_pn[2]; |
236 | *pos++ = key->tx_pn[1]; | 229 | *pos++ = key->tx_pn[1]; |
237 | *pos++ = key->tx_pn[0]; | 230 | *pos++ = key->tx_pn[0]; |
238 | 231 | ||
239 | hdr = (struct ieee80211_hdr *) skb->data; | 232 | hdr = (struct ieee80211_hdr *)skb->data; |
240 | ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); | 233 | ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); |
241 | 234 | ||
242 | blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; | 235 | blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; |
@@ -261,7 +254,6 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
261 | return 0; | 254 | return 0; |
262 | } | 255 | } |
263 | 256 | ||
264 | |||
265 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 257 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
266 | { | 258 | { |
267 | struct ieee80211_ccmp_data *key = priv; | 259 | struct ieee80211_ccmp_data *key = priv; |
@@ -280,7 +272,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
280 | return -1; | 272 | return -1; |
281 | } | 273 | } |
282 | 274 | ||
283 | hdr = (struct ieee80211_hdr *) skb->data; | 275 | hdr = (struct ieee80211_hdr *)skb->data; |
284 | pos = skb->data + hdr_len; | 276 | pos = skb->data + hdr_len; |
285 | keyidx = pos[3]; | 277 | keyidx = pos[3]; |
286 | if (!(keyidx & (1 << 5))) { | 278 | if (!(keyidx & (1 << 5))) { |
@@ -364,8 +356,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
364 | return keyidx; | 356 | return keyidx; |
365 | } | 357 | } |
366 | 358 | ||
367 | 359 | static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) | |
368 | static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) | ||
369 | { | 360 | { |
370 | struct ieee80211_ccmp_data *data = priv; | 361 | struct ieee80211_ccmp_data *data = priv; |
371 | int keyidx; | 362 | int keyidx; |
@@ -395,8 +386,7 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) | |||
395 | return 0; | 386 | return 0; |
396 | } | 387 | } |
397 | 388 | ||
398 | 389 | static int ieee80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv) | |
399 | static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) | ||
400 | { | 390 | { |
401 | struct ieee80211_ccmp_data *data = priv; | 391 | struct ieee80211_ccmp_data *data = priv; |
402 | 392 | ||
@@ -419,8 +409,7 @@ static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) | |||
419 | return CCMP_TK_LEN; | 409 | return CCMP_TK_LEN; |
420 | } | 410 | } |
421 | 411 | ||
422 | 412 | static char *ieee80211_ccmp_print_stats(char *p, void *priv) | |
423 | static char * ieee80211_ccmp_print_stats(char *p, void *priv) | ||
424 | { | 413 | { |
425 | struct ieee80211_ccmp_data *ccmp = priv; | 414 | struct ieee80211_ccmp_data *ccmp = priv; |
426 | p += sprintf(p, "key[%d] alg=CCMP key_set=%d " | 415 | p += sprintf(p, "key[%d] alg=CCMP key_set=%d " |
@@ -436,7 +425,6 @@ static char * ieee80211_ccmp_print_stats(char *p, void *priv) | |||
436 | return p; | 425 | return p; |
437 | } | 426 | } |
438 | 427 | ||
439 | |||
440 | static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { | 428 | static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { |
441 | .name = "CCMP", | 429 | .name = "CCMP", |
442 | .init = ieee80211_ccmp_init, | 430 | .init = ieee80211_ccmp_init, |
@@ -453,18 +441,15 @@ static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { | |||
453 | .owner = THIS_MODULE, | 441 | .owner = THIS_MODULE, |
454 | }; | 442 | }; |
455 | 443 | ||
456 | |||
457 | static int __init ieee80211_crypto_ccmp_init(void) | 444 | static int __init ieee80211_crypto_ccmp_init(void) |
458 | { | 445 | { |
459 | return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); | 446 | return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); |
460 | } | 447 | } |
461 | 448 | ||
462 | |||
463 | static void __exit ieee80211_crypto_ccmp_exit(void) | 449 | static void __exit ieee80211_crypto_ccmp_exit(void) |
464 | { | 450 | { |
465 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); | 451 | ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); |
466 | } | 452 | } |
467 | 453 | ||
468 | |||
469 | module_init(ieee80211_crypto_ccmp_init); | 454 | module_init(ieee80211_crypto_ccmp_init); |
470 | module_exit(ieee80211_crypto_ccmp_exit); | 455 | module_exit(ieee80211_crypto_ccmp_exit); |