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

mac80111: Add CCMP-256 cipher

This allows mac80211 to configure CCMP-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>
[squash ccmp256 -> mic_len argument change]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Jouni Malinen and committed by
Johannes Berg
2b2ba0db 00b9cfa3

+88 -31
+12 -9
net/mac80211/aes_ccm.c
··· 20 20 #include "aes_ccm.h" 21 21 22 22 void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 23 - u8 *data, size_t data_len, u8 *mic) 23 + u8 *data, size_t data_len, u8 *mic, 24 + size_t mic_len) 24 25 { 25 26 struct scatterlist assoc, pt, ct[2]; 26 27 ··· 36 35 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 37 36 sg_init_table(ct, 2); 38 37 sg_set_buf(&ct[0], data, data_len); 39 - sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); 38 + sg_set_buf(&ct[1], mic, mic_len); 40 39 41 40 aead_request_set_tfm(aead_req, tfm); 42 41 aead_request_set_assoc(aead_req, &assoc, assoc.length); ··· 46 45 } 47 46 48 47 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 49 - u8 *data, size_t data_len, u8 *mic) 48 + u8 *data, size_t data_len, u8 *mic, 49 + size_t mic_len) 50 50 { 51 51 struct scatterlist assoc, pt, ct[2]; 52 52 char aead_req_data[sizeof(struct aead_request) + ··· 64 62 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 65 63 sg_init_table(ct, 2); 66 64 sg_set_buf(&ct[0], data, data_len); 67 - sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); 65 + sg_set_buf(&ct[1], mic, mic_len); 68 66 69 67 aead_request_set_tfm(aead_req, tfm); 70 68 aead_request_set_assoc(aead_req, &assoc, assoc.length); 71 - aead_request_set_crypt(aead_req, ct, &pt, 72 - data_len + IEEE80211_CCMP_MIC_LEN, b_0); 69 + aead_request_set_crypt(aead_req, ct, &pt, data_len + mic_len, b_0); 73 70 74 71 return crypto_aead_decrypt(aead_req); 75 72 } 76 73 77 - struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]) 74 + struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], 75 + size_t key_len, 76 + size_t mic_len) 78 77 { 79 78 struct crypto_aead *tfm; 80 79 int err; ··· 84 81 if (IS_ERR(tfm)) 85 82 return tfm; 86 83 87 - err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP); 84 + err = crypto_aead_setkey(tfm, key, key_len); 88 85 if (!err) 89 - err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN); 86 + err = crypto_aead_setauthsize(tfm, mic_len); 90 87 if (!err) 91 88 return tfm; 92 89
+7 -3
net/mac80211/aes_ccm.h
··· 12 12 13 13 #include <linux/crypto.h> 14 14 15 - struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]); 15 + struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], 16 + size_t key_len, 17 + size_t mic_len); 16 18 void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 17 - u8 *data, size_t data_len, u8 *mic); 19 + u8 *data, size_t data_len, u8 *mic, 20 + size_t mic_len); 18 21 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 19 - u8 *data, size_t data_len, u8 *mic); 22 + u8 *data, size_t data_len, u8 *mic, 23 + size_t mic_len); 20 24 void ieee80211_aes_key_free(struct crypto_aead *tfm); 21 25 22 26 #endif /* AES_CCM_H */
+2
net/mac80211/cfg.c
··· 162 162 return -EINVAL; 163 163 break; 164 164 case WLAN_CIPHER_SUITE_CCMP: 165 + case WLAN_CIPHER_SUITE_CCMP_256: 165 166 case WLAN_CIPHER_SUITE_AES_CMAC: 166 167 case WLAN_CIPHER_SUITE_GCMP: 167 168 case WLAN_CIPHER_SUITE_GCMP_256: ··· 350 349 params.seq_len = 6; 351 350 break; 352 351 case WLAN_CIPHER_SUITE_CCMP: 352 + case WLAN_CIPHER_SUITE_CCMP_256: 353 353 pn64 = atomic64_read(&key->u.ccmp.tx_pn); 354 354 seq[0] = pn64; 355 355 seq[1] = pn64 >> 8;
+3
net/mac80211/debugfs_key.c
··· 94 94 key->u.tkip.tx.iv16); 95 95 break; 96 96 case WLAN_CIPHER_SUITE_CCMP: 97 + case WLAN_CIPHER_SUITE_CCMP_256: 97 98 pn = atomic64_read(&key->u.ccmp.tx_pn); 98 99 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 99 100 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), ··· 142 141 len = p - buf; 143 142 break; 144 143 case WLAN_CIPHER_SUITE_CCMP: 144 + case WLAN_CIPHER_SUITE_CCMP_256: 145 145 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 146 146 rpn = key->u.ccmp.rx_pn[i]; 147 147 p += scnprintf(p, sizeof(buf)+buf-p, ··· 187 185 188 186 switch (key->conf.cipher) { 189 187 case WLAN_CIPHER_SUITE_CCMP: 188 + case WLAN_CIPHER_SUITE_CCMP_256: 190 189 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 191 190 break; 192 191 case WLAN_CIPHER_SUITE_AES_CMAC:
+26 -1
net/mac80211/key.c
··· 163 163 case WLAN_CIPHER_SUITE_WEP104: 164 164 case WLAN_CIPHER_SUITE_TKIP: 165 165 case WLAN_CIPHER_SUITE_CCMP: 166 + case WLAN_CIPHER_SUITE_CCMP_256: 166 167 case WLAN_CIPHER_SUITE_AES_CMAC: 167 168 case WLAN_CIPHER_SUITE_GCMP: 168 169 case WLAN_CIPHER_SUITE_GCMP_256: ··· 390 389 * Initialize AES key state here as an optimization so that 391 390 * it does not need to be initialized for every packet. 392 391 */ 393 - key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); 392 + key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( 393 + key_data, key_len, IEEE80211_CCMP_MIC_LEN); 394 + if (IS_ERR(key->u.ccmp.tfm)) { 395 + err = PTR_ERR(key->u.ccmp.tfm); 396 + kfree(key); 397 + return ERR_PTR(err); 398 + } 399 + break; 400 + case WLAN_CIPHER_SUITE_CCMP_256: 401 + key->conf.iv_len = IEEE80211_CCMP_256_HDR_LEN; 402 + key->conf.icv_len = IEEE80211_CCMP_256_MIC_LEN; 403 + for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++) 404 + for (j = 0; j < IEEE80211_CCMP_256_PN_LEN; j++) 405 + key->u.ccmp.rx_pn[i][j] = 406 + seq[IEEE80211_CCMP_256_PN_LEN - j - 1]; 407 + /* Initialize AES key state here as an optimization so that 408 + * it does not need to be initialized for every packet. 409 + */ 410 + key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( 411 + key_data, key_len, IEEE80211_CCMP_256_MIC_LEN); 394 412 if (IS_ERR(key->u.ccmp.tfm)) { 395 413 err = PTR_ERR(key->u.ccmp.tfm); 396 414 kfree(key); ··· 477 457 { 478 458 switch (key->conf.cipher) { 479 459 case WLAN_CIPHER_SUITE_CCMP: 460 + case WLAN_CIPHER_SUITE_CCMP_256: 480 461 ieee80211_aes_key_free(key->u.ccmp.tfm); 481 462 break; 482 463 case WLAN_CIPHER_SUITE_AES_CMAC: ··· 794 773 seq->tkip.iv16 = key->u.tkip.tx.iv16; 795 774 break; 796 775 case WLAN_CIPHER_SUITE_CCMP: 776 + case WLAN_CIPHER_SUITE_CCMP_256: 797 777 pn64 = atomic64_read(&key->u.ccmp.tx_pn); 798 778 seq->ccmp.pn[5] = pn64; 799 779 seq->ccmp.pn[4] = pn64 >> 8; ··· 844 822 seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; 845 823 break; 846 824 case WLAN_CIPHER_SUITE_CCMP: 825 + case WLAN_CIPHER_SUITE_CCMP_256: 847 826 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 848 827 return; 849 828 if (tid < 0) ··· 887 864 key->u.tkip.tx.iv16 = seq->tkip.iv16; 888 865 break; 889 866 case WLAN_CIPHER_SUITE_CCMP: 867 + case WLAN_CIPHER_SUITE_CCMP_256: 890 868 pn64 = (u64)seq->ccmp.pn[5] | 891 869 ((u64)seq->ccmp.pn[4] << 8) | 892 870 ((u64)seq->ccmp.pn[3] << 16) | ··· 938 914 key->u.tkip.rx[tid].iv16 = seq->tkip.iv16; 939 915 break; 940 916 case WLAN_CIPHER_SUITE_CCMP: 917 + case WLAN_CIPHER_SUITE_CCMP_256: 941 918 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 942 919 return; 943 920 if (tid < 0)
+4 -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_CCMP_256, 669 670 WLAN_CIPHER_SUITE_GCMP, 670 671 WLAN_CIPHER_SUITE_GCMP_256, 671 672 ··· 728 727 * including the schemes) 729 728 * 730 729 * We start counting ciphers defined by schemes, TKIP, CCMP, 731 - * GCMP, and GCMP-256 730 + * CCMP-256, GCMP, and GCMP-256 732 731 */ 733 - n_suites = local->hw.n_cipher_schemes + 4; 732 + n_suites = local->hw.n_cipher_schemes + 5; 734 733 735 734 /* check if we have WEP40 and WEP104 */ 736 735 if (have_wep) ··· 745 744 return -ENOMEM; 746 745 747 746 suites[w++] = WLAN_CIPHER_SUITE_CCMP; 747 + suites[w++] = WLAN_CIPHER_SUITE_CCMP_256; 748 748 suites[w++] = WLAN_CIPHER_SUITE_TKIP; 749 749 suites[w++] = WLAN_CIPHER_SUITE_GCMP; 750 750 suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
+12 -3
net/mac80211/rx.c
··· 1650 1650 result = ieee80211_crypto_tkip_decrypt(rx); 1651 1651 break; 1652 1652 case WLAN_CIPHER_SUITE_CCMP: 1653 - result = ieee80211_crypto_ccmp_decrypt(rx); 1653 + result = ieee80211_crypto_ccmp_decrypt( 1654 + rx, IEEE80211_CCMP_MIC_LEN); 1655 + break; 1656 + case WLAN_CIPHER_SUITE_CCMP_256: 1657 + result = ieee80211_crypto_ccmp_decrypt( 1658 + rx, IEEE80211_CCMP_256_MIC_LEN); 1654 1659 break; 1655 1660 case WLAN_CIPHER_SUITE_AES_CMAC: 1656 1661 result = ieee80211_crypto_aes_cmac_decrypt(rx); ··· 1790 1785 /* This is the first fragment of a new frame. */ 1791 1786 entry = ieee80211_reassemble_add(rx->sdata, frag, seq, 1792 1787 rx->seqno_idx, &(rx->skb)); 1793 - if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && 1788 + if (rx->key && 1789 + (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || 1790 + rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) && 1794 1791 ieee80211_has_protected(fc)) { 1795 1792 int queue = rx->security_idx; 1796 1793 /* Store CCMP PN so that we can verify that the next ··· 1821 1814 int i; 1822 1815 u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; 1823 1816 int queue; 1824 - if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) 1817 + if (!rx->key || 1818 + (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP && 1819 + rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256)) 1825 1820 return RX_DROP_UNUSABLE; 1826 1821 memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); 1827 1822 for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
+6 -1
net/mac80211/tx.c
··· 626 626 tx->key = NULL; 627 627 break; 628 628 case WLAN_CIPHER_SUITE_CCMP: 629 + case WLAN_CIPHER_SUITE_CCMP_256: 629 630 case WLAN_CIPHER_SUITE_GCMP: 630 631 case WLAN_CIPHER_SUITE_GCMP_256: 631 632 if (!ieee80211_is_data_present(hdr->frame_control) && ··· 1014 1013 case WLAN_CIPHER_SUITE_TKIP: 1015 1014 return ieee80211_crypto_tkip_encrypt(tx); 1016 1015 case WLAN_CIPHER_SUITE_CCMP: 1017 - return ieee80211_crypto_ccmp_encrypt(tx); 1016 + return ieee80211_crypto_ccmp_encrypt( 1017 + tx, IEEE80211_CCMP_MIC_LEN); 1018 + case WLAN_CIPHER_SUITE_CCMP_256: 1019 + return ieee80211_crypto_ccmp_encrypt( 1020 + tx, IEEE80211_CCMP_256_MIC_LEN); 1018 1021 case WLAN_CIPHER_SUITE_AES_CMAC: 1019 1022 return ieee80211_crypto_aes_cmac_encrypt(tx); 1020 1023 case WLAN_CIPHER_SUITE_GCMP:
+12 -10
net/mac80211/wpa.c
··· 394 394 } 395 395 396 396 397 - static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) 397 + static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, 398 + unsigned int mic_len) 398 399 { 399 400 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 400 401 struct ieee80211_key *key = tx->key; ··· 426 425 if (info->control.hw_key) 427 426 tail = 0; 428 427 else 429 - tail = IEEE80211_CCMP_MIC_LEN; 428 + tail = mic_len; 430 429 431 430 if (WARN_ON(skb_tailroom(skb) < tail || 432 431 skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN)) ··· 461 460 pos += IEEE80211_CCMP_HDR_LEN; 462 461 ccmp_special_blocks(skb, pn, b_0, aad); 463 462 ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, 464 - skb_put(skb, IEEE80211_CCMP_MIC_LEN)); 463 + skb_put(skb, mic_len), mic_len); 465 464 466 465 return 0; 467 466 } 468 467 469 468 470 469 ieee80211_tx_result 471 - ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) 470 + ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx, 471 + unsigned int mic_len) 472 472 { 473 473 struct sk_buff *skb; 474 474 475 475 ieee80211_tx_set_protected(tx); 476 476 477 477 skb_queue_walk(&tx->skbs, skb) { 478 - if (ccmp_encrypt_skb(tx, skb) < 0) 478 + if (ccmp_encrypt_skb(tx, skb, mic_len) < 0) 479 479 return TX_DROP; 480 480 } 481 481 ··· 485 483 486 484 487 485 ieee80211_rx_result 488 - ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) 486 + ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, 487 + unsigned int mic_len) 489 488 { 490 489 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 491 490 int hdrlen; ··· 503 500 !ieee80211_is_robust_mgmt_frame(skb)) 504 501 return RX_CONTINUE; 505 502 506 - data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - 507 - IEEE80211_CCMP_MIC_LEN; 503 + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; 508 504 if (!rx->sta || data_len < 0) 509 505 return RX_DROP_UNUSABLE; 510 506 ··· 534 532 key->u.ccmp.tfm, b_0, aad, 535 533 skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, 536 534 data_len, 537 - skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) 535 + skb->data + skb->len - mic_len, mic_len)) 538 536 return RX_DROP_UNUSABLE; 539 537 } 540 538 541 539 memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN); 542 540 543 541 /* Remove CCMP header and MIC */ 544 - if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN)) 542 + if (pskb_trim(skb, skb->len - mic_len)) 545 543 return RX_DROP_UNUSABLE; 546 544 memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen); 547 545 skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
+4 -2
net/mac80211/wpa.h
··· 24 24 ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx); 25 25 26 26 ieee80211_tx_result 27 - ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx); 27 + ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx, 28 + unsigned int mic_len); 28 29 ieee80211_rx_result 29 - ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); 30 + ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, 31 + unsigned int mic_len); 30 32 31 33 ieee80211_tx_result 32 34 ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);