From patchwork Thu Jan 11 01:20:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Henry Ptasinski X-Patchwork-Id: 1885292 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=4fYh+eta; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=e78com.com header.i=@e78com.com header.a=rsa-sha256 header.s=google header.b=KqaSPZV/; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T9RjT6Xscz1yPm for ; Thu, 11 Jan 2024 12:22:21 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=UBaUcZgiSe4LQQrUTnw5H3mzbKqKMX0x3X+3c9aEvzc=; b=4fYh+etaHMYJO6 OTgNtVtQNkVZgPk4ROQbpiWg/d8JZJ6xbwnu6lMEkTwsu12hSAiMSp3tCdtD9NVeXlHqj/VTL0Eir SjCWWpRv4jNd2fX5DTEDgyBaJAq+xOXmYhN0C/APbtbWNlBi+CiUmPdgIgJMs8oe9ly3dj4puRHQj RrlCX8U+BlG9R1ts6zrVXKLjNCbOp1q51bgKvMtpxle+miyMbqFhMUvHAE/3UI4iMiRj3Ry/en0Km gN8XVN2+xmwd0VAfMZ7YfTwJiJUH7daJGmieogk0eyqD4/4D3LkFYJ1gOSGETbDO85xklmKk2GW5U hSYggluD8htKA8LlTJ5Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rNjkw-00FCqu-1T; Thu, 11 Jan 2024 01:21:14 +0000 Received: from mail-ot1-x32b.google.com ([2607:f8b0:4864:20::32b]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1rNjkq-00FCoe-2C for hostap@lists.infradead.org; Thu, 11 Jan 2024 01:21:12 +0000 Received: by mail-ot1-x32b.google.com with SMTP id 46e09a7af769-6ddeb7b4366so1177346a34.2 for ; Wed, 10 Jan 2024 17:21:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=e78com.com; s=google; t=1704936066; x=1705540866; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=uvK6wlr7grnMv69ieU3KvtA3sqQr7MoFlXUJEsXeaC0=; b=KqaSPZV/lxAwQIIgPedf8B1ZvqZdeWGkFwLQqbX06kuLLXY/9rzg0orv5gqL7iVStS tnBRNCnZQ+kDlc3ZBDRbUFKgHFGS0v85rfM7S9zfVR6cItjn8p7sGH1jToTy1MJTHGmq LuokfQ18CzMKtF7uvZ4RSFGYT8T9Ovvut5gnsfbxlagRiPiZx2H/uiYq6vkj1j6C5oqg wGIrZ0795t62EF6bAW+F2coXKwebTXDp9blc2UWL+UrE2vmEzfbtdD8StMn5ztmhqSZM EOlTfnmdV6HqC8vsHN51LAggrWcVpKQNJRiUhXVBUl4eKK9CUbgk0MRhRbS+2yWds5c5 znYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704936066; x=1705540866; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=uvK6wlr7grnMv69ieU3KvtA3sqQr7MoFlXUJEsXeaC0=; b=VdkdcD/LV9NbfhR4mYss+NQw0kWv1F3Y2wEqfBkl24RgJj4pMmNq5jPsyf2UQN6Ghj 5mGxNLy+nkpjfyZewxVfGTk3inTvYfZE6g4uhlUMgLxPUakfaaKH6Umw27vl+wxanbwK lIoiAt3v4Ln99GLx6uHM5irNr/VMGshc/Vu4xH0yqLXJFiHq6163XyDj6GDL6uOWVC5f qFUD3BSYlYA0gq9LePnWjjae5JzTV7faaceMg1S7uKzrTdOZZkrRlH03iG+BRPeMf9aG yhaTMAWFGt//mLcsppsHlt60OSiIBWgEW/5eAPgngeEUHIMJrSW0oZB4zqa4HblTnL9k 6ViQ== X-Gm-Message-State: AOJu0Yy3ckzTM/T2C0hRqOdCcvWHM2VO1/ILQghZK5vukeoT3gAu+Qg5 EzZ3xIDm+DZrZITx+7P+FUkkkPKT9I+z9HA9Xg6GOYQnTuc= X-Google-Smtp-Source: AGHT+IGlQjXRj6hQIUKw60xKVpiymHL4UOu825nTYqKYJqbB25WApzjMw38AdgwJmW1wp8Az/iNfiQ== X-Received: by 2002:a05:6808:1186:b0:3bb:c76f:f82a with SMTP id j6-20020a056808118600b003bbc76ff82amr417671oil.64.1704936066105; Wed, 10 Jan 2024 17:21:06 -0800 (PST) Received: from gigi.lan ([73.70.155.158]) by smtp.gmail.com with ESMTPSA id a14-20020a056a000c8e00b006d9bf45436asm4084267pfv.48.2024.01.10.17.21.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Jan 2024 17:21:05 -0800 (PST) From: Henry Ptasinski To: hostap@lists.infradead.org Cc: Henry Ptasinski , Andrew Pope , David Goodall Subject: [PATCH] wlantest: Add test vectors for S1G BIP Date: Wed, 10 Jan 2024 17:20:55 -0800 Message-Id: <20240111012055.13636-1-henry@e78com.com> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240110_172108_835462_A8AB822D X-CRM114-Status: GOOD ( 23.11 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: - CMAC and GMAC modes - 128-bit and 256-bit modes - normal BIP and BIP using BCE - test vectors with minimum and optional additional header elements in S1G beacon frames - S1G Beacon Compatibility ele [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:32b listed in] [list.dnswl.org] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org - CMAC and GMAC modes - 128-bit and 256-bit modes - normal BIP and BIP using BCE - test vectors with minimum and optional additional header elements in S1G beacon frames - S1G Beacon Compatibility element in some cases, no other beacon body components Signed-off-by: Henry Ptasinski Signed-off-by: Andrew Pope Signed-off-by: David Goodall --- src/common/ieee802_11_defs.h | 36 +++ wlantest/bip.c | 212 +++++++++++++ wlantest/test_vectors.c | 560 ++++++++++++++++++++++++++++++++++- wlantest/wlantest.h | 4 + 4 files changed, 811 insertions(+), 1 deletion(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 12137dcf4..764bc002b 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -24,6 +24,13 @@ #define WLAN_FC_ISWEP 0x4000 #define WLAN_FC_HTC 0x8000 +#define WLAN_FC_S1G_BEACON_NEXT_TBTT 0x0100 +#define WLAN_FC_S1G_BEACON_COMP_SSID 0x0200 +#define WLAN_FC_S1G_BEACON_ANO 0x0400 +#define WLAN_FC_S1G_BEACON_BSS_BW 0x3800 +#define WLAN_FC_S1G_BEACON_SECURITY 0x4000 +#define WLAN_FC_S1G_BEACON_AP_PM 0x8000 + #define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) #define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) @@ -36,6 +43,7 @@ #define WLAN_FC_TYPE_MGMT 0 #define WLAN_FC_TYPE_CTRL 1 #define WLAN_FC_TYPE_DATA 2 +#define WLAN_FC_TYPE_EXT 3 /* management */ #define WLAN_FC_STYPE_ASSOC_REQ 0 @@ -77,6 +85,10 @@ #define WLAN_FC_STYPE_QOS_CFPOLL 14 #define WLAN_FC_STYPE_QOS_CFACKPOLL 15 +/* extension */ +#define WLAN_FC_STYPE_DMG_BEACON 0 +#define WLAN_FC_STYPE_S1G_BEACON 1 + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -954,6 +966,21 @@ struct ieee80211_hdr { #define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) +struct ieee80211_hdr_s1g_beacon { + le16 frame_control; + le16 duration_id; + u8 sa[6]; + u8 timestamp[4]; + u8 change_seq[1]; + /* followed by: + * 'u8 next_tbtt[3];' if the Next TBTT Present field in the Frame Control field is 1 + * 'u8 compressed_ssid[4];' if the Compressed SSID Present field in the Frame Control is 1 + * 'u8 ano[1];' if the ANO field in the Frame Control field is 1 + */ +} STRUCT_PACKED; + +#define IEEE80211_HDRLEN_S1G_BEACON (sizeof(struct ieee80211_hdr_s1g_beacon)) + #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) struct ieee80211_mgmt { @@ -3007,6 +3034,15 @@ struct ieee80211_neighbor_ap_info { u8 data[0]; } STRUCT_PACKED; +/* S1G Beacon Compatibility element */ +struct ieee80211_s1g_beacon_compat { + u8 element_id; + u8 length; + le16 compat_info; + le16 beacon_interval; + le32 tsf_completion; +} STRUCT_PACKED; + #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ diff --git a/wlantest/bip.c b/wlantest/bip.c index c73a15c98..7989ae9e5 100644 --- a/wlantest/bip.c +++ b/wlantest/bip.c @@ -67,6 +67,108 @@ u8 * bip_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, } +#define MME_LEN_LESS_MIC 10 +#define MIC_ELEM_LEN_LESS_MIC 2 + +u8 * bip_protect_s1g_beacon(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, + u8 *ipn, int keyid, int bce, size_t *prot_len) +{ + u8 *prot, *pos, *buf; + u8 mic[16]; + u16 fc; + struct ieee80211_hdr_s1g_beacon *hdr; + struct ieee80211_s1g_beacon_compat *bc; + size_t plen, hdr_add_len = 0, bce_add_len = 0, mic_len, element_len, buf_len; + wpa_debug_level = MSG_EXCESSIVE; + + mic_len = igtk_len == 32 ? 16 : 8; + if (bce) { + element_len = MIC_ELEM_LEN_LESS_MIC + mic_len; + } else { + element_len = MME_LEN_LESS_MIC + mic_len; + } + plen = len + element_len; /* add element length */ + prot = os_malloc(plen); + if (prot == NULL) + return NULL; + os_memcpy(prot, frame, len); + pos = prot + len; + /* Add MME/MIC element to the end of the frame */ + if (bce) { + bce_add_len = 6; /* AAD increases by 6 bytes for BCE */ + *pos++ = WLAN_EID_MIC; /* Element ID */ + *pos++ = element_len - 2; /* Length field */ + } else { + *pos++ = WLAN_EID_MMIE; /* Element ID */ + *pos++ = element_len - 2; /* Length field */ + WPA_PUT_LE16(pos, keyid); /* KeyID */ + pos += 2; + os_memcpy(pos, ipn, 6); /* BIPN */ + pos += 6; + } + os_memset(pos, 0, mic_len); /* MIC */ + + buf_len = plen - 6 + bce_add_len; /* Duration (2) and Timestamp (4) are omitted from AAD, BIPN (6) is added if BCE is used */ + buf = os_malloc(buf_len); + if (buf == NULL) { + os_free(prot); + return NULL; + } + + /* BIP AAD: FC SA ChangeSeq NextTBTT(if present) CompressedSSID(if present) ANO(if present), BIPN(if using BCE) */ + hdr = (struct ieee80211_hdr_s1g_beacon *) frame; + fc = le_to_host16(hdr->frame_control); + if ((WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_EXT) || (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_S1G_BEACON)) { + wpa_printf(MSG_ERROR, "Frame is not an S1G Beacon"); + os_free(prot); + os_free(buf); + return NULL; + } + WPA_PUT_LE16(buf, fc); + os_memcpy(buf + 2, hdr->sa, ETH_ALEN); + os_memcpy(buf + 8, hdr->change_seq, 1); + if (fc & WLAN_FC_S1G_BEACON_NEXT_TBTT) + hdr_add_len += 3; + if (fc & WLAN_FC_S1G_BEACON_COMP_SSID) + hdr_add_len += 4; + if (fc & WLAN_FC_S1G_BEACON_ANO) + hdr_add_len += 1; + os_memcpy(buf + 9, prot + IEEE80211_HDRLEN_S1G_BEACON, hdr_add_len); + if (bce) { + os_memcpy(buf + 9 + hdr_add_len, ipn, bce_add_len); + } + os_memcpy(buf + 9 + hdr_add_len + bce_add_len, prot + IEEE80211_HDRLEN_S1G_BEACON + hdr_add_len, plen - (IEEE80211_HDRLEN_S1G_BEACON + hdr_add_len)); + /* The S1G Beacon Compatibility element, when present, is the first element in the S1G Beacon frame body */ + if (len >= IEEE80211_HDRLEN_S1G_BEACON + hdr_add_len + sizeof(struct ieee80211_s1g_beacon_compat)) { + bc = (struct ieee80211_s1g_beacon_compat *) (buf + 9 + hdr_add_len + bce_add_len); + if (bc->element_id == WLAN_EID_S1G_BCN_COMPAT) { + wpa_printf(MSG_DEBUG, "S1G Beacon Compatibility element found, masking TSF Completion field"); + os_memset(&(bc->tsf_completion), 0, sizeof(bc->tsf_completion)); + if ((bce) && ( (keyid - 6) != ((bc->compat_info & 0x80) >> 7))) { + wpa_printf(MSG_ERROR, "keyid does not match BIGTK Key ID Index in S1G Beacon Compatibility element"); + os_free(prot); + os_free(buf); + return NULL; + } + } + } + wpa_hexdump(MSG_MSGDUMP, "S1G BIP-CMAC AAD|Body(masked)", buf, buf_len); + /* MIC = L(AES-128-CMAC(AAD || Frame Body), 0, 64) */ + if (omac1_aes_128(igtk, buf, buf_len, mic) < 0) { + os_free(prot); + os_free(buf); + return NULL; + } + os_free(buf); + + os_memcpy(pos, mic, mic_len); + wpa_hexdump(MSG_DEBUG, "S1G BIP-CMAC MIC", pos, mic_len); + + *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) { @@ -131,3 +233,113 @@ u8 * bip_gmac_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, *prot_len = plen; return prot; } + + +u8 * bip_gmac_protect_s1g_beacon(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, + u8 *ipn, int keyid, int bce, size_t *prot_len) +{ + u8 *prot, *pos, *buf; + u16 fc; + struct ieee80211_hdr_s1g_beacon *hdr; + struct ieee80211_s1g_beacon_compat *bc; + size_t plen, hdr_add_len = 0, bce_add_len = 0, mic_len, element_len, buf_len; + u8 nonce[12], *npos; + wpa_debug_level = MSG_EXCESSIVE; + + mic_len = 16; + if (bce) { + element_len = MIC_ELEM_LEN_LESS_MIC + mic_len; + } else { + element_len = MME_LEN_LESS_MIC + mic_len; + } + plen = len + element_len; /* add element length */ + prot = os_malloc(plen); + if (prot == NULL) + return NULL; + os_memcpy(prot, frame, len); + pos = prot + len; + /* Add MME/MIC element to the end of the frame */ + if (bce) { + bce_add_len = 6; + *pos++ = WLAN_EID_MIC; /* Element ID */ + *pos++ = element_len - 2; /* Length field */ + } else { + *pos++ = WLAN_EID_MMIE; /* Element ID */ + *pos++ = element_len - 2; /* Length field */ + WPA_PUT_LE16(pos, keyid); /* KeyID */ + pos += 2; + os_memcpy(pos, ipn, 6); /* BIPN */ + pos += 6; + } + os_memset(pos, 0, mic_len); /* MIC */ + + buf_len = plen - 6 + bce_add_len; /* Duration (2) and Timestamp (4) are omitted from AAD, BIPN (6) is added if BCE is used */ + buf = os_malloc(buf_len); + if (buf == NULL) { + os_free(prot); + return NULL; + } + + /* BIP AAD: FC SA ChangeSeq NextTBTT(if present) CompressedSSID(if present) ANO(if present) */ + hdr = (struct ieee80211_hdr_s1g_beacon *) frame; + fc = le_to_host16(hdr->frame_control); + if ((WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_EXT) || (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_S1G_BEACON)) { + wpa_printf(MSG_ERROR, "Frame is not an S1G Beacon"); + os_free(prot); + os_free(buf); + return NULL; + } + WPA_PUT_LE16(buf, fc); + os_memcpy(buf + 2, hdr->sa, ETH_ALEN); + os_memcpy(buf + 8, hdr->change_seq, 1); + if (fc & WLAN_FC_S1G_BEACON_NEXT_TBTT) + hdr_add_len += 3; + if (fc & WLAN_FC_S1G_BEACON_COMP_SSID) + hdr_add_len += 4; + if (fc & WLAN_FC_S1G_BEACON_ANO) + hdr_add_len += 1; + os_memcpy(buf + 9, prot + IEEE80211_HDRLEN_S1G_BEACON, hdr_add_len); + if (bce) { + os_memcpy(buf + 9 + hdr_add_len, ipn, bce_add_len); + } + os_memcpy(buf + 9 + hdr_add_len + bce_add_len, prot + IEEE80211_HDRLEN_S1G_BEACON + hdr_add_len, plen - (IEEE80211_HDRLEN_S1G_BEACON + hdr_add_len)); + /* The S1G Beacon Compatibility element, when present, is the first element in the S1G Beacon frame body */ + if (len >= IEEE80211_HDRLEN_S1G_BEACON + hdr_add_len + sizeof(struct ieee80211_s1g_beacon_compat)) { + bc = (struct ieee80211_s1g_beacon_compat *) (buf + 9 + hdr_add_len + bce_add_len); + if (bc->element_id == WLAN_EID_S1G_BCN_COMPAT) { + wpa_printf(MSG_DEBUG, "S1G Beacon Compatibility element found, masking TSF Completion field"); + os_memset(&(bc->tsf_completion), 0, sizeof(bc->tsf_completion)); + if ((bce) && ( (keyid - 6) != ((bc->compat_info & 0x80) >> 7))) { + wpa_printf(MSG_ERROR, "keyid does not match BIGTK Key ID Index in S1G Beacon Compatibility element"); + os_free(prot); + os_free(buf); + return NULL; + } + } + } + wpa_hexdump(MSG_MSGDUMP, "S1G BIP-GMAC AAD|Body(masked)", buf, buf_len); + + /* Nonce: SA | IPN */ + os_memcpy(nonce, hdr->sa, 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, "S1G BIP-GMAC Nonce", nonce, sizeof(nonce)); + + /* MIC = AES-GMAC(AAD || Frame Body) */ + if (aes_gmac(igtk, igtk_len, nonce, sizeof(nonce), buf, buf_len, pos) < 0) { + os_free(prot); + os_free(buf); + return NULL; + } + os_free(buf); + + wpa_hexdump(MSG_DEBUG, "S1G BIP-GMAC MIC", pos, 16); + + *prot_len = plen; + return prot; +} diff --git a/wlantest/test_vectors.c b/wlantest/test_vectors.c index f2517cb8c..464429636 100644 --- a/wlantest/test_vectors.c +++ b/wlantest/test_vectors.c @@ -381,6 +381,152 @@ static void test_vector_bip(void) } +static void test_vector_bip_s1g_beacon(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + // FC 2 Dur 2 SA 6 Time 4 CS 1 Next 0/3 Comp 0/4 ANO 0/1 + // FC: prot 2 type 2 subtype 4 next 1 comp 1 ano 1 bss bw 3 sec 1 ap pm 1 + // S1G Beacon, no extra header fields, S1G Beacon Compatibility element + u8 frame[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, + 0x08, 0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78 + }; + u8 *prot; + size_t prot_len; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-CMAC-128, no optional header fields, S1G Beacon Compatibility element in body\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 7, 0, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-CMAC-128"); + return; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + os_free(prot); +} + + +static void test_vector_bip_s1g_beacon_ext(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + // FC 2 Dur 2 SA 6 Time 4 CS 1 Next 0/3 Comp 0/4 ANO 0/1 + // FC: prot 2 type 2 subtype 4 next 1 comp 1 ano 1 bss bw 3 sec 1 ap pm 1 + // S1G Beacon, all possible extra header fields, no body fields + u8 frame[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u8 *prot; + size_t prot_len; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-CMAC-128, all optional header fields, no body elements\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 6, 0, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-CMAC-128"); + return; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + os_free(prot); +} + + +static void test_vector_bip_s1g_beacon_bce(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + // FC 2 Dur 2 SA 6 Time 4 CS 1 Next 0/3 Comp 0/4 ANO 0/1 + // FC: prot 2 type 2 subtype 4 next 1 comp 1 ano 1 bss bw 3 sec 1 ap pm 1 + // S1G Beacon, no extra header fields, S1G Beacon Compatibility element + u8 frame[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, + 0x08, 0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78 + }; + u8 *prot; + size_t prot_len; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-CMAC-128 using BCE, no optional header fields, S1G Beacon Compatibility element in body\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 7, 1, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP using BCE-CMAC-128"); + return; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + os_free(prot); +} + + +static void test_vector_bip_s1g_beacon_bce_ext(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + // FC 2 Dur 2 SA 6 Time 4 CS 1 Next 0/3 Comp 0/4 ANO 0/1 + // FC: prot 2 type 2 subtype 4 next 1 comp 1 ano 1 bss bw 3 sec 1 ap pm 1 + // S1G Beacon, all possible extra header fields, no body fields + u8 frame[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u8 *prot; + size_t prot_len; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-CMAC-128 using BCE, all optional header fields, no body elements\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 6, 1, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP using BCE-CMAC-128"); + return; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + os_free(prot); +} + + static void test_vector_ccmp_mgmt(void) { u8 tk[] = { 0x66, 0xed, 0x21, 0x04, 0x2f, 0x9f, 0x26, 0xd7, @@ -863,6 +1009,202 @@ static int test_vector_bip_gmac_128(void) } +static int test_vector_bip_gmac_128_s1g_beacon(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78 + }; + u8 res[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78, 0x4c, 0x18, 0x06, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa5, 0xb2, 0x42, 0xc1, 0xc1, + 0x1e, 0xab, 0x10, 0xc5, 0xa4, 0xe8, 0xb9, 0x53, + 0x66, 0x19, 0x38 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-128, no optional header fields, S1G Beacon Compatibility element in body\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 6, 0, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-GMAC-128"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-128 test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_128_s1g_beacon_ext(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u8 res[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, + 0x18, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x39, 0xd0, 0x0c, 0xc2, 0xee, 0xd7, 0x4c, + 0x2a, 0xb7, 0x41, 0xcc, 0xf8, 0x08, 0x9b, 0x5b, + 0x08 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-128, all optional header fields, no body elements\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 7, 0, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-GMAC-128"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-128 test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_128_s1g_beacon_bce(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78 + }; + u8 res[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78, 0x8c, 0x10, 0xa2, 0x5b, 0x7e, 0x67, 0x76, + 0xf0, 0x11, 0x57, 0xa4, 0xfb, 0x4a, 0x2d, 0x66, + 0xd0, 0x17, 0x66 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-128 using BCE, no optional header fields, S1G Beacon Compatibility element in body\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 6, 1, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-GMAC-128 using BCE"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-128 using BCE test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_128_s1g_beacon_bce_ext(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u8 res[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, + 0x10, 0x86, 0xdd, 0xb6, 0xc0, 0x56, 0x21, 0x30, + 0x9d, 0x3e, 0xbd, 0x25, 0x96, 0x67, 0x5b, 0xdd, + 0xc3 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-128 using BCE, all optional header fields, no body elements\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 7, 1, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-GMAC-128 using BCE"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-128 using BCE test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + static int test_vector_bip_gmac_256(void) { u8 igtk[] = { @@ -906,7 +1248,211 @@ static int test_vector_bip_gmac_256(void) wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { - wpa_printf(MSG_ERROR, "BIP-GMAC-128 test vector mismatch"); + wpa_printf(MSG_ERROR, "BIP-GMAC-256 test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_256_s1g_beacon(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, + 0x08, 0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78 + }; + u8 res[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, + 0x08, 0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78, 0x4c, 0x18, 0x07, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x33, 0xa2, 0x6f, 0xc6, 0x7e, + 0xbf, 0xfd, 0xa0, 0xac, 0x9b, 0x29, 0xaa, 0x70, + 0xda, 0x3f, 0x51 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-256, no optional header fields, S1G Beacon Compatibility element in body\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 7, 0, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-GMAC-256"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-256 test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_256_s1g_beacon_ext(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u8 res[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, + 0x18, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x5f, 0xa0, 0xf4, 0x71, 0xdf, 0x73, + 0x9e, 0x61, 0x4d, 0xcf, 0x5d, 0xbb, 0x36, 0xf9, + 0x65 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-256, all optional header fields, no body elements\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 6, 0, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1B Beacon frame with BIP-GMAC-256"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-256 test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_256_s1g_beacon_bce(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, + 0x08, 0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78 + }; + u8 res[] = { + 0x1c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, + 0x08, 0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, + 0x78, 0x8c, 0x10, 0xf8, 0x76, 0x22, 0x80, 0x3d, + 0x9c, 0x22, 0x8a, 0xcb, 0x3c, 0x55, 0x8a, 0x33, + 0x2e, 0x94, 0x13 + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-256 using BCE, no optional header fields, S1G Beacon Compatibility element in body\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 7, 1, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1G Beacon frame with BIP-GMAC-256 using BCE"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-256 using BCE test vector mismatch"); + err++; + } + os_free(prot); + + return err; +} + + +static int test_vector_bip_gmac_256_s1g_beacon_bce_ext(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + u8 res[] = { + 0x1c, 0x47, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, + 0x10, 0x3c, 0x80, 0x49, 0xbe, 0x8c, 0x23, 0x34, + 0x1f, 0x5c, 0x2f, 0x9c, 0xd6, 0x03, 0xe3, 0x7a, + 0x5b + }; + u8 *prot; + size_t prot_len; + int err = 0; + + wpa_printf(MSG_INFO, "\nIEEE P802.11REVme/D4.0, J.9.2 S1G Beacon frame with BIP-GMAC-256 using BCE, all optional header fields, no body elements\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect_s1g_beacon(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 6, 1, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect S1B Beacon frame with BIP-GMAC-256 using BCE"); + return 1; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + if (prot_len != sizeof(res) || os_memcmp(res, prot, prot_len) != 0) { + wpa_printf(MSG_ERROR, "S1G Beacon frame with BIP-GMAC-256 using BCE test vector mismatch"); err++; } os_free(prot); @@ -929,12 +1475,24 @@ int main(int argc, char *argv[]) test_vector_ccmp(); test_vector_ccmp_pv1(); test_vector_bip(); + test_vector_bip_s1g_beacon(); + test_vector_bip_s1g_beacon_ext(); + test_vector_bip_s1g_beacon_bce(); + test_vector_bip_s1g_beacon_bce_ext(); test_vector_ccmp_mgmt(); errors += test_vector_gcmp(); errors += test_vector_gcmp_256(); errors += test_vector_ccmp_256(); errors += test_vector_bip_gmac_128(); + errors += test_vector_bip_gmac_128_s1g_beacon(); + errors += test_vector_bip_gmac_128_s1g_beacon_ext(); + errors += test_vector_bip_gmac_128_s1g_beacon_bce(); + errors += test_vector_bip_gmac_128_s1g_beacon_bce_ext(); errors += test_vector_bip_gmac_256(); + errors += test_vector_bip_gmac_256_s1g_beacon(); + errors += test_vector_bip_gmac_256_s1g_beacon_ext(); + errors += test_vector_bip_gmac_256_s1g_beacon_bce(); + errors += test_vector_bip_gmac_256_s1g_beacon_bce_ext(); if (errors) wpa_printf(MSG_INFO, "One or more test vectors failed"); diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 65ae74cb4..af32eefb8 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -353,8 +353,12 @@ u8 * wep_decrypt(struct wlantest *wt, const struct ieee80211_hdr *hdr, u8 * bip_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, u8 *ipn, int keyid, size_t *prot_len); +u8 * bip_protect_s1g_beacon(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, + u8 *ipn, int keyid, int bce, size_t *prot_len); 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 * bip_gmac_protect_s1g_beacon(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, + u8 *ipn, int keyid, int bce, size_t *prot_len); u8 * gcmp_decrypt(const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr, const u8 *a1, const u8 *a2, const u8 *a3,