mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
wifi: mac80211: fix CMAC functions not handling errors
The called hash functions could fail thus we should check return values.
Fixes: 26717828b7 ("mac80211: aes-cmac: switch to shash CMAC driver")
Signed-off-by: Chien Wong <m@xv97.com>
Link: https://patch.msgid.link/20251113140511.48658-2-m@xv97.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
799e98708f
commit
353cda30d3
@@ -22,50 +22,77 @@
|
|||||||
|
|
||||||
static const u8 zero[CMAC_TLEN_256];
|
static const u8 zero[CMAC_TLEN_256];
|
||||||
|
|
||||||
void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
|
int ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
|
||||||
const u8 *data, size_t data_len, u8 *mic)
|
const u8 *data, size_t data_len, u8 *mic)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
SHASH_DESC_ON_STACK(desc, tfm);
|
SHASH_DESC_ON_STACK(desc, tfm);
|
||||||
u8 out[AES_BLOCK_SIZE];
|
u8 out[AES_BLOCK_SIZE];
|
||||||
const __le16 *fc;
|
const __le16 *fc;
|
||||||
|
|
||||||
desc->tfm = tfm;
|
desc->tfm = tfm;
|
||||||
|
|
||||||
crypto_shash_init(desc);
|
err = crypto_shash_init(desc);
|
||||||
crypto_shash_update(desc, aad, AAD_LEN);
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = crypto_shash_update(desc, aad, AAD_LEN);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
fc = (const __le16 *)aad;
|
fc = (const __le16 *)aad;
|
||||||
if (ieee80211_is_beacon(*fc)) {
|
if (ieee80211_is_beacon(*fc)) {
|
||||||
/* mask Timestamp field to zero */
|
/* mask Timestamp field to zero */
|
||||||
crypto_shash_update(desc, zero, 8);
|
err = crypto_shash_update(desc, zero, 8);
|
||||||
crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN);
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = crypto_shash_update(desc, data + 8,
|
||||||
|
data_len - 8 - CMAC_TLEN);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
} else {
|
} else {
|
||||||
crypto_shash_update(desc, data, data_len - CMAC_TLEN);
|
err = crypto_shash_update(desc, data,
|
||||||
|
data_len - CMAC_TLEN);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
crypto_shash_finup(desc, zero, CMAC_TLEN, out);
|
err = crypto_shash_finup(desc, zero, CMAC_TLEN, out);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
memcpy(mic, out, CMAC_TLEN);
|
memcpy(mic, out, CMAC_TLEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
|
int ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
|
||||||
const u8 *data, size_t data_len, u8 *mic)
|
const u8 *data, size_t data_len, u8 *mic)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
SHASH_DESC_ON_STACK(desc, tfm);
|
SHASH_DESC_ON_STACK(desc, tfm);
|
||||||
const __le16 *fc;
|
const __le16 *fc;
|
||||||
|
|
||||||
desc->tfm = tfm;
|
desc->tfm = tfm;
|
||||||
|
|
||||||
crypto_shash_init(desc);
|
err = crypto_shash_init(desc);
|
||||||
crypto_shash_update(desc, aad, AAD_LEN);
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = crypto_shash_update(desc, aad, AAD_LEN);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
fc = (const __le16 *)aad;
|
fc = (const __le16 *)aad;
|
||||||
if (ieee80211_is_beacon(*fc)) {
|
if (ieee80211_is_beacon(*fc)) {
|
||||||
/* mask Timestamp field to zero */
|
/* mask Timestamp field to zero */
|
||||||
crypto_shash_update(desc, zero, 8);
|
err = crypto_shash_update(desc, zero, 8);
|
||||||
crypto_shash_update(desc, data + 8,
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = crypto_shash_update(desc, data + 8,
|
||||||
data_len - 8 - CMAC_TLEN_256);
|
data_len - 8 - CMAC_TLEN_256);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
} else {
|
} else {
|
||||||
crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
|
err = crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
|
return crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
|
struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
|
struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
|
||||||
size_t key_len);
|
size_t key_len);
|
||||||
void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
|
int ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
|
||||||
const u8 *data, size_t data_len, u8 *mic);
|
const u8 *data, size_t data_len, u8 *mic);
|
||||||
void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
|
int ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
|
||||||
const u8 *data, size_t data_len, u8 *mic);
|
const u8 *data, size_t data_len, u8 *mic);
|
||||||
void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm);
|
void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm);
|
||||||
|
|
||||||
|
|||||||
@@ -869,8 +869,9 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
|
|||||||
/*
|
/*
|
||||||
* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
|
* MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
|
||||||
*/
|
*/
|
||||||
ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
|
if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
|
||||||
skb->data + 24, skb->len - 24, mmie->mic);
|
skb->data + 24, skb->len - 24, mmie->mic))
|
||||||
|
return TX_DROP;
|
||||||
|
|
||||||
return TX_CONTINUE;
|
return TX_CONTINUE;
|
||||||
}
|
}
|
||||||
@@ -916,8 +917,9 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
|
|||||||
|
|
||||||
/* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
|
/* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
|
||||||
*/
|
*/
|
||||||
ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
|
if (ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
|
||||||
skb->data + 24, skb->len - 24, mmie->mic);
|
skb->data + 24, skb->len - 24, mmie->mic))
|
||||||
|
return TX_DROP;
|
||||||
|
|
||||||
return TX_CONTINUE;
|
return TX_CONTINUE;
|
||||||
}
|
}
|
||||||
@@ -956,8 +958,9 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
|
|||||||
if (!(status->flag & RX_FLAG_DECRYPTED)) {
|
if (!(status->flag & RX_FLAG_DECRYPTED)) {
|
||||||
/* hardware didn't decrypt/verify MIC */
|
/* hardware didn't decrypt/verify MIC */
|
||||||
bip_aad(skb, aad);
|
bip_aad(skb, aad);
|
||||||
ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
|
if (ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
|
||||||
skb->data + 24, skb->len - 24, mic);
|
skb->data + 24, skb->len - 24, mic))
|
||||||
|
return RX_DROP_U_DECRYPT_FAIL;
|
||||||
if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
||||||
key->u.aes_cmac.icverrors++;
|
key->u.aes_cmac.icverrors++;
|
||||||
return RX_DROP_U_MIC_FAIL;
|
return RX_DROP_U_MIC_FAIL;
|
||||||
@@ -1006,8 +1009,9 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
|
|||||||
if (!(status->flag & RX_FLAG_DECRYPTED)) {
|
if (!(status->flag & RX_FLAG_DECRYPTED)) {
|
||||||
/* hardware didn't decrypt/verify MIC */
|
/* hardware didn't decrypt/verify MIC */
|
||||||
bip_aad(skb, aad);
|
bip_aad(skb, aad);
|
||||||
ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
|
if (ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
|
||||||
skb->data + 24, skb->len - 24, mic);
|
skb->data + 24, skb->len - 24, mic))
|
||||||
|
return RX_DROP_U_DECRYPT_FAIL;
|
||||||
if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
||||||
key->u.aes_cmac.icverrors++;
|
key->u.aes_cmac.icverrors++;
|
||||||
return RX_DROP_U_MIC_FAIL;
|
return RX_DROP_U_MIC_FAIL;
|
||||||
|
|||||||
Reference in New Issue
Block a user