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

mac80111: Add BIP-GMAC-128 and BIP-GMAC-256 ciphers

This allows mac80211 to configure BIP-GMAC-128 and BIP-GMAC-256 to the
driver and also use software-implementation within mac80211 when the
driver does not support this with hardware accelaration.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Jouni Malinen and committed by
Johannes Berg
8ade538b 56c52da2

+344 -3
+5
include/net/mac80211.h
··· 4098 4098 * reverse order than in packet) 4099 4099 * @aes_cmac: PN data, most significant byte first (big endian, 4100 4100 * reverse order than in packet) 4101 + * @aes_gmac: PN data, most significant byte first (big endian, 4102 + * reverse order than in packet) 4101 4103 * @gcmp: PN data, most significant byte first (big endian, 4102 4104 * reverse order than in packet) 4103 4105 */ ··· 4115 4113 struct { 4116 4114 u8 pn[6]; 4117 4115 } aes_cmac; 4116 + struct { 4117 + u8 pn[6]; 4118 + } aes_gmac; 4118 4119 struct { 4119 4120 u8 pn[6]; 4120 4121 } gcmp;
+1
net/mac80211/Makefile
··· 17 17 aes_ccm.o \ 18 18 aes_gcm.o \ 19 19 aes_cmac.o \ 20 + aes_gmac.o \ 20 21 cfg.o \ 21 22 ethtool.o \ 22 23 rx.o \
+84
net/mac80211/aes_gmac.c
··· 1 + /* 2 + * AES-GMAC for IEEE 802.11 BIP-GMAC-128 and BIP-GMAC-256 3 + * Copyright 2015, Qualcomm Atheros, Inc. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/types.h> 12 + #include <linux/crypto.h> 13 + #include <linux/err.h> 14 + #include <crypto/aes.h> 15 + 16 + #include <net/mac80211.h> 17 + #include "key.h" 18 + #include "aes_gmac.h" 19 + 20 + #define GMAC_MIC_LEN 16 21 + #define GMAC_NONCE_LEN 12 22 + #define AAD_LEN 20 23 + 24 + int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, 25 + const u8 *data, size_t data_len, u8 *mic) 26 + { 27 + struct scatterlist sg[3], ct[1]; 28 + char aead_req_data[sizeof(struct aead_request) + 29 + crypto_aead_reqsize(tfm)] 30 + __aligned(__alignof__(struct aead_request)); 31 + struct aead_request *aead_req = (void *)aead_req_data; 32 + u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE]; 33 + 34 + if (data_len < GMAC_MIC_LEN) 35 + return -EINVAL; 36 + 37 + memset(aead_req, 0, sizeof(aead_req_data)); 38 + 39 + memset(zero, 0, GMAC_MIC_LEN); 40 + sg_init_table(sg, 3); 41 + sg_set_buf(&sg[0], aad, AAD_LEN); 42 + sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN); 43 + sg_set_buf(&sg[2], zero, GMAC_MIC_LEN); 44 + 45 + memcpy(iv, nonce, GMAC_NONCE_LEN); 46 + memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN); 47 + iv[AES_BLOCK_SIZE - 1] = 0x01; 48 + 49 + sg_init_table(ct, 1); 50 + sg_set_buf(&ct[0], mic, GMAC_MIC_LEN); 51 + 52 + aead_request_set_tfm(aead_req, tfm); 53 + aead_request_set_assoc(aead_req, sg, AAD_LEN + data_len); 54 + aead_request_set_crypt(aead_req, NULL, ct, 0, iv); 55 + 56 + crypto_aead_encrypt(aead_req); 57 + 58 + return 0; 59 + } 60 + 61 + struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], 62 + size_t key_len) 63 + { 64 + struct crypto_aead *tfm; 65 + int err; 66 + 67 + tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); 68 + if (IS_ERR(tfm)) 69 + return tfm; 70 + 71 + err = crypto_aead_setkey(tfm, key, key_len); 72 + if (!err) 73 + return tfm; 74 + if (!err) 75 + err = crypto_aead_setauthsize(tfm, GMAC_MIC_LEN); 76 + 77 + crypto_free_aead(tfm); 78 + return ERR_PTR(err); 79 + } 80 + 81 + void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) 82 + { 83 + crypto_free_aead(tfm); 84 + }
+20
net/mac80211/aes_gmac.h
··· 1 + /* 2 + * Copyright 2015, Qualcomm Atheros, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef AES_GMAC_H 10 + #define AES_GMAC_H 11 + 12 + #include <linux/crypto.h> 13 + 14 + struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], 15 + size_t key_len); 16 + int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, 17 + const u8 *data, size_t data_len, u8 *mic); 18 + void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); 19 + 20 + #endif /* AES_GMAC_H */
+14
net/mac80211/cfg.c
··· 165 165 case WLAN_CIPHER_SUITE_CCMP_256: 166 166 case WLAN_CIPHER_SUITE_AES_CMAC: 167 167 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 168 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 169 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 168 170 case WLAN_CIPHER_SUITE_GCMP: 169 171 case WLAN_CIPHER_SUITE_GCMP_256: 170 172 break; ··· 367 365 case WLAN_CIPHER_SUITE_AES_CMAC: 368 366 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 369 367 pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); 368 + seq[0] = pn64; 369 + seq[1] = pn64 >> 8; 370 + seq[2] = pn64 >> 16; 371 + seq[3] = pn64 >> 24; 372 + seq[4] = pn64 >> 32; 373 + seq[5] = pn64 >> 40; 374 + params.seq = seq; 375 + params.seq_len = 6; 376 + break; 377 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 378 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 379 + pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); 370 380 seq[0] = pn64; 371 381 seq[1] = pn64 >> 8; 372 382 seq[2] = pn64 >> 16;
+26
net/mac80211/debugfs_key.c
··· 107 107 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 108 108 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 109 109 break; 110 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 111 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 112 + pn = atomic64_read(&key->u.aes_gmac.tx_pn); 113 + len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 114 + (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 115 + (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 116 + break; 110 117 case WLAN_CIPHER_SUITE_GCMP: 111 118 case WLAN_CIPHER_SUITE_GCMP_256: 112 119 pn = atomic64_read(&key->u.gcmp.tx_pn); ··· 169 162 rpn[3], rpn[4], rpn[5]); 170 163 len = p - buf; 171 164 break; 165 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 166 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 167 + rpn = key->u.aes_gmac.rx_pn; 168 + p += scnprintf(p, sizeof(buf)+buf-p, 169 + "%02x%02x%02x%02x%02x%02x\n", 170 + rpn[0], rpn[1], rpn[2], 171 + rpn[3], rpn[4], rpn[5]); 172 + len = p - buf; 173 + break; 172 174 case WLAN_CIPHER_SUITE_GCMP: 173 175 case WLAN_CIPHER_SUITE_GCMP_256: 174 176 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { ··· 213 197 len = scnprintf(buf, sizeof(buf), "%u\n", 214 198 key->u.aes_cmac.replays); 215 199 break; 200 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 201 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 202 + len = scnprintf(buf, sizeof(buf), "%u\n", 203 + key->u.aes_gmac.replays); 204 + break; 216 205 case WLAN_CIPHER_SUITE_GCMP: 217 206 case WLAN_CIPHER_SUITE_GCMP_256: 218 207 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); ··· 241 220 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 242 221 len = scnprintf(buf, sizeof(buf), "%u\n", 243 222 key->u.aes_cmac.icverrors); 223 + break; 224 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 225 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 226 + len = scnprintf(buf, sizeof(buf), "%u\n", 227 + key->u.aes_gmac.icverrors); 244 228 break; 245 229 default: 246 230 return 0;
+60
net/mac80211/key.c
··· 24 24 #include "debugfs_key.h" 25 25 #include "aes_ccm.h" 26 26 #include "aes_cmac.h" 27 + #include "aes_gmac.h" 27 28 #include "aes_gcm.h" 28 29 29 30 ··· 167 166 case WLAN_CIPHER_SUITE_CCMP_256: 168 167 case WLAN_CIPHER_SUITE_AES_CMAC: 169 168 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 169 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 170 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 170 171 case WLAN_CIPHER_SUITE_GCMP: 171 172 case WLAN_CIPHER_SUITE_GCMP_256: 172 173 /* all of these we can do in software - if driver can */ ··· 443 440 return ERR_PTR(err); 444 441 } 445 442 break; 443 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 444 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 445 + key->conf.iv_len = 0; 446 + key->conf.icv_len = sizeof(struct ieee80211_mmie_16); 447 + if (seq) 448 + for (j = 0; j < IEEE80211_GMAC_PN_LEN; j++) 449 + key->u.aes_gmac.rx_pn[j] = 450 + seq[IEEE80211_GMAC_PN_LEN - j - 1]; 451 + /* Initialize AES key state here as an optimization so that 452 + * it does not need to be initialized for every packet. 453 + */ 454 + key->u.aes_gmac.tfm = 455 + ieee80211_aes_gmac_key_setup(key_data, key_len); 456 + if (IS_ERR(key->u.aes_gmac.tfm)) { 457 + err = PTR_ERR(key->u.aes_gmac.tfm); 458 + kfree(key); 459 + return ERR_PTR(err); 460 + } 461 + break; 446 462 case WLAN_CIPHER_SUITE_GCMP: 447 463 case WLAN_CIPHER_SUITE_GCMP_256: 448 464 key->conf.iv_len = IEEE80211_GCMP_HDR_LEN; ··· 510 488 case WLAN_CIPHER_SUITE_AES_CMAC: 511 489 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 512 490 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 491 + break; 492 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 493 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 494 + ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm); 513 495 break; 514 496 case WLAN_CIPHER_SUITE_GCMP: 515 497 case WLAN_CIPHER_SUITE_GCMP_256: ··· 845 819 seq->ccmp.pn[1] = pn64 >> 32; 846 820 seq->ccmp.pn[0] = pn64 >> 40; 847 821 break; 822 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 823 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 824 + pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); 825 + seq->ccmp.pn[5] = pn64; 826 + seq->ccmp.pn[4] = pn64 >> 8; 827 + seq->ccmp.pn[3] = pn64 >> 16; 828 + seq->ccmp.pn[2] = pn64 >> 24; 829 + seq->ccmp.pn[1] = pn64 >> 32; 830 + seq->ccmp.pn[0] = pn64 >> 40; 831 + break; 848 832 case WLAN_CIPHER_SUITE_GCMP: 849 833 case WLAN_CIPHER_SUITE_GCMP_256: 850 834 pn64 = atomic64_read(&key->u.gcmp.tx_pn); ··· 903 867 pn = key->u.aes_cmac.rx_pn; 904 868 memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); 905 869 break; 870 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 871 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 872 + if (WARN_ON(tid != 0)) 873 + return; 874 + pn = key->u.aes_gmac.rx_pn; 875 + memcpy(seq->aes_gmac.pn, pn, IEEE80211_GMAC_PN_LEN); 876 + break; 906 877 case WLAN_CIPHER_SUITE_GCMP: 907 878 case WLAN_CIPHER_SUITE_GCMP_256: 908 879 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) ··· 956 913 ((u64)seq->aes_cmac.pn[1] << 32) | 957 914 ((u64)seq->aes_cmac.pn[0] << 40); 958 915 atomic64_set(&key->u.aes_cmac.tx_pn, pn64); 916 + break; 917 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 918 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 919 + pn64 = (u64)seq->aes_gmac.pn[5] | 920 + ((u64)seq->aes_gmac.pn[4] << 8) | 921 + ((u64)seq->aes_gmac.pn[3] << 16) | 922 + ((u64)seq->aes_gmac.pn[2] << 24) | 923 + ((u64)seq->aes_gmac.pn[1] << 32) | 924 + ((u64)seq->aes_gmac.pn[0] << 40); 925 + atomic64_set(&key->u.aes_gmac.tx_pn, pn64); 959 926 break; 960 927 case WLAN_CIPHER_SUITE_GCMP: 961 928 case WLAN_CIPHER_SUITE_GCMP_256: ··· 1015 962 return; 1016 963 pn = key->u.aes_cmac.rx_pn; 1017 964 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); 965 + break; 966 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 967 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 968 + if (WARN_ON(tid != 0)) 969 + return; 970 + pn = key->u.aes_gmac.rx_pn; 971 + memcpy(pn, seq->aes_gmac.pn, IEEE80211_GMAC_PN_LEN); 1018 972 break; 1019 973 case WLAN_CIPHER_SUITE_GCMP: 1020 974 case WLAN_CIPHER_SUITE_GCMP_256:
+7
net/mac80211/key.h
··· 96 96 } aes_cmac; 97 97 struct { 98 98 atomic64_t tx_pn; 99 + u8 rx_pn[IEEE80211_GMAC_PN_LEN]; 100 + struct crypto_aead *tfm; 101 + u32 replays; /* dot11RSNAStatsCMACReplays */ 102 + u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 103 + } aes_gmac; 104 + struct { 105 + atomic64_t tx_pn; 99 106 /* Last received packet number. The first 100 107 * IEEE80211_NUM_TIDS counters are used with Data 101 108 * frames and the last counter is used with Robust
+9 -3
net/mac80211/main.c
··· 673 673 /* keep last -- depends on hw flags! */ 674 674 WLAN_CIPHER_SUITE_AES_CMAC, 675 675 WLAN_CIPHER_SUITE_BIP_CMAC_256, 676 + WLAN_CIPHER_SUITE_BIP_GMAC_128, 677 + WLAN_CIPHER_SUITE_BIP_GMAC_256, 676 678 }; 677 679 678 680 if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || ··· 713 711 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 714 712 715 713 if (!have_mfp) 716 - local->hw.wiphy->n_cipher_suites -= 2; 714 + local->hw.wiphy->n_cipher_suites -= 4; 717 715 718 716 if (!have_wep) { 719 717 local->hw.wiphy->cipher_suites += 2; ··· 739 737 if (have_wep) 740 738 n_suites += 2; 741 739 742 - /* check if we have AES_CMAC, BIP-CMAC-256 */ 740 + /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128, 741 + * BIP-GMAC-256 742 + */ 743 743 if (have_mfp) 744 - n_suites += 2; 744 + n_suites += 4; 745 745 746 746 suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); 747 747 if (!suites) ··· 763 759 if (have_mfp) { 764 760 suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; 765 761 suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; 762 + suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128; 763 + suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; 766 764 } 767 765 768 766 for (r = 0; r < local->hw.n_cipher_schemes; r++)
+4
net/mac80211/rx.c
··· 1671 1671 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1672 1672 result = ieee80211_crypto_aes_cmac_256_decrypt(rx); 1673 1673 break; 1674 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1675 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1676 + result = ieee80211_crypto_aes_gmac_decrypt(rx); 1677 + break; 1674 1678 case WLAN_CIPHER_SUITE_GCMP: 1675 1679 case WLAN_CIPHER_SUITE_GCMP_256: 1676 1680 result = ieee80211_crypto_gcmp_decrypt(rx);
+5
net/mac80211/tx.c
··· 640 640 break; 641 641 case WLAN_CIPHER_SUITE_AES_CMAC: 642 642 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 643 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 644 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 643 645 if (!ieee80211_is_mgmt(hdr->frame_control)) 644 646 tx->key = NULL; 645 647 break; ··· 1026 1024 return ieee80211_crypto_aes_cmac_encrypt(tx); 1027 1025 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1028 1026 return ieee80211_crypto_aes_cmac_256_encrypt(tx); 1027 + case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1028 + case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1029 + return ieee80211_crypto_aes_gmac_encrypt(tx); 1029 1030 case WLAN_CIPHER_SUITE_GCMP: 1030 1031 case WLAN_CIPHER_SUITE_GCMP_256: 1031 1032 return ieee80211_crypto_gcmp_encrypt(tx);
+105
net/mac80211/wpa.c
··· 22 22 #include "tkip.h" 23 23 #include "aes_ccm.h" 24 24 #include "aes_cmac.h" 25 + #include "aes_gmac.h" 25 26 #include "aes_gcm.h" 26 27 #include "wpa.h" 27 28 ··· 1092 1091 } 1093 1092 1094 1093 memcpy(key->u.aes_cmac.rx_pn, ipn, 6); 1094 + 1095 + /* Remove MMIE */ 1096 + skb_trim(skb, skb->len - sizeof(*mmie)); 1097 + 1098 + return RX_CONTINUE; 1099 + } 1100 + 1101 + ieee80211_tx_result 1102 + ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx) 1103 + { 1104 + struct sk_buff *skb; 1105 + struct ieee80211_tx_info *info; 1106 + struct ieee80211_key *key = tx->key; 1107 + struct ieee80211_mmie_16 *mmie; 1108 + struct ieee80211_hdr *hdr; 1109 + u8 aad[20]; 1110 + u64 pn64; 1111 + u8 nonce[12]; 1112 + 1113 + if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) 1114 + return TX_DROP; 1115 + 1116 + skb = skb_peek(&tx->skbs); 1117 + 1118 + info = IEEE80211_SKB_CB(skb); 1119 + 1120 + if (info->control.hw_key) 1121 + return TX_CONTINUE; 1122 + 1123 + if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) 1124 + return TX_DROP; 1125 + 1126 + mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie)); 1127 + mmie->element_id = WLAN_EID_MMIE; 1128 + mmie->length = sizeof(*mmie) - 2; 1129 + mmie->key_id = cpu_to_le16(key->conf.keyidx); 1130 + 1131 + /* PN = PN + 1 */ 1132 + pn64 = atomic64_inc_return(&key->u.aes_gmac.tx_pn); 1133 + 1134 + bip_ipn_set64(mmie->sequence_number, pn64); 1135 + 1136 + bip_aad(skb, aad); 1137 + 1138 + hdr = (struct ieee80211_hdr *)skb->data; 1139 + memcpy(nonce, hdr->addr2, ETH_ALEN); 1140 + bip_ipn_swap(nonce + ETH_ALEN, mmie->sequence_number); 1141 + 1142 + /* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */ 1143 + if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, 1144 + skb->data + 24, skb->len - 24, mmie->mic) < 0) 1145 + return TX_DROP; 1146 + 1147 + return TX_CONTINUE; 1148 + } 1149 + 1150 + ieee80211_rx_result 1151 + ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) 1152 + { 1153 + struct sk_buff *skb = rx->skb; 1154 + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 1155 + struct ieee80211_key *key = rx->key; 1156 + struct ieee80211_mmie_16 *mmie; 1157 + u8 aad[20], mic[16], ipn[6], nonce[12]; 1158 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1159 + 1160 + if (!ieee80211_is_mgmt(hdr->frame_control)) 1161 + return RX_CONTINUE; 1162 + 1163 + /* management frames are already linear */ 1164 + 1165 + if (skb->len < 24 + sizeof(*mmie)) 1166 + return RX_DROP_UNUSABLE; 1167 + 1168 + mmie = (struct ieee80211_mmie_16 *) 1169 + (skb->data + skb->len - sizeof(*mmie)); 1170 + if (mmie->element_id != WLAN_EID_MMIE || 1171 + mmie->length != sizeof(*mmie) - 2) 1172 + return RX_DROP_UNUSABLE; /* Invalid MMIE */ 1173 + 1174 + bip_ipn_swap(ipn, mmie->sequence_number); 1175 + 1176 + if (memcmp(ipn, key->u.aes_gmac.rx_pn, 6) <= 0) { 1177 + key->u.aes_gmac.replays++; 1178 + return RX_DROP_UNUSABLE; 1179 + } 1180 + 1181 + if (!(status->flag & RX_FLAG_DECRYPTED)) { 1182 + /* hardware didn't decrypt/verify MIC */ 1183 + bip_aad(skb, aad); 1184 + 1185 + memcpy(nonce, hdr->addr2, ETH_ALEN); 1186 + memcpy(nonce + ETH_ALEN, ipn, 6); 1187 + 1188 + if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, 1189 + skb->data + 24, skb->len - 24, 1190 + mic) < 0 || 1191 + memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { 1192 + key->u.aes_gmac.icverrors++; 1193 + return RX_DROP_UNUSABLE; 1194 + } 1195 + } 1196 + 1197 + memcpy(key->u.aes_gmac.rx_pn, ipn, 6); 1095 1198 1096 1199 /* Remove MMIE */ 1097 1200 skb_trim(skb, skb->len - sizeof(*mmie));
+4
net/mac80211/wpa.h
··· 39 39 ieee80211_rx_result 40 40 ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx); 41 41 ieee80211_tx_result 42 + ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx); 43 + ieee80211_rx_result 44 + ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx); 45 + ieee80211_tx_result 42 46 ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); 43 47 ieee80211_rx_result 44 48 ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);