Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: fix CMAC races

Just like TKIP and CCMP, CMAC has the PN race.
It might not actually be possible to hit it now
since there aren't multiple ACs for management
frames, but fix it anyway.

Also move scratch buffers onto the stack.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Johannes Berg and committed by
John W. Linville
75396ae6 aba83a0b

+33 -32
+4 -4
net/mac80211/aes_cmac.c
··· 35 35 } 36 36 37 37 38 - static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, 39 - size_t num_elem, 38 + static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, 40 39 const u8 *addr[], const size_t *len, u8 *mac) 41 40 { 41 + u8 scratch[2 * AES_BLOCK_SIZE]; 42 42 u8 *cbc, *pad; 43 43 const u8 *pos, *end; 44 44 size_t i, e, left, total_len; ··· 95 95 } 96 96 97 97 98 - void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, 98 + void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, 99 99 const u8 *data, size_t data_len, u8 *mic) 100 100 { 101 101 const u8 *addr[3]; ··· 110 110 addr[2] = zero; 111 111 len[2] = CMAC_TLEN; 112 112 113 - aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic); 113 + aes_128_cmac_vector(tfm, 3, addr, len, mic); 114 114 } 115 115 116 116
+1 -1
net/mac80211/aes_cmac.h
··· 12 12 #include <linux/crypto.h> 13 13 14 14 struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); 15 - void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, 15 + void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, 16 16 const u8 *data, size_t data_len, u8 *mic); 17 17 void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); 18 18
+7 -6
net/mac80211/cfg.c
··· 268 268 params.seq_len = 6; 269 269 break; 270 270 case WLAN_CIPHER_SUITE_AES_CMAC: 271 - seq[0] = key->u.aes_cmac.tx_pn[5]; 272 - seq[1] = key->u.aes_cmac.tx_pn[4]; 273 - seq[2] = key->u.aes_cmac.tx_pn[3]; 274 - seq[3] = key->u.aes_cmac.tx_pn[2]; 275 - seq[4] = key->u.aes_cmac.tx_pn[1]; 276 - seq[5] = key->u.aes_cmac.tx_pn[0]; 271 + pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); 272 + seq[0] = pn64; 273 + seq[1] = pn64 >> 8; 274 + seq[2] = pn64 >> 16; 275 + seq[3] = pn64 >> 24; 276 + seq[4] = pn64 >> 32; 277 + seq[5] = pn64 >> 40; 277 278 params.seq = seq; 278 279 params.seq_len = 6; 279 280 break;
+3 -4
net/mac80211/debugfs_key.c
··· 78 78 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 79 79 size_t count, loff_t *ppos) 80 80 { 81 - const u8 *tpn; 82 81 u64 pn; 83 82 char buf[20]; 84 83 int len; ··· 100 101 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 101 102 break; 102 103 case WLAN_CIPHER_SUITE_AES_CMAC: 103 - tpn = key->u.aes_cmac.tx_pn; 104 + pn = atomic64_read(&key->u.aes_cmac.tx_pn); 104 105 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 105 - tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], 106 - tpn[5]); 106 + (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 107 + (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 107 108 break; 108 109 default: 109 110 return 0;
+1 -4
net/mac80211/key.h
··· 97 97 #endif 98 98 } ccmp; 99 99 struct { 100 - u8 tx_pn[6]; 100 + atomic64_t tx_pn; 101 101 u8 rx_pn[6]; 102 102 struct crypto_cipher *tfm; 103 103 u32 replays; /* dot11RSNAStatsCMACReplays */ 104 104 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 105 - /* scratch buffers for virt_to_page() (crypto API) */ 106 - u8 tx_crypto_buf[2 * AES_BLOCK_LEN]; 107 - u8 rx_crypto_buf[2 * AES_BLOCK_LEN]; 108 105 } aes_cmac; 109 106 } u; 110 107
+17 -13
net/mac80211/wpa.c
··· 523 523 } 524 524 525 525 526 + static inline void bip_ipn_set64(u8 *d, u64 pn) 527 + { 528 + *d++ = pn; 529 + *d++ = pn >> 8; 530 + *d++ = pn >> 16; 531 + *d++ = pn >> 24; 532 + *d++ = pn >> 32; 533 + *d = pn >> 40; 534 + } 535 + 526 536 static inline void bip_ipn_swap(u8 *d, const u8 *s) 527 537 { 528 538 *d++ = s[5]; ··· 551 541 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 552 542 struct ieee80211_key *key = tx->key; 553 543 struct ieee80211_mmie *mmie; 554 - u8 *pn, aad[20]; 555 - int i; 544 + u8 aad[20]; 545 + u64 pn64; 556 546 557 547 if (info->control.hw_key) 558 548 return 0; ··· 566 556 mmie->key_id = cpu_to_le16(key->conf.keyidx); 567 557 568 558 /* PN = PN + 1 */ 569 - pn = key->u.aes_cmac.tx_pn; 559 + pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn); 570 560 571 - for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { 572 - pn[i]++; 573 - if (pn[i]) 574 - break; 575 - } 576 - bip_ipn_swap(mmie->sequence_number, pn); 561 + bip_ipn_set64(mmie->sequence_number, pn64); 577 562 578 563 bip_aad(skb, aad); 579 564 580 565 /* 581 566 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) 582 567 */ 583 - ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, 584 - aad, skb->data + 24, skb->len - 24, mmie->mic); 568 + ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, 569 + skb->data + 24, skb->len - 24, mmie->mic); 585 570 586 571 return TX_CONTINUE; 587 572 } ··· 614 609 if (!(status->flag & RX_FLAG_DECRYPTED)) { 615 610 /* hardware didn't decrypt/verify MIC */ 616 611 bip_aad(skb, aad); 617 - ieee80211_aes_cmac(key->u.aes_cmac.tfm, 618 - key->u.aes_cmac.rx_crypto_buf, aad, 612 + ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, 619 613 skb->data + 24, skb->len - 24, mic); 620 614 if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { 621 615 key->u.aes_cmac.icverrors++;