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

mac80111: Add BIP-CMAC-256 cipher

This allows mac80211 to configure BIP-CMAC-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
56c52da2 2b2ba0db

+179 -20
+9
include/linux/ieee80211.h
··· 1017 1017 u8 mic[8]; 1018 1018 } __packed; 1019 1019 1020 + /* Management MIC information element (IEEE 802.11w) for GMAC and CMAC-256 */ 1021 + struct ieee80211_mmie_16 { 1022 + u8 element_id; 1023 + u8 length; 1024 + __le16 key_id; 1025 + u8 sequence_number[6]; 1026 + u8 mic[16]; 1027 + } __packed; 1028 + 1020 1029 struct ieee80211_vendor_ie { 1021 1030 u8 element_id; 1022 1031 u8 len;
+26 -8
net/mac80211/aes_cmac.c
··· 18 18 #include "key.h" 19 19 #include "aes_cmac.h" 20 20 21 - #define AES_CMAC_KEY_LEN 16 22 21 #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ 22 + #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ 23 23 #define AAD_LEN 20 24 24 25 25 ··· 35 35 pad[AES_BLOCK_SIZE - 1] ^= 0x87; 36 36 } 37 37 38 - 39 - static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, 40 - const u8 *addr[], const size_t *len, u8 *mac) 38 + static void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, 39 + const u8 *addr[], const size_t *len, u8 *mac, 40 + size_t mac_len) 41 41 { 42 42 u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; 43 43 const u8 *pos, *end; ··· 88 88 for (i = 0; i < AES_BLOCK_SIZE; i++) 89 89 pad[i] ^= cbc[i]; 90 90 crypto_cipher_encrypt_one(tfm, pad, pad); 91 - memcpy(mac, pad, CMAC_TLEN); 91 + memcpy(mac, pad, mac_len); 92 92 } 93 93 94 94 ··· 107 107 addr[2] = zero; 108 108 len[2] = CMAC_TLEN; 109 109 110 - aes_128_cmac_vector(tfm, 3, addr, len, mic); 110 + aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); 111 111 } 112 112 113 + void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, 114 + const u8 *data, size_t data_len, u8 *mic) 115 + { 116 + const u8 *addr[3]; 117 + size_t len[3]; 118 + u8 zero[CMAC_TLEN_256]; 113 119 114 - struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[]) 120 + memset(zero, 0, CMAC_TLEN_256); 121 + addr[0] = aad; 122 + len[0] = AAD_LEN; 123 + addr[1] = data; 124 + len[1] = data_len - CMAC_TLEN_256; 125 + addr[2] = zero; 126 + len[2] = CMAC_TLEN_256; 127 + 128 + aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); 129 + } 130 + 131 + struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], 132 + size_t key_len) 115 133 { 116 134 struct crypto_cipher *tfm; 117 135 118 136 tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); 119 137 if (!IS_ERR(tfm)) 120 - crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); 138 + crypto_cipher_setkey(tfm, key, key_len); 121 139 122 140 return tfm; 123 141 }
+4 -1
net/mac80211/aes_cmac.h
··· 11 11 12 12 #include <linux/crypto.h> 13 13 14 - struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[]); 14 + struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], 15 + size_t key_len); 15 16 void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, 16 17 const u8 *data, size_t data_len, u8 *mic); 18 + void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, 19 + const u8 *data, size_t data_len, u8 *mic); 17 20 void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); 18 21 19 22 #endif /* AES_CMAC_H */
+2
net/mac80211/cfg.c
··· 164 164 case WLAN_CIPHER_SUITE_CCMP: 165 165 case WLAN_CIPHER_SUITE_CCMP_256: 166 166 case WLAN_CIPHER_SUITE_AES_CMAC: 167 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 167 168 case WLAN_CIPHER_SUITE_GCMP: 168 169 case WLAN_CIPHER_SUITE_GCMP_256: 169 170 break; ··· 363 362 params.seq_len = 6; 364 363 break; 365 364 case WLAN_CIPHER_SUITE_AES_CMAC: 365 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 366 366 pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); 367 367 seq[0] = pn64; 368 368 seq[1] = pn64 >> 8;
+4
net/mac80211/debugfs_key.c
··· 101 101 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 102 102 break; 103 103 case WLAN_CIPHER_SUITE_AES_CMAC: 104 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 104 105 pn = atomic64_read(&key->u.aes_cmac.tx_pn); 105 106 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 106 107 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), ··· 154 153 len = p - buf; 155 154 break; 156 155 case WLAN_CIPHER_SUITE_AES_CMAC: 156 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 157 157 rpn = key->u.aes_cmac.rx_pn; 158 158 p += scnprintf(p, sizeof(buf)+buf-p, 159 159 "%02x%02x%02x%02x%02x%02x\n", ··· 193 191 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 194 192 break; 195 193 case WLAN_CIPHER_SUITE_AES_CMAC: 194 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 196 195 len = scnprintf(buf, sizeof(buf), "%u\n", 197 196 key->u.aes_cmac.replays); 198 197 break; ··· 217 214 218 215 switch (key->conf.cipher) { 219 216 case WLAN_CIPHER_SUITE_AES_CMAC: 217 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 220 218 len = scnprintf(buf, sizeof(buf), "%u\n", 221 219 key->u.aes_cmac.icverrors); 222 220 break;
+12 -2
net/mac80211/key.c
··· 165 165 case WLAN_CIPHER_SUITE_CCMP: 166 166 case WLAN_CIPHER_SUITE_CCMP_256: 167 167 case WLAN_CIPHER_SUITE_AES_CMAC: 168 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 168 169 case WLAN_CIPHER_SUITE_GCMP: 169 170 case WLAN_CIPHER_SUITE_GCMP_256: 170 171 /* all of these we can do in software - if driver can */ ··· 418 417 } 419 418 break; 420 419 case WLAN_CIPHER_SUITE_AES_CMAC: 420 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 421 421 key->conf.iv_len = 0; 422 - key->conf.icv_len = sizeof(struct ieee80211_mmie); 422 + if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) 423 + key->conf.icv_len = sizeof(struct ieee80211_mmie); 424 + else 425 + key->conf.icv_len = sizeof(struct ieee80211_mmie_16); 423 426 if (seq) 424 427 for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++) 425 428 key->u.aes_cmac.rx_pn[j] = ··· 433 428 * it does not need to be initialized for every packet. 434 429 */ 435 430 key->u.aes_cmac.tfm = 436 - ieee80211_aes_cmac_key_setup(key_data); 431 + ieee80211_aes_cmac_key_setup(key_data, key_len); 437 432 if (IS_ERR(key->u.aes_cmac.tfm)) { 438 433 err = PTR_ERR(key->u.aes_cmac.tfm); 439 434 kfree(key); ··· 486 481 ieee80211_aes_key_free(key->u.ccmp.tfm); 487 482 break; 488 483 case WLAN_CIPHER_SUITE_AES_CMAC: 484 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 489 485 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 490 486 break; 491 487 case WLAN_CIPHER_SUITE_GCMP: ··· 810 804 seq->ccmp.pn[0] = pn64 >> 40; 811 805 break; 812 806 case WLAN_CIPHER_SUITE_AES_CMAC: 807 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 813 808 pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); 814 809 seq->ccmp.pn[5] = pn64; 815 810 seq->ccmp.pn[4] = pn64 >> 8; ··· 861 854 memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN); 862 855 break; 863 856 case WLAN_CIPHER_SUITE_AES_CMAC: 857 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 864 858 if (WARN_ON(tid != 0)) 865 859 return; 866 860 pn = key->u.aes_cmac.rx_pn; ··· 905 897 atomic64_set(&key->u.ccmp.tx_pn, pn64); 906 898 break; 907 899 case WLAN_CIPHER_SUITE_AES_CMAC: 900 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 908 901 pn64 = (u64)seq->aes_cmac.pn[5] | 909 902 ((u64)seq->aes_cmac.pn[4] << 8) | 910 903 ((u64)seq->aes_cmac.pn[3] << 16) | ··· 957 948 memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN); 958 949 break; 959 950 case WLAN_CIPHER_SUITE_AES_CMAC: 951 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 960 952 if (WARN_ON(tid != 0)) 961 953 return; 962 954 pn = key->u.aes_cmac.rx_pn;
+8 -5
net/mac80211/main.c
··· 671 671 WLAN_CIPHER_SUITE_GCMP_256, 672 672 673 673 /* keep last -- depends on hw flags! */ 674 - WLAN_CIPHER_SUITE_AES_CMAC 674 + WLAN_CIPHER_SUITE_AES_CMAC, 675 + WLAN_CIPHER_SUITE_BIP_CMAC_256, 675 676 }; 676 677 677 678 if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || ··· 711 710 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 712 711 713 712 if (!have_mfp) 714 - local->hw.wiphy->n_cipher_suites--; 713 + local->hw.wiphy->n_cipher_suites -= 2; 715 714 716 715 if (!have_wep) { 717 716 local->hw.wiphy->cipher_suites += 2; ··· 737 736 if (have_wep) 738 737 n_suites += 2; 739 738 740 - /* check if we have AES_CMAC */ 739 + /* check if we have AES_CMAC, BIP-CMAC-256 */ 741 740 if (have_mfp) 742 - n_suites++; 741 + n_suites += 2; 743 742 744 743 suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); 745 744 if (!suites) ··· 756 755 suites[w++] = WLAN_CIPHER_SUITE_WEP104; 757 756 } 758 757 759 - if (have_mfp) 758 + if (have_mfp) { 760 759 suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; 760 + suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; 761 + } 761 762 762 763 for (r = 0; r < local->hw.n_cipher_schemes; r++) 763 764 suites[w++] = cs[r].cipher;
+15 -4
net/mac80211/rx.c
··· 647 647 { 648 648 struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; 649 649 struct ieee80211_mmie *mmie; 650 + struct ieee80211_mmie_16 *mmie16; 650 651 651 652 if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) 652 653 return -1; ··· 657 656 658 657 mmie = (struct ieee80211_mmie *) 659 658 (skb->data + skb->len - sizeof(*mmie)); 660 - if (mmie->element_id != WLAN_EID_MMIE || 661 - mmie->length != sizeof(*mmie) - 2) 662 - return -1; 659 + if (mmie->element_id == WLAN_EID_MMIE && 660 + mmie->length == sizeof(*mmie) - 2) 661 + return le16_to_cpu(mmie->key_id); 663 662 664 - return le16_to_cpu(mmie->key_id); 663 + mmie16 = (struct ieee80211_mmie_16 *) 664 + (skb->data + skb->len - sizeof(*mmie16)); 665 + if (skb->len >= 24 + sizeof(*mmie16) && 666 + mmie16->element_id == WLAN_EID_MMIE && 667 + mmie16->length == sizeof(*mmie16) - 2) 668 + return le16_to_cpu(mmie16->key_id); 669 + 670 + return -1; 665 671 } 666 672 667 673 static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, ··· 1667 1659 break; 1668 1660 case WLAN_CIPHER_SUITE_AES_CMAC: 1669 1661 result = ieee80211_crypto_aes_cmac_decrypt(rx); 1662 + break; 1663 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1664 + result = ieee80211_crypto_aes_cmac_256_decrypt(rx); 1670 1665 break; 1671 1666 case WLAN_CIPHER_SUITE_GCMP: 1672 1667 case WLAN_CIPHER_SUITE_GCMP_256:
+3
net/mac80211/tx.c
··· 639 639 ieee80211_is_mgmt(hdr->frame_control); 640 640 break; 641 641 case WLAN_CIPHER_SUITE_AES_CMAC: 642 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 642 643 if (!ieee80211_is_mgmt(hdr->frame_control)) 643 644 tx->key = NULL; 644 645 break; ··· 1022 1021 tx, IEEE80211_CCMP_256_MIC_LEN); 1023 1022 case WLAN_CIPHER_SUITE_AES_CMAC: 1024 1023 return ieee80211_crypto_aes_cmac_encrypt(tx); 1024 + case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1025 + return ieee80211_crypto_aes_cmac_256_encrypt(tx); 1025 1026 case WLAN_CIPHER_SUITE_GCMP: 1026 1027 case WLAN_CIPHER_SUITE_GCMP_256: 1027 1028 return ieee80211_crypto_gcmp_encrypt(tx);
+92
net/mac80211/wpa.c
··· 955 955 return TX_CONTINUE; 956 956 } 957 957 958 + ieee80211_tx_result 959 + ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx) 960 + { 961 + struct sk_buff *skb; 962 + struct ieee80211_tx_info *info; 963 + struct ieee80211_key *key = tx->key; 964 + struct ieee80211_mmie_16 *mmie; 965 + u8 aad[20]; 966 + u64 pn64; 967 + 968 + if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) 969 + return TX_DROP; 970 + 971 + skb = skb_peek(&tx->skbs); 972 + 973 + info = IEEE80211_SKB_CB(skb); 974 + 975 + if (info->control.hw_key) 976 + return TX_CONTINUE; 977 + 978 + if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) 979 + return TX_DROP; 980 + 981 + mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie)); 982 + mmie->element_id = WLAN_EID_MMIE; 983 + mmie->length = sizeof(*mmie) - 2; 984 + mmie->key_id = cpu_to_le16(key->conf.keyidx); 985 + 986 + /* PN = PN + 1 */ 987 + pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn); 988 + 989 + bip_ipn_set64(mmie->sequence_number, pn64); 990 + 991 + bip_aad(skb, aad); 992 + 993 + /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128) 994 + */ 995 + ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, 996 + skb->data + 24, skb->len - 24, mmie->mic); 997 + 998 + return TX_CONTINUE; 999 + } 958 1000 959 1001 ieee80211_rx_result 960 1002 ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) ··· 1034 992 bip_aad(skb, aad); 1035 993 ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, 1036 994 skb->data + 24, skb->len - 24, mic); 995 + if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { 996 + key->u.aes_cmac.icverrors++; 997 + return RX_DROP_UNUSABLE; 998 + } 999 + } 1000 + 1001 + memcpy(key->u.aes_cmac.rx_pn, ipn, 6); 1002 + 1003 + /* Remove MMIE */ 1004 + skb_trim(skb, skb->len - sizeof(*mmie)); 1005 + 1006 + return RX_CONTINUE; 1007 + } 1008 + 1009 + ieee80211_rx_result 1010 + ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) 1011 + { 1012 + struct sk_buff *skb = rx->skb; 1013 + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 1014 + struct ieee80211_key *key = rx->key; 1015 + struct ieee80211_mmie_16 *mmie; 1016 + u8 aad[20], mic[16], ipn[6]; 1017 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1018 + 1019 + if (!ieee80211_is_mgmt(hdr->frame_control)) 1020 + return RX_CONTINUE; 1021 + 1022 + /* management frames are already linear */ 1023 + 1024 + if (skb->len < 24 + sizeof(*mmie)) 1025 + return RX_DROP_UNUSABLE; 1026 + 1027 + mmie = (struct ieee80211_mmie_16 *) 1028 + (skb->data + skb->len - sizeof(*mmie)); 1029 + if (mmie->element_id != WLAN_EID_MMIE || 1030 + mmie->length != sizeof(*mmie) - 2) 1031 + return RX_DROP_UNUSABLE; /* Invalid MMIE */ 1032 + 1033 + bip_ipn_swap(ipn, mmie->sequence_number); 1034 + 1035 + if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) { 1036 + key->u.aes_cmac.replays++; 1037 + return RX_DROP_UNUSABLE; 1038 + } 1039 + 1040 + if (!(status->flag & RX_FLAG_DECRYPTED)) { 1041 + /* hardware didn't decrypt/verify MIC */ 1042 + bip_aad(skb, aad); 1043 + ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, 1044 + skb->data + 24, skb->len - 24, mic); 1037 1045 if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { 1038 1046 key->u.aes_cmac.icverrors++; 1039 1047 return RX_DROP_UNUSABLE;
+4
net/mac80211/wpa.h
··· 32 32 33 33 ieee80211_tx_result 34 34 ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); 35 + ieee80211_tx_result 36 + ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx); 35 37 ieee80211_rx_result 36 38 ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); 39 + ieee80211_rx_result 40 + ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx); 37 41 ieee80211_tx_result 38 42 ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); 39 43 ieee80211_rx_result