mac80211: Update BIP to support Beacon frames

When BIP is used to protect Beacon frames, the Timestamp field is masked
to zero. Otherwise, the BIP processing is identical to the way it was
already used with group-addressed Robust Management frames.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Link: https://lore.kernel.org/r/20200222132548.20835-4-jouni@codeaurora.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Jouni Malinen 2020-02-22 15:25:45 +02:00 committed by Johannes Berg
parent e5473e80d4
commit 2d5d4b0a6d
2 changed files with 37 additions and 8 deletions

View File

@ -26,12 +26,20 @@ void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
{ {
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;
desc->tfm = tfm; desc->tfm = tfm;
crypto_shash_init(desc); crypto_shash_init(desc);
crypto_shash_update(desc, aad, AAD_LEN); crypto_shash_update(desc, aad, AAD_LEN);
crypto_shash_update(desc, data, data_len - CMAC_TLEN); fc = (const __le16 *)aad;
if (ieee80211_is_beacon(*fc)) {
/* mask Timestamp field to zero */
crypto_shash_update(desc, zero, 8);
crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN);
} else {
crypto_shash_update(desc, data, data_len - CMAC_TLEN);
}
crypto_shash_finup(desc, zero, CMAC_TLEN, out); crypto_shash_finup(desc, zero, CMAC_TLEN, out);
memcpy(mic, out, CMAC_TLEN); memcpy(mic, out, CMAC_TLEN);
@ -41,12 +49,21 @@ void 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)
{ {
SHASH_DESC_ON_STACK(desc, tfm); SHASH_DESC_ON_STACK(desc, tfm);
const __le16 *fc;
desc->tfm = tfm; desc->tfm = tfm;
crypto_shash_init(desc); crypto_shash_init(desc);
crypto_shash_update(desc, aad, AAD_LEN); crypto_shash_update(desc, aad, AAD_LEN);
crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); fc = (const __le16 *)aad;
if (ieee80211_is_beacon(*fc)) {
/* mask Timestamp field to zero */
crypto_shash_update(desc, zero, 8);
crypto_shash_update(desc, data + 8,
data_len - 8 - CMAC_TLEN_256);
} else {
crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
}
crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic); crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
} }

View File

@ -17,10 +17,11 @@
int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
const u8 *data, size_t data_len, u8 *mic) const u8 *data, size_t data_len, u8 *mic)
{ {
struct scatterlist sg[4]; struct scatterlist sg[5];
u8 *zero, *__aad, iv[AES_BLOCK_SIZE]; u8 *zero, *__aad, iv[AES_BLOCK_SIZE];
struct aead_request *aead_req; struct aead_request *aead_req;
int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
const __le16 *fc;
if (data_len < GMAC_MIC_LEN) if (data_len < GMAC_MIC_LEN)
return -EINVAL; return -EINVAL;
@ -33,11 +34,22 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
__aad = zero + GMAC_MIC_LEN; __aad = zero + GMAC_MIC_LEN;
memcpy(__aad, aad, GMAC_AAD_LEN); memcpy(__aad, aad, GMAC_AAD_LEN);
sg_init_table(sg, 4); fc = (const __le16 *)aad;
sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN); if (ieee80211_is_beacon(*fc)) {
sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN); /* mask Timestamp field to zero */
sg_set_buf(&sg[2], zero, GMAC_MIC_LEN); sg_init_table(sg, 5);
sg_set_buf(&sg[3], mic, GMAC_MIC_LEN); sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
sg_set_buf(&sg[1], zero, 8);
sg_set_buf(&sg[2], data + 8, data_len - 8 - GMAC_MIC_LEN);
sg_set_buf(&sg[3], zero, GMAC_MIC_LEN);
sg_set_buf(&sg[4], mic, GMAC_MIC_LEN);
} else {
sg_init_table(sg, 4);
sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
}
memcpy(iv, nonce, GMAC_NONCE_LEN); memcpy(iv, nonce, GMAC_NONCE_LEN);
memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN); memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);