Commit b688a944 authored by Chien Wong's avatar Chien Wong Committed by Johannes Berg
Browse files

wifi: mac80211: refactor CMAC packet handlers



Merge CMAC-128 and CMAC-256 handlers since they are almost the same.
This removes duplication.

The comment 'MIC = AES-128-CMAC(IGTK, AAD ...' is out-dated since CMAC
is also used with BIGTK, as is the comment for CMAC-256. Simply remove
the comments.

Tested-on: mac80211_hwsim

Signed-off-by: default avatarChien Wong <m@xv97.com>
Link: https://patch.msgid.link/20251113140511.48658-6-m@xv97.com


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a22fb192
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -2215,10 +2215,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
			rx, IEEE80211_CCMP_256_MIC_LEN);
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
		result = ieee80211_crypto_aes_cmac_decrypt(rx);
		result = ieee80211_crypto_aes_cmac_decrypt(
			rx, IEEE80211_CMAC_128_MIC_LEN);
		break;
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		result = ieee80211_crypto_aes_cmac_256_decrypt(rx);
		result = ieee80211_crypto_aes_cmac_decrypt(
			rx, IEEE80211_CMAC_256_MIC_LEN);
		break;
	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+4 −2
Original line number Diff line number Diff line
@@ -1062,9 +1062,11 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
		return ieee80211_crypto_ccmp_encrypt(
			tx, IEEE80211_CCMP_256_MIC_LEN);
	case WLAN_CIPHER_SUITE_AES_CMAC:
		return ieee80211_crypto_aes_cmac_encrypt(tx);
		return ieee80211_crypto_aes_cmac_encrypt(
			tx, IEEE80211_CMAC_128_MIC_LEN);
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		return ieee80211_crypto_aes_cmac_256_encrypt(tx);
		return ieee80211_crypto_aes_cmac_encrypt(
			tx, IEEE80211_CMAC_256_MIC_LEN);
	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
		return ieee80211_crypto_aes_gmac_encrypt(tx);
+25 −121
Original line number Diff line number Diff line
@@ -828,12 +828,14 @@ static inline void bip_ipn_swap(u8 *d, const u8 *s)


ieee80211_tx_result
ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx,
				  unsigned int mic_len)
{
	struct sk_buff *skb;
	struct ieee80211_tx_info *info;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_mmie *mmie;
	struct ieee80211_mmie_var *mmie;
	size_t mmie_len;
	u8 aad[20];
	u64 pn64;

@@ -848,62 +850,14 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
	    !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
		return TX_CONTINUE;

	if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
		return TX_DROP;

	mmie = skb_put(skb, sizeof(*mmie));
	mmie->element_id = WLAN_EID_MMIE;
	mmie->length = sizeof(*mmie) - 2;
	mmie->key_id = cpu_to_le16(key->conf.keyidx);

	/* PN = PN + 1 */
	pn64 = atomic64_inc_return(&key->conf.tx_pn);

	bip_ipn_set64(mmie->sequence_number, pn64);

	if (info->control.hw_key)
		return TX_CONTINUE;

	bip_aad(skb, aad);
	mmie_len = sizeof(*mmie) + mic_len;

	/*
	 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
	 */
	if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
			       skb->data + 24, skb->len - 24, mmie->mic,
			       IEEE80211_CMAC_128_MIC_LEN))
	if (WARN_ON(skb_tailroom(skb) < mmie_len))
		return TX_DROP;

	return TX_CONTINUE;
}

ieee80211_tx_result
ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
{
	struct sk_buff *skb;
	struct ieee80211_tx_info *info;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_mmie_16 *mmie;
	u8 aad[20];
	u64 pn64;

	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
		return TX_DROP;

	skb = skb_peek(&tx->skbs);

	info = IEEE80211_SKB_CB(skb);

	if (info->control.hw_key &&
	    !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
		return TX_CONTINUE;

	if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
		return TX_DROP;

	mmie = skb_put(skb, sizeof(*mmie));
	mmie = skb_put(skb, mmie_len);
	mmie->element_id = WLAN_EID_MMIE;
	mmie->length = sizeof(*mmie) - 2;
	mmie->length = mmie_len - 2;
	mmie->key_id = cpu_to_le16(key->conf.keyidx);

	/* PN = PN + 1 */
@@ -916,90 +870,40 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)

	bip_aad(skb, aad);

	/* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
	 */
	if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
			       skb->data + 24, skb->len - 24, mmie->mic,
			       IEEE80211_CMAC_256_MIC_LEN))
			       skb->data + 24, skb->len - 24,
			       mmie->mic, mic_len))
		return TX_DROP;

	return TX_CONTINUE;
}

