diff options
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_ccmp.c')
| -rw-r--r-- | net/ieee80211/ieee80211_crypt_ccmp.c | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index 78b2d13e80e3..35aa3426c3fa 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | * more details. | 9 | * more details. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/config.h> | 12 | #include <linux/err.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| @@ -49,7 +49,7 @@ struct ieee80211_ccmp_data { | |||
| 49 | 49 | ||
| 50 | int key_idx; | 50 | int key_idx; |
| 51 | 51 | ||
| 52 | struct crypto_tfm *tfm; | 52 | struct crypto_cipher *tfm; |
| 53 | 53 | ||
| 54 | /* scratch buffers for virt_to_page() (crypto API) */ | 54 | /* scratch buffers for virt_to_page() (crypto API) */ |
| 55 | u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], | 55 | u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], |
| @@ -57,36 +57,26 @@ struct ieee80211_ccmp_data { | |||
| 57 | u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; | 57 | u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, | 60 | static inline void ieee80211_ccmp_aes_encrypt(struct crypto_cipher *tfm, |
| 61 | const u8 pt[16], u8 ct[16]) | 61 | const u8 pt[16], u8 ct[16]) |
| 62 | { | 62 | { |
| 63 | struct scatterlist src, dst; | 63 | crypto_cipher_encrypt_one(tfm, ct, pt); |
| 64 | |||
| 65 | src.page = virt_to_page(pt); | ||
| 66 | src.offset = offset_in_page(pt); | ||
| 67 | src.length = AES_BLOCK_LEN; | ||
| 68 | |||
| 69 | dst.page = virt_to_page(ct); | ||
| 70 | dst.offset = offset_in_page(ct); | ||
| 71 | dst.length = AES_BLOCK_LEN; | ||
| 72 | |||
| 73 | crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN); | ||
| 74 | } | 64 | } |
| 75 | 65 | ||
| 76 | static void *ieee80211_ccmp_init(int key_idx) | 66 | static void *ieee80211_ccmp_init(int key_idx) |
| 77 | { | 67 | { |
| 78 | struct ieee80211_ccmp_data *priv; | 68 | struct ieee80211_ccmp_data *priv; |
| 79 | 69 | ||
| 80 | priv = kmalloc(sizeof(*priv), GFP_ATOMIC); | 70 | priv = kzalloc(sizeof(*priv), GFP_ATOMIC); |
| 81 | if (priv == NULL) | 71 | if (priv == NULL) |
| 82 | goto fail; | 72 | goto fail; |
| 83 | memset(priv, 0, sizeof(*priv)); | ||
| 84 | priv->key_idx = key_idx; | 73 | priv->key_idx = key_idx; |
| 85 | 74 | ||
| 86 | priv->tfm = crypto_alloc_tfm("aes", 0); | 75 | priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
| 87 | if (priv->tfm == NULL) { | 76 | if (IS_ERR(priv->tfm)) { |
| 88 | printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " | 77 | printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " |
| 89 | "crypto API aes\n"); | 78 | "crypto API aes\n"); |
| 79 | priv->tfm = NULL; | ||
| 90 | goto fail; | 80 | goto fail; |
| 91 | } | 81 | } |
| 92 | 82 | ||
| @@ -95,7 +85,7 @@ static void *ieee80211_ccmp_init(int key_idx) | |||
| 95 | fail: | 85 | fail: |
| 96 | if (priv) { | 86 | if (priv) { |
| 97 | if (priv->tfm) | 87 | if (priv->tfm) |
| 98 | crypto_free_tfm(priv->tfm); | 88 | crypto_free_cipher(priv->tfm); |
| 99 | kfree(priv); | 89 | kfree(priv); |
| 100 | } | 90 | } |
| 101 | 91 | ||
| @@ -106,7 +96,7 @@ static void ieee80211_ccmp_deinit(void *priv) | |||
| 106 | { | 96 | { |
| 107 | struct ieee80211_ccmp_data *_priv = priv; | 97 | struct ieee80211_ccmp_data *_priv = priv; |
| 108 | if (_priv && _priv->tfm) | 98 | if (_priv && _priv->tfm) |
| 109 | crypto_free_tfm(_priv->tfm); | 99 | crypto_free_cipher(_priv->tfm); |
| 110 | kfree(priv); | 100 | kfree(priv); |
| 111 | } | 101 | } |
| 112 | 102 | ||
| @@ -117,7 +107,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len) | |||
| 117 | b[i] ^= a[i]; | 107 | b[i] ^= a[i]; |
| 118 | } | 108 | } |
| 119 | 109 | ||
| 120 | static void ccmp_init_blocks(struct crypto_tfm *tfm, | 110 | static void ccmp_init_blocks(struct crypto_cipher *tfm, |
| 121 | struct ieee80211_hdr_4addr *hdr, | 111 | struct ieee80211_hdr_4addr *hdr, |
| 122 | u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) | 112 | u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) |
| 123 | { | 113 | { |
| @@ -273,6 +263,27 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
| 273 | return 0; | 263 | return 0; |
| 274 | } | 264 | } |
| 275 | 265 | ||
| 266 | /* | ||
| 267 | * deal with seq counter wrapping correctly. | ||
| 268 | * refer to timer_after() for jiffies wrapping handling | ||
| 269 | */ | ||
| 270 | static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o) | ||
| 271 | { | ||
| 272 | u32 iv32_n, iv16_n; | ||
| 273 | u32 iv32_o, iv16_o; | ||
| 274 | |||
| 275 | iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3]; | ||
| 276 | iv16_n = (pn_n[4] << 8) | pn_n[5]; | ||
| 277 | |||
| 278 | iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3]; | ||
| 279 | iv16_o = (pn_o[4] << 8) | pn_o[5]; | ||
| 280 | |||
| 281 | if ((s32)iv32_n - (s32)iv32_o < 0 || | ||
| 282 | (iv32_n == iv32_o && iv16_n <= iv16_o)) | ||
| 283 | return 1; | ||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 276 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | 287 | static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) |
| 277 | { | 288 | { |
| 278 | struct ieee80211_ccmp_data *key = priv; | 289 | struct ieee80211_ccmp_data *key = priv; |
| @@ -325,7 +336,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) | |||
| 325 | pn[5] = pos[0]; | 336 | pn[5] = pos[0]; |
| 326 | pos += 8; | 337 | pos += 8; |
| 327 | 338 | ||
| 328 | if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { | 339 | if (ccmp_replay_check(pn, key->rx_pn)) { |
| 329 | if (net_ratelimit()) { | 340 | if (net_ratelimit()) { |
| 330 | printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT | 341 | printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT |
| 331 | " previous PN %02x%02x%02x%02x%02x%02x " | 342 | " previous PN %02x%02x%02x%02x%02x%02x " |
| @@ -379,7 +390,7 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) | |||
| 379 | { | 390 | { |
| 380 | struct ieee80211_ccmp_data *data = priv; | 391 | struct ieee80211_ccmp_data *data = priv; |
| 381 | int keyidx; | 392 | int keyidx; |
| 382 | struct crypto_tfm *tfm = data->tfm; | 393 | struct crypto_cipher *tfm = data->tfm; |
| 383 | 394 | ||
| 384 | keyidx = data->key_idx; | 395 | keyidx = data->key_idx; |
| 385 | memset(data, 0, sizeof(*data)); | 396 | memset(data, 0, sizeof(*data)); |
