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

mac80111: Add GCMP and GCMP-256 ciphers

This allows mac80211 to configure GCMP and GCMP-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>
[remove a spurious newline]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Jouni Malinen and committed by
Johannes Berg
00b9cfa3 cfcf1682

+492 -9
+10 -5
include/net/mac80211.h
··· 1294 1294 * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates 1295 1295 * that the key is pairwise rather then a shared key. 1296 1296 * @IEEE80211_KEY_FLAG_SW_MGMT_TX: This flag should be set by the driver for a 1297 - * CCMP key if it requires CCMP encryption of management frames (MFP) to 1298 - * be done in software. 1297 + * CCMP/GCMP key if it requires CCMP/GCMP encryption of management frames 1298 + * (MFP) to be done in software. 1299 1299 * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver 1300 1300 * if space should be prepared for the IV, but the IV 1301 1301 * itself should not be generated. Do not set together with ··· 1310 1310 * RX, if your crypto engine can't deal with TX you can also set the 1311 1311 * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. 1312 1312 * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the 1313 - * driver for a CCMP key to indicate that is requires IV generation 1313 + * driver for a CCMP/GCMP key to indicate that is requires IV generation 1314 1314 * only for managment frames (MFP). 1315 1315 * @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the 1316 1316 * driver for a key to indicate that sufficient tailroom must always ··· 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 + * @gcmp: PN data, most significant byte first (big endian, 4102 + * reverse order than in packet) 4101 4103 */ 4102 4104 struct ieee80211_key_seq { 4103 4105 union { ··· 4113 4111 struct { 4114 4112 u8 pn[6]; 4115 4113 } aes_cmac; 4114 + struct { 4115 + u8 pn[6]; 4116 + } gcmp; 4116 4117 }; 4117 4118 }; 4118 4119 ··· 4140 4135 * ieee80211_get_key_rx_seq - get key RX sequence counter 4141 4136 * 4142 4137 * @keyconf: the parameter passed with the set key 4143 - * @tid: The TID, or -1 for the management frame value (CCMP only); 4138 + * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only); 4144 4139 * the value on TID 0 is also used for non-QoS frames. For 4145 4140 * CMAC, only TID 0 is valid. 4146 4141 * @seq: buffer to receive the sequence data ··· 4176 4171 * ieee80211_set_key_rx_seq - set key RX sequence counter 4177 4172 * 4178 4173 * @keyconf: the parameter passed with the set key 4179 - * @tid: The TID, or -1 for the management frame value (CCMP only); 4174 + * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only); 4180 4175 * the value on TID 0 is also used for non-QoS frames. For 4181 4176 * CMAC, only TID 0 is valid. 4182 4177 * @seq: new sequence data
+1
net/mac80211/Kconfig
··· 5 5 select CRYPTO_ARC4 6 6 select CRYPTO_AES 7 7 select CRYPTO_CCM 8 + select CRYPTO_GCM 8 9 select CRC32 9 10 select AVERAGE 10 11 ---help---
+1
net/mac80211/Makefile
··· 15 15 michael.o \ 16 16 tkip.o \ 17 17 aes_ccm.o \ 18 + aes_gcm.o \ 18 19 aes_cmac.o \ 19 20 cfg.o \ 20 21 ethtool.o \
+95
net/mac80211/aes_gcm.c
··· 1 + /* 2 + * Copyright 2014-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 + #include <linux/kernel.h> 10 + #include <linux/types.h> 11 + #include <linux/crypto.h> 12 + #include <linux/err.h> 13 + #include <crypto/aes.h> 14 + 15 + #include <net/mac80211.h> 16 + #include "key.h" 17 + #include "aes_gcm.h" 18 + 19 + void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 20 + u8 *data, size_t data_len, u8 *mic) 21 + { 22 + struct scatterlist assoc, pt, ct[2]; 23 + 24 + char aead_req_data[sizeof(struct aead_request) + 25 + crypto_aead_reqsize(tfm)] 26 + __aligned(__alignof__(struct aead_request)); 27 + struct aead_request *aead_req = (void *)aead_req_data; 28 + 29 + memset(aead_req, 0, sizeof(aead_req_data)); 30 + 31 + sg_init_one(&pt, data, data_len); 32 + sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 33 + sg_init_table(ct, 2); 34 + sg_set_buf(&ct[0], data, data_len); 35 + sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN); 36 + 37 + aead_request_set_tfm(aead_req, tfm); 38 + aead_request_set_assoc(aead_req, &assoc, assoc.length); 39 + aead_request_set_crypt(aead_req, &pt, ct, data_len, j_0); 40 + 41 + crypto_aead_encrypt(aead_req); 42 + } 43 + 44 + int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 45 + u8 *data, size_t data_len, u8 *mic) 46 + { 47 + struct scatterlist assoc, pt, ct[2]; 48 + char aead_req_data[sizeof(struct aead_request) + 49 + crypto_aead_reqsize(tfm)] 50 + __aligned(__alignof__(struct aead_request)); 51 + struct aead_request *aead_req = (void *)aead_req_data; 52 + 53 + if (data_len == 0) 54 + return -EINVAL; 55 + 56 + memset(aead_req, 0, sizeof(aead_req_data)); 57 + 58 + sg_init_one(&pt, data, data_len); 59 + sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 60 + sg_init_table(ct, 2); 61 + sg_set_buf(&ct[0], data, data_len); 62 + sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN); 63 + 64 + aead_request_set_tfm(aead_req, tfm); 65 + aead_request_set_assoc(aead_req, &assoc, assoc.length); 66 + aead_request_set_crypt(aead_req, ct, &pt, 67 + data_len + IEEE80211_GCMP_MIC_LEN, j_0); 68 + 69 + return crypto_aead_decrypt(aead_req); 70 + } 71 + 72 + struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], 73 + size_t key_len) 74 + { 75 + struct crypto_aead *tfm; 76 + int err; 77 + 78 + tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); 79 + if (IS_ERR(tfm)) 80 + return tfm; 81 + 82 + err = crypto_aead_setkey(tfm, key, key_len); 83 + if (!err) 84 + err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN); 85 + if (!err) 86 + return tfm; 87 + 88 + crypto_free_aead(tfm); 89 + return ERR_PTR(err); 90 + } 91 + 92 + void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) 93 + { 94 + crypto_free_aead(tfm); 95 + }
+22
net/mac80211/aes_gcm.h
··· 1 + /* 2 + * Copyright 2014-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_GCM_H 10 + #define AES_GCM_H 11 + 12 + #include <linux/crypto.h> 13 + 14 + void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 15 + u8 *data, size_t data_len, u8 *mic); 16 + int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, 17 + u8 *data, size_t data_len, u8 *mic); 18 + struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], 19 + size_t key_len); 20 + void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); 21 + 22 + #endif /* AES_GCM_H */
+13
net/mac80211/cfg.c
··· 164 164 case WLAN_CIPHER_SUITE_CCMP: 165 165 case WLAN_CIPHER_SUITE_AES_CMAC: 166 166 case WLAN_CIPHER_SUITE_GCMP: 167 + case WLAN_CIPHER_SUITE_GCMP_256: 167 168 break; 168 169 default: 169 170 cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type); ··· 361 360 break; 362 361 case WLAN_CIPHER_SUITE_AES_CMAC: 363 362 pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); 363 + seq[0] = pn64; 364 + seq[1] = pn64 >> 8; 365 + seq[2] = pn64 >> 16; 366 + seq[3] = pn64 >> 24; 367 + seq[4] = pn64 >> 32; 368 + seq[5] = pn64 >> 40; 369 + params.seq = seq; 370 + params.seq_len = 6; 371 + break; 372 + case WLAN_CIPHER_SUITE_GCMP: 373 + case WLAN_CIPHER_SUITE_GCMP_256: 374 + pn64 = atomic64_read(&key->u.gcmp.tx_pn); 364 375 seq[0] = pn64; 365 376 seq[1] = pn64 >> 8; 366 377 seq[2] = pn64 >> 16;
+22
net/mac80211/debugfs_key.c
··· 105 105 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 106 106 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 107 107 break; 108 + case WLAN_CIPHER_SUITE_GCMP: 109 + case WLAN_CIPHER_SUITE_GCMP_256: 110 + pn = atomic64_read(&key->u.gcmp.tx_pn); 111 + len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 112 + (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 113 + (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 114 + break; 108 115 default: 109 116 return 0; 110 117 } ··· 158 151 rpn[3], rpn[4], rpn[5]); 159 152 len = p - buf; 160 153 break; 154 + case WLAN_CIPHER_SUITE_GCMP: 155 + case WLAN_CIPHER_SUITE_GCMP_256: 156 + for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 157 + rpn = key->u.gcmp.rx_pn[i]; 158 + p += scnprintf(p, sizeof(buf)+buf-p, 159 + "%02x%02x%02x%02x%02x%02x\n", 160 + rpn[0], rpn[1], rpn[2], 161 + rpn[3], rpn[4], rpn[5]); 162 + } 163 + len = p - buf; 164 + break; 161 165 default: 162 166 return 0; 163 167 } ··· 190 172 case WLAN_CIPHER_SUITE_AES_CMAC: 191 173 len = scnprintf(buf, sizeof(buf), "%u\n", 192 174 key->u.aes_cmac.replays); 175 + break; 176 + case WLAN_CIPHER_SUITE_GCMP: 177 + case WLAN_CIPHER_SUITE_GCMP_256: 178 + len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); 193 179 break; 194 180 default: 195 181 return 0;
+72 -2
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_gcm.h" 27 28 28 29 29 30 /** ··· 164 163 case WLAN_CIPHER_SUITE_TKIP: 165 164 case WLAN_CIPHER_SUITE_CCMP: 166 165 case WLAN_CIPHER_SUITE_AES_CMAC: 166 + case WLAN_CIPHER_SUITE_GCMP: 167 + case WLAN_CIPHER_SUITE_GCMP_256: 167 168 /* all of these we can do in software - if driver can */ 168 169 if (ret == 1) 169 170 return 0; ··· 415 412 return ERR_PTR(err); 416 413 } 417 414 break; 415 + case WLAN_CIPHER_SUITE_GCMP: 416 + case WLAN_CIPHER_SUITE_GCMP_256: 417 + key->conf.iv_len = IEEE80211_GCMP_HDR_LEN; 418 + key->conf.icv_len = IEEE80211_GCMP_MIC_LEN; 419 + for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++) 420 + for (j = 0; j < IEEE80211_GCMP_PN_LEN; j++) 421 + key->u.gcmp.rx_pn[i][j] = 422 + seq[IEEE80211_GCMP_PN_LEN - j - 1]; 423 + /* Initialize AES key state here as an optimization so that 424 + * it does not need to be initialized for every packet. 425 + */ 426 + key->u.gcmp.tfm = ieee80211_aes_gcm_key_setup_encrypt(key_data, 427 + key_len); 428 + if (IS_ERR(key->u.gcmp.tfm)) { 429 + err = PTR_ERR(key->u.gcmp.tfm); 430 + kfree(key); 431 + return ERR_PTR(err); 432 + } 433 + break; 418 434 default: 419 435 if (cs) { 420 436 size_t len = (seq_len > MAX_PN_LEN) ? ··· 455 433 456 434 static void ieee80211_key_free_common(struct ieee80211_key *key) 457 435 { 458 - if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) 436 + switch (key->conf.cipher) { 437 + case WLAN_CIPHER_SUITE_CCMP: 459 438 ieee80211_aes_key_free(key->u.ccmp.tfm); 460 - if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 439 + break; 440 + case WLAN_CIPHER_SUITE_AES_CMAC: 461 441 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 442 + break; 443 + case WLAN_CIPHER_SUITE_GCMP: 444 + case WLAN_CIPHER_SUITE_GCMP_256: 445 + ieee80211_aes_gcm_key_free(key->u.gcmp.tfm); 446 + break; 447 + } 462 448 kzfree(key); 463 449 } 464 450 ··· 790 760 seq->ccmp.pn[1] = pn64 >> 32; 791 761 seq->ccmp.pn[0] = pn64 >> 40; 792 762 break; 763 + case WLAN_CIPHER_SUITE_GCMP: 764 + case WLAN_CIPHER_SUITE_GCMP_256: 765 + pn64 = atomic64_read(&key->u.gcmp.tx_pn); 766 + seq->gcmp.pn[5] = pn64; 767 + seq->gcmp.pn[4] = pn64 >> 8; 768 + seq->gcmp.pn[3] = pn64 >> 16; 769 + seq->gcmp.pn[2] = pn64 >> 24; 770 + seq->gcmp.pn[1] = pn64 >> 32; 771 + seq->gcmp.pn[0] = pn64 >> 40; 772 + break; 793 773 default: 794 774 WARN_ON(1); 795 775 } ··· 836 796 pn = key->u.aes_cmac.rx_pn; 837 797 memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); 838 798 break; 799 + case WLAN_CIPHER_SUITE_GCMP: 800 + case WLAN_CIPHER_SUITE_GCMP_256: 801 + if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 802 + return; 803 + if (tid < 0) 804 + pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS]; 805 + else 806 + pn = key->u.gcmp.rx_pn[tid]; 807 + memcpy(seq->gcmp.pn, pn, IEEE80211_GCMP_PN_LEN); 808 + break; 839 809 } 840 810 } 841 811 EXPORT_SYMBOL(ieee80211_get_key_rx_seq); ··· 880 830 ((u64)seq->aes_cmac.pn[1] << 32) | 881 831 ((u64)seq->aes_cmac.pn[0] << 40); 882 832 atomic64_set(&key->u.aes_cmac.tx_pn, pn64); 833 + break; 834 + case WLAN_CIPHER_SUITE_GCMP: 835 + case WLAN_CIPHER_SUITE_GCMP_256: 836 + pn64 = (u64)seq->gcmp.pn[5] | 837 + ((u64)seq->gcmp.pn[4] << 8) | 838 + ((u64)seq->gcmp.pn[3] << 16) | 839 + ((u64)seq->gcmp.pn[2] << 24) | 840 + ((u64)seq->gcmp.pn[1] << 32) | 841 + ((u64)seq->gcmp.pn[0] << 40); 842 + atomic64_set(&key->u.gcmp.tx_pn, pn64); 883 843 break; 884 844 default: 885 845 WARN_ON(1); ··· 927 867 return; 928 868 pn = key->u.aes_cmac.rx_pn; 929 869 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); 870 + break; 871 + case WLAN_CIPHER_SUITE_GCMP: 872 + case WLAN_CIPHER_SUITE_GCMP_256: 873 + if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 874 + return; 875 + if (tid < 0) 876 + pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS]; 877 + else 878 + pn = key->u.gcmp.rx_pn[tid]; 879 + memcpy(pn, seq->gcmp.pn, IEEE80211_GCMP_PN_LEN); 930 880 break; 931 881 default: 932 882 WARN_ON(1);
+11
net/mac80211/key.h
··· 95 95 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 96 96 } aes_cmac; 97 97 struct { 98 + atomic64_t tx_pn; 99 + /* Last received packet number. The first 100 + * IEEE80211_NUM_TIDS counters are used with Data 101 + * frames and the last counter is used with Robust 102 + * Management frames. 103 + */ 104 + u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_GCMP_PN_LEN]; 105 + struct crypto_aead *tfm; 106 + u32 replays; /* dot11RSNAStatsGCMPReplays */ 107 + } gcmp; 108 + struct { 98 109 /* generic cipher scheme */ 99 110 u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN]; 100 111 } gen;
+7 -2
net/mac80211/main.c
··· 666 666 WLAN_CIPHER_SUITE_WEP104, 667 667 WLAN_CIPHER_SUITE_TKIP, 668 668 WLAN_CIPHER_SUITE_CCMP, 669 + WLAN_CIPHER_SUITE_GCMP, 670 + WLAN_CIPHER_SUITE_GCMP_256, 669 671 670 672 /* keep last -- depends on hw flags! */ 671 673 WLAN_CIPHER_SUITE_AES_CMAC ··· 726 724 /* Driver specifies cipher schemes only (but not cipher suites 727 725 * including the schemes) 728 726 * 729 - * We start counting ciphers defined by schemes, TKIP and CCMP 727 + * We start counting ciphers defined by schemes, TKIP, CCMP, 728 + * GCMP, and GCMP-256 730 729 */ 731 - n_suites = local->hw.n_cipher_schemes + 2; 730 + n_suites = local->hw.n_cipher_schemes + 4; 732 731 733 732 /* check if we have WEP40 and WEP104 */ 734 733 if (have_wep) ··· 745 742 746 743 suites[w++] = WLAN_CIPHER_SUITE_CCMP; 747 744 suites[w++] = WLAN_CIPHER_SUITE_TKIP; 745 + suites[w++] = WLAN_CIPHER_SUITE_GCMP; 746 + suites[w++] = WLAN_CIPHER_SUITE_GCMP_256; 748 747 749 748 if (have_wep) { 750 749 suites[w++] = WLAN_CIPHER_SUITE_WEP40;
+4
net/mac80211/rx.c
··· 1655 1655 case WLAN_CIPHER_SUITE_AES_CMAC: 1656 1656 result = ieee80211_crypto_aes_cmac_decrypt(rx); 1657 1657 break; 1658 + case WLAN_CIPHER_SUITE_GCMP: 1659 + case WLAN_CIPHER_SUITE_GCMP_256: 1660 + result = ieee80211_crypto_gcmp_decrypt(rx); 1661 + break; 1658 1662 default: 1659 1663 result = ieee80211_crypto_hw_decrypt(rx); 1660 1664 }
+5
net/mac80211/tx.c
··· 626 626 tx->key = NULL; 627 627 break; 628 628 case WLAN_CIPHER_SUITE_CCMP: 629 + case WLAN_CIPHER_SUITE_GCMP: 630 + case WLAN_CIPHER_SUITE_GCMP_256: 629 631 if (!ieee80211_is_data_present(hdr->frame_control) && 630 632 !ieee80211_use_mfp(hdr->frame_control, tx->sta, 631 633 tx->skb)) ··· 1016 1014 return ieee80211_crypto_ccmp_encrypt(tx); 1017 1015 case WLAN_CIPHER_SUITE_AES_CMAC: 1018 1016 return ieee80211_crypto_aes_cmac_encrypt(tx); 1017 + case WLAN_CIPHER_SUITE_GCMP: 1018 + case WLAN_CIPHER_SUITE_GCMP_256: 1019 + return ieee80211_crypto_gcmp_encrypt(tx); 1019 1020 default: 1020 1021 return ieee80211_crypto_hw_encrypt(tx); 1021 1022 }
+224
net/mac80211/wpa.c
··· 22 22 #include "tkip.h" 23 23 #include "aes_ccm.h" 24 24 #include "aes_cmac.h" 25 + #include "aes_gcm.h" 25 26 #include "wpa.h" 26 27 27 28 ieee80211_tx_result ··· 543 542 return RX_DROP_UNUSABLE; 544 543 memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen); 545 544 skb_pull(skb, IEEE80211_CCMP_HDR_LEN); 545 + 546 + return RX_CONTINUE; 547 + } 548 + 549 + static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad) 550 + { 551 + __le16 mask_fc; 552 + u8 qos_tid; 553 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 554 + 555 + memcpy(j_0, hdr->addr2, ETH_ALEN); 556 + memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN); 557 + j_0[13] = 0; 558 + j_0[14] = 0; 559 + j_0[AES_BLOCK_SIZE - 1] = 0x01; 560 + 561 + /* AAD (extra authenticate-only data) / masked 802.11 header 562 + * FC | A1 | A2 | A3 | SC | [A4] | [QC] 563 + */ 564 + put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]); 565 + /* Mask FC: zero subtype b4 b5 b6 (if not mgmt) 566 + * Retry, PwrMgt, MoreData; set Protected 567 + */ 568 + mask_fc = hdr->frame_control; 569 + mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | 570 + IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); 571 + if (!ieee80211_is_mgmt(hdr->frame_control)) 572 + mask_fc &= ~cpu_to_le16(0x0070); 573 + mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 574 + 575 + put_unaligned(mask_fc, (__le16 *)&aad[2]); 576 + memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); 577 + 578 + /* Mask Seq#, leave Frag# */ 579 + aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f; 580 + aad[23] = 0; 581 + 582 + if (ieee80211_is_data_qos(hdr->frame_control)) 583 + qos_tid = *ieee80211_get_qos_ctl(hdr) & 584 + IEEE80211_QOS_CTL_TID_MASK; 585 + else 586 + qos_tid = 0; 587 + 588 + if (ieee80211_has_a4(hdr->frame_control)) { 589 + memcpy(&aad[24], hdr->addr4, ETH_ALEN); 590 + aad[30] = qos_tid; 591 + aad[31] = 0; 592 + } else { 593 + memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); 594 + aad[24] = qos_tid; 595 + } 596 + } 597 + 598 + static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id) 599 + { 600 + hdr[0] = pn[5]; 601 + hdr[1] = pn[4]; 602 + hdr[2] = 0; 603 + hdr[3] = 0x20 | (key_id << 6); 604 + hdr[4] = pn[3]; 605 + hdr[5] = pn[2]; 606 + hdr[6] = pn[1]; 607 + hdr[7] = pn[0]; 608 + } 609 + 610 + static inline void gcmp_hdr2pn(u8 *pn, const u8 *hdr) 611 + { 612 + pn[0] = hdr[7]; 613 + pn[1] = hdr[6]; 614 + pn[2] = hdr[5]; 615 + pn[3] = hdr[4]; 616 + pn[4] = hdr[1]; 617 + pn[5] = hdr[0]; 618 + } 619 + 620 + static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) 621 + { 622 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 623 + struct ieee80211_key *key = tx->key; 624 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 625 + int hdrlen, len, tail; 626 + u8 *pos; 627 + u8 pn[6]; 628 + u64 pn64; 629 + u8 aad[2 * AES_BLOCK_SIZE]; 630 + u8 j_0[AES_BLOCK_SIZE]; 631 + 632 + if (info->control.hw_key && 633 + !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && 634 + !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && 635 + !((info->control.hw_key->flags & 636 + IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) && 637 + ieee80211_is_mgmt(hdr->frame_control))) { 638 + /* hwaccel has no need for preallocated room for GCMP 639 + * header or MIC fields 640 + */ 641 + return 0; 642 + } 643 + 644 + hdrlen = ieee80211_hdrlen(hdr->frame_control); 645 + len = skb->len - hdrlen; 646 + 647 + if (info->control.hw_key) 648 + tail = 0; 649 + else 650 + tail = IEEE80211_GCMP_MIC_LEN; 651 + 652 + if (WARN_ON(skb_tailroom(skb) < tail || 653 + skb_headroom(skb) < IEEE80211_GCMP_HDR_LEN)) 654 + return -1; 655 + 656 + pos = skb_push(skb, IEEE80211_GCMP_HDR_LEN); 657 + memmove(pos, pos + IEEE80211_GCMP_HDR_LEN, hdrlen); 658 + skb_set_network_header(skb, skb_network_offset(skb) + 659 + IEEE80211_GCMP_HDR_LEN); 660 + 661 + /* the HW only needs room for the IV, but not the actual IV */ 662 + if (info->control.hw_key && 663 + (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) 664 + return 0; 665 + 666 + hdr = (struct ieee80211_hdr *)pos; 667 + pos += hdrlen; 668 + 669 + pn64 = atomic64_inc_return(&key->u.gcmp.tx_pn); 670 + 671 + pn[5] = pn64; 672 + pn[4] = pn64 >> 8; 673 + pn[3] = pn64 >> 16; 674 + pn[2] = pn64 >> 24; 675 + pn[1] = pn64 >> 32; 676 + pn[0] = pn64 >> 40; 677 + 678 + gcmp_pn2hdr(pos, pn, key->conf.keyidx); 679 + 680 + /* hwaccel - with software GCMP header */ 681 + if (info->control.hw_key) 682 + return 0; 683 + 684 + pos += IEEE80211_GCMP_HDR_LEN; 685 + gcmp_special_blocks(skb, pn, j_0, aad); 686 + ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len, 687 + skb_put(skb, IEEE80211_GCMP_MIC_LEN)); 688 + 689 + return 0; 690 + } 691 + 692 + ieee80211_tx_result 693 + ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx) 694 + { 695 + struct sk_buff *skb; 696 + 697 + ieee80211_tx_set_protected(tx); 698 + 699 + skb_queue_walk(&tx->skbs, skb) { 700 + if (gcmp_encrypt_skb(tx, skb) < 0) 701 + return TX_DROP; 702 + } 703 + 704 + return TX_CONTINUE; 705 + } 706 + 707 + ieee80211_rx_result 708 + ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) 709 + { 710 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 711 + int hdrlen; 712 + struct ieee80211_key *key = rx->key; 713 + struct sk_buff *skb = rx->skb; 714 + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 715 + u8 pn[IEEE80211_GCMP_PN_LEN]; 716 + int data_len; 717 + int queue; 718 + 719 + hdrlen = ieee80211_hdrlen(hdr->frame_control); 720 + 721 + if (!ieee80211_is_data(hdr->frame_control) && 722 + !ieee80211_is_robust_mgmt_frame(skb)) 723 + return RX_CONTINUE; 724 + 725 + data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - 726 + IEEE80211_GCMP_MIC_LEN; 727 + if (!rx->sta || data_len < 0) 728 + return RX_DROP_UNUSABLE; 729 + 730 + if (status->flag & RX_FLAG_DECRYPTED) { 731 + if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN)) 732 + return RX_DROP_UNUSABLE; 733 + } else { 734 + if (skb_linearize(rx->skb)) 735 + return RX_DROP_UNUSABLE; 736 + } 737 + 738 + gcmp_hdr2pn(pn, skb->data + hdrlen); 739 + 740 + queue = rx->security_idx; 741 + 742 + if (memcmp(pn, key->u.gcmp.rx_pn[queue], IEEE80211_GCMP_PN_LEN) <= 0) { 743 + key->u.gcmp.replays++; 744 + return RX_DROP_UNUSABLE; 745 + } 746 + 747 + if (!(status->flag & RX_FLAG_DECRYPTED)) { 748 + u8 aad[2 * AES_BLOCK_SIZE]; 749 + u8 j_0[AES_BLOCK_SIZE]; 750 + /* hardware didn't decrypt/verify MIC */ 751 + gcmp_special_blocks(skb, pn, j_0, aad); 752 + 753 + if (ieee80211_aes_gcm_decrypt( 754 + key->u.gcmp.tfm, j_0, aad, 755 + skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN, 756 + data_len, 757 + skb->data + skb->len - IEEE80211_GCMP_MIC_LEN)) 758 + return RX_DROP_UNUSABLE; 759 + } 760 + 761 + memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN); 762 + 763 + /* Remove GCMP header and MIC */ 764 + if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN)) 765 + return RX_DROP_UNUSABLE; 766 + memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen); 767 + skb_pull(skb, IEEE80211_GCMP_HDR_LEN); 546 768 547 769 return RX_CONTINUE; 548 770 }
+5
net/mac80211/wpa.h
··· 37 37 ieee80211_rx_result 38 38 ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx); 39 39 40 + ieee80211_tx_result 41 + ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx); 42 + ieee80211_rx_result 43 + ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx); 44 + 40 45 #endif /* WPA_H */