hostapd/wlantest/bip.c
Jouni Malinen 9231c2476f wlantest: Fix bip_protect() memory allocation
The addition operator is of higher precedence than the ternary
conditional and the construction here needs to use parentheses to
calculate the buffer length properly when generating test frames with
BIP protection.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2016-03-14 18:42:46 +02:00

133 lines
3.1 KiB
C

/*
* BIP
* Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "crypto/aes_wrap.h"
#include "wlantest.h"
u8 * bip_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len,
u8 *ipn, int keyid, size_t *prot_len)
{
u8 *prot, *pos, *buf;
u8 mic[16];
u16 fc;
struct ieee80211_hdr *hdr;
size_t plen;
plen = len + (igtk_len == 32 ? 26 : 18);
prot = os_malloc(plen);
if (prot == NULL)
return NULL;
os_memcpy(prot, frame, len);
pos = prot + len;
*pos++ = WLAN_EID_MMIE;
*pos++ = igtk_len == 32 ? 24 : 16;
WPA_PUT_LE16(pos, keyid);
pos += 2;
os_memcpy(pos, ipn, 6);
pos += 6;
os_memset(pos, 0, igtk_len == 32 ? 16 : 8); /* MIC */
buf = os_malloc(plen + 20 - 24);
if (buf == NULL) {
os_free(prot);
return NULL;
}
/* BIP AAD: FC(masked) A1 A2 A3 */
hdr = (struct ieee80211_hdr *) frame;
fc = le_to_host16(hdr->frame_control);
fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
WPA_PUT_LE16(buf, fc);
os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
os_memcpy(buf + 20, prot + 24, plen - 24);
wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, plen + 20 - 24);
/* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
if (omac1_aes_128(igtk, buf, plen + 20 - 24, mic) < 0) {
os_free(prot);
os_free(buf);
return NULL;
}
os_free(buf);
os_memcpy(pos, mic, igtk_len == 32 ? 16 : 8);
wpa_hexdump(MSG_DEBUG, "BIP MMIE MIC", pos, igtk_len == 32 ? 16 : 8);
*prot_len = plen;
return prot;
}
u8 * bip_gmac_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len,
u8 *ipn, int keyid, size_t *prot_len)
{
u8 *prot, *pos, *buf;
u16 fc;
struct ieee80211_hdr *hdr;
size_t plen;
u8 nonce[12], *npos;
plen = len + 26;
prot = os_malloc(plen);
if (prot == NULL)
return NULL;
os_memcpy(prot, frame, len);
pos = prot + len;
*pos++ = WLAN_EID_MMIE;
*pos++ = 24;
WPA_PUT_LE16(pos, keyid);
pos += 2;
os_memcpy(pos, ipn, 6);
pos += 6;
os_memset(pos, 0, 16); /* MIC */
buf = os_malloc(plen + 20 - 24);
if (buf == NULL) {
os_free(prot);
return NULL;
}
/* BIP AAD: FC(masked) A1 A2 A3 */
hdr = (struct ieee80211_hdr *) frame;
fc = le_to_host16(hdr->frame_control);
fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
WPA_PUT_LE16(buf, fc);
os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
os_memcpy(buf + 20, prot + 24, plen - 24);
wpa_hexdump(MSG_MSGDUMP, "BIP-GMAC: AAD|Body(masked)",
buf, plen + 20 - 24);
/* Nonce: A2 | IPN */
os_memcpy(nonce, hdr->addr2, ETH_ALEN);
npos = nonce + ETH_ALEN;
*npos++ = ipn[5];
*npos++ = ipn[4];
*npos++ = ipn[3];
*npos++ = ipn[2];
*npos++ = ipn[1];
*npos++ = ipn[0];
wpa_hexdump(MSG_EXCESSIVE, "BIP-GMAC: Nonce", nonce, sizeof(nonce));
/* MIC = AES-GMAC(AAD || Frame Body(masked)) */
if (aes_gmac(igtk, igtk_len, nonce, sizeof(nonce),
buf, plen + 20 - 24, pos) < 0) {
os_free(prot);
os_free(buf);
return NULL;
}
os_free(buf);
wpa_hexdump(MSG_DEBUG, "BIP-GMAC MMIE MIC", pos, 16);
*prot_len = plen;
return prot;
}