ieee80211_rx_result
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx,
				  unsigned int mic_len)
{
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	struct ieee80211_key *key = rx->key;
	struct ieee80211_mmie *mmie;
	u8 aad[20], mic[8], ipn[6];
	struct ieee80211_mmie_var *mmie;
	size_t mmie_len;
	u8 aad[20], mic[IEEE80211_CMAC_256_MIC_LEN], ipn[6];
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;

	if (!ieee80211_is_mgmt(hdr->frame_control))
		return RX_CONTINUE;

	/* management frames are already linear */

	if (skb->len < 24 + sizeof(*mmie))
		return RX_DROP_U_SHORT_CMAC;

	mmie = (struct ieee80211_mmie *)
		(skb->data + skb->len - sizeof(*mmie));
	if (mmie->element_id != WLAN_EID_MMIE ||
	    mmie->length != sizeof(*mmie) - 2)
		return RX_DROP_U_BAD_MMIE; /* Invalid MMIE */

	bip_ipn_swap(ipn, mmie->sequence_number);

	if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
		key->u.aes_cmac.replays++;
		return RX_DROP_U_REPLAY;
	}

	if (!(status->flag & RX_FLAG_DECRYPTED)) {
		/* hardware didn't decrypt/verify MIC */
		bip_aad(skb, aad);
		if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
				       skb->data + 24, skb->len - 24, mic,
				       IEEE80211_CMAC_128_MIC_LEN))
			return RX_DROP_U_DECRYPT_FAIL;
		if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
			key->u.aes_cmac.icverrors++;
			return RX_DROP_U_MIC_FAIL;
		}
	}

	memcpy(key->u.aes_cmac.rx_pn, ipn, 6);

	/* Remove MMIE */
	skb_trim(skb, skb->len - sizeof(*mmie));

	return RX_CONTINUE;
}

ieee80211_rx_result
ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
{
	struct sk_buff *skb = rx->skb;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	struct ieee80211_key *key = rx->key;
	struct ieee80211_mmie_16 *mmie;
	u8 aad[20], mic[16], ipn[6];
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;

	if (!ieee80211_is_mgmt(hdr->frame_control))
		return RX_CONTINUE;
	mmie_len = sizeof(*mmie) + mic_len;

	/* management frames are already linear */

	if (skb->len < 24 + sizeof(*mmie))
		return RX_DROP_U_SHORT_CMAC256;
	if (skb->len < 24 + mmie_len)
		return mic_len == IEEE80211_CMAC_128_MIC_LEN ?
			RX_DROP_U_SHORT_CMAC : RX_DROP_U_SHORT_CMAC256;

	mmie = (struct ieee80211_mmie_16 *)
		(skb->data + skb->len - sizeof(*mmie));
	mmie = (struct ieee80211_mmie_var *)(skb->data + skb->len - mmie_len);
	if (mmie->element_id != WLAN_EID_MMIE ||
	    mmie->length != sizeof(*mmie) - 2)
	    mmie->length != mmie_len - 2)
		return RX_DROP_U_BAD_MMIE; /* Invalid MMIE */

	bip_ipn_swap(ipn, mmie->sequence_number);
@@ -1013,10 +917,10 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
		/* hardware didn't decrypt/verify MIC */
		bip_aad(skb, aad);
		if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
				       skb->data + 24, skb->len - 24, mic,
				       IEEE80211_CMAC_256_MIC_LEN))
				       skb->data + 24, skb->len - 24,
				       mic, mic_len))
			return RX_DROP_U_DECRYPT_FAIL;
		if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
		if (crypto_memneq(mic, mmie->mic, mic_len)) {
			key->u.aes_cmac.icverrors++;
			return RX_DROP_U_MIC_FAIL;
		}
@@ -1025,7 +929,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
	memcpy(key->u.aes_cmac.rx_pn, ipn, 6);

	/* Remove MMIE */
	skb_trim(skb, skb->len - sizeof(*mmie));
	skb_trim(skb, skb->len - mmie_len);

	return RX_CONTINUE;
}
+4 −6
Original line number Diff line number Diff line
@@ -29,13 +29,11 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
			      unsigned int mic_len);

ieee80211_tx_result
ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);
ieee80211_tx_result
ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx);
ieee80211_rx_result
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx,
				  unsigned int mic_len);
ieee80211_rx_result
ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx);
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx,
				  unsigned int mic_len);
ieee80211_tx_result
ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx);
ieee80211_rx_result