📄 wpa.c
字号:
//---------------------------------------------------------------------------
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//--------------------------------------------------------------------------
//
// File: wpa.c
// Source file for platform specific SDIO WLAN functions
//------------------------------------------------------------------------------
/***************************************************************************/
/*** Include Files ***/
/***************************************************************************/
#include "precomp.h"
#include "umi.h"
/***************************************************************************/
/*** Local Constants ***/
/***************************************************************************/
/***************************************************************************/
/*** Typedefs ***/
/***************************************************************************/
// Refer to IEEE 802.11i standard for description of RSN IE format
// Refer to Wi-Fi Alliance's Wi-Fi Protected Access (WPA) document for description of WPA format of an RSN IE
/* Format of the RSN IE Payload contains mandatory and optional elements */
typedef struct
{
/* start of optional elements */
uint8 au8VariablePayload[UMI_RSN_IE_MAX_LEN - UMI_RSN_IE_HEADER_LEN];
/* Note: RSN IE Variable Payload consists of the following elements:
UMI_RSN_IE_WECA_OUI_LEN // Wi-Fi Alliance OUI Field Length - 4 octets
+UMI_RSN_IE_VERSION_LEN // Version Field Length - 2 octets
+UMI_RSN_IE_SUITE_SELECTOR_LEN // Group Cipher Suite Field Length - 4 octets
+UMI_RSN_IE_SUITE_COUNT_LEN // Pairwise Cipher Suite Field Length - 2 octets
+CIPHER_SUITE_LIST_MAX_PAYLOAD // Pairwise Cipher Suite List Field Length - 4*m octets
+UMI_RSN_IE_SUITE_COUNT_LEN // AKM Suite Count Field Length - 2 octets
+AKM_SUITE_LIST_MAX_PAYLOAD // AKM Suite List Field Length - 4*n octets
+UMI_RSN_IE_CAPABILITIES_LEN // RSN Capabilities Field Length - 2 octets
+UMI_RSN_IE_PMKID_COUNT_LEN // PMKID Count Field Length - 2 octets
+PMKID_LIST_MAX_PAYLOAD]; // PMKID List Field Length - 16*s octets
*/
} WPA_RSN_IE_PAYLOAD;
/***************************************************************************/
/*** Private Function Prototypes ***/
/***************************************************************************/
static uint8 *pu8WPAaddRsnIeOuiField(bool bouseWECAoui, uint8 *pu8OutOui);
static uint8 *pu8WPAaddRsnIeVersionField(uint16 u16version, uint8 *pu8OutVersion);
static uint8 *pu8WPAaddRsnIeGroupCipherField(const UMI_RSN_CAPS *psRsnCaps, uint8 *pu8OutGroupCipher);
static uint8 *pu8WPAaddRsnIePairwiseCipherFields(const UMI_RSN_CAPS *psRsnCaps, uint8 *pu8OutPairwiseCipher);
static uint8 *pu8WPAaddRsnIeAkmFields(const UMI_RSN_CAPS *psRsnCaps, uint8 *pu8OutAkm);
static uint8 *pu8WPAaddRsnIeRsnCapField(const UMI_RSN_CAPS *psRsnCaps, uint8 *pu8OutRsnCap);
static uint16 u16WPAgetPairwiseCipherSuiteCount(const UMI_RSN_CAPS *psRsnCaps);
static uint16 u16WPAgetAkmSuiteCount(const UMI_RSN_CAPS *psRsnCaps);
/***************************************************************************/
/*** Public Functions ***/
/***************************************************************************/
/*****************************************************************************
**
** NAME pu8WPAaddRsnIePayloadFields
**
** PARAMETERS psRsnCaps pointer to structure with the RsnCaps
** for this Network
** pu8OutRsnIeData pointer to Rsn IE's payload section
**
** RETURNS pointer to end of added fields. If function is unable to
** successfully build RSN IE Payload, then it returns the same
** value that was passed in by the pu8OutRsnIe function
** input parameter (i.e., RSN IE length = 0).
**
** DESCRIPTION This function reads the RsnCaps bitmap of this Network and
** builds the Payload portion of the RSN Information Element.
** Refer to IEEE 802.11i standard for a description of the RSN IE.
**
******************************************************************************/
uint8 *pu8WPAaddRsnIePayloadFields(const UMI_RSN_CAPS *psRsnCaps, uint8 *pu8OutRsnIeData)
{
uint16 u16testRsnIeLength;
uint16 u16sizeOfCipherSuiteList;
uint16 u16sizeOfAkmSuiteList;
uint16 u16sizeOfPkmidList;
WPA_RSN_IE_PAYLOAD * psrsnIeInfo = (WPA_RSN_IE_PAYLOAD *) pu8OutRsnIeData;
uint8 * pu8payload = psrsnIeInfo->au8VariablePayload;
ASSERT(psRsnCaps != NULL);
ASSERT(pu8OutRsnIeData != NULL);
if (psRsnCaps->u32CapsMap & UMI_RSN_CAPS_IE_TYPE_MASK)
{
//------------------------------------------
// Add RSN IE Version
//------------------------------------------
if (psRsnCaps->u32CapsMap & UMI_RSN_CAPS_IE_TYPE_IEEE)
{
/* Add in RSN IE Version */
pu8payload = pu8WPAaddRsnIeVersionField(UMI_RSN_IE_SUPPORTED_IEEE_VERSION, pu8payload);
}
else if (psRsnCaps->u32CapsMap & UMI_RSN_CAPS_IE_TYPE_WECA)
{
/* Add in Wi-Fi Alliance's OUI & Type */
pu8payload = pu8WPAaddRsnIeOuiField(TRUE, pu8payload);
*pu8payload++ = UMI_RSN_OUI_WECA_TYPE_WPA;
/* Add in RSN IE Version */
pu8payload = pu8WPAaddRsnIeVersionField(UMI_RSN_IE_SUPPORTED_WECA_VERSION, pu8payload);
}
else
{
// unknown RSN IE from network...
DBG_LEV0(("ERROR: Unknown RSN IE Type, IE Element Id = 0x%lx.\n", (psRsnCaps->u32CapsMap & UMI_RSN_CAPS_IE_TYPE_MASK)));
return pu8OutRsnIeData;
}
//------------------------------------------
// Verify that the buffer won't be overrun
// when the variable length payload is
// added
//------------------------------------------
u16testRsnIeLength = UMI_RSN_IE_HEADER_LEN + (pu8payload - pu8OutRsnIeData);
// Calculate length of Cipher Suite List
u16sizeOfCipherSuiteList = (!(psRsnCaps->u32CapsMap & UMI_RSN_CAPS_PAIRWISE_CIPHER_SUITE_MASK)) ?
UMI_RSN_IE_SUITE_SELECTOR_LEN : // use default Cipher Suite
u16WPAgetPairwiseCipherSuiteCount(psRsnCaps) * UMI_RSN_IE_SUITE_SELECTOR_LEN;
// Calculate length of AKM Suite List
u16sizeOfAkmSuiteList = (!(psRsnCaps->u32CapsMap & UMI_RSN_CAPS_AUTH_SUITE_MASK)) ?
UMI_RSN_IE_SUITE_SELECTOR_LEN : // use default AKM Suite
u16WPAgetAkmSuiteCount(psRsnCaps) * UMI_RSN_IE_SUITE_SELECTOR_LEN;
// FIXME: Calculate length of PMKID List...
u16sizeOfPkmidList = 0; /* = n * UMI_RSN_IE_PMKID_KEY_LEN; */
// FIXME: add in PMKID Count Field Length ...
u16testRsnIeLength += UMI_RSN_IE_SUITE_SELECTOR_LEN /* Group Cipher Suite Field Length - 4 octets */
+UMI_RSN_IE_SUITE_COUNT_LEN /* Pairwise Cipher Suite Field Length - 2 octets */
+u16sizeOfCipherSuiteList /* Pairwise Cipher Suite List Field Length - 4*m octets*/
+UMI_RSN_IE_SUITE_COUNT_LEN /* AKM Suite Count Field Length - 2 octets */
+u16sizeOfAkmSuiteList /* AKM Suite List Field Length - 4*n octets*/
+UMI_RSN_IE_CAPABILITIES_LEN /* RSN Capabilities Field Length - 2 octets */
// +UMI_RSN_IE_PMKID_COUNT_LEN /* PMKID Count Field Length - 2 octets */
+u16sizeOfPkmidList; /* PMKID List Field Length - 16*s octets */
if (u16testRsnIeLength > UMI_RSN_IE_MAX_LEN)
{
DBG_LEV0(("ERROR: Invalid RSN IE: u32CapsMap = 0x%lx. Exceeds max length: length = %d, allowed = %d.\n", psRsnCaps->u32CapsMap, u16testRsnIeLength, UMI_RSN_IE_MAX_LEN));
return pu8OutRsnIeData;
}
//------------------------------------------
// Build the RSN IE Payload Body
//------------------------------------------
/* Add in variable length RSN IE fields */
pu8payload = pu8WPAaddRsnIeGroupCipherField(psRsnCaps, pu8payload);
pu8payload = pu8WPAaddRsnIePairwiseCipherFields(psRsnCaps, pu8payload);
pu8payload = pu8WPAaddRsnIeAkmFields(psRsnCaps, pu8payload);
pu8payload = pu8WPAaddRsnIeRsnCapField(psRsnCaps, pu8payload);
// FIXME: Need to add in PMKID fields ....
}
return pu8payload;
}
/***************************************************************************/
/*** Private Functions ***/
/***************************************************************************/
/*****************************************************************************
**
** NAME pu8WPAaddRsnIeOuiField
**
** PARAMETERS bouseWECAoui - if True the WECA OUI will be inserted in the
** output field. Otherwise the IEEE OUI will
** be inserted in the output field.
** pu8OutOui - pointer to start of output field
**
** RETURNS pointer to start of next field
**
** DESCRIPTION This function inserts the OUI field into the RSN IE.
**
******************************************************************************/
static uint8 *pu8WPAaddRsnIeOuiField(bool bouseWECAoui, uint8 *pu8OutOui)
{
if (bouseWECAoui)
{
/* Add in WECA OUI */
*pu8OutOui++ = UMI_RSN_OUI_WECA_OCTET_0;
*pu8OutOui++ = UMI_RSN_OUI_WECA_OCTET_1;
*pu8OutOui++ = UMI_RSN_OUI_WECA_OCTET_2;
}
else
{
/* Add in IEEE OUI */
*pu8OutOui++ = UMI_RSN_OUI_IEEE_OCTET_0;
*pu8OutOui++ = UMI_RSN_OUI_IEEE_OCTET_1;
*pu8OutOui++ = UMI_RSN_OUI_IEEE_OCTET_2;
}
return pu8OutOui;
}
/*****************************************************************************
**
** NAME pu8WPAaddRsnIeVersionField
**
** PARAMETERS u16version - version number to insert
** pu8OutVersion - pointer to start of output field
**
** RETURNS pointer to start of next field
**
** DESCRIPTION This function inserts the Version field into the RSN IE.
**
******************************************************************************/
static uint8 *pu8WPAaddRsnIeVersionField(uint16 u16version, uint8 *pu8OutVersion)
{
/* Add in RSN IE Version */
*pu8OutVersion++ = u16version & 0x00FF; // LSB
*pu8OutVersion++ = u16version >> 8; // MSB
return pu8OutVersion;
}
/*****************************************************************************
**
** NAME pu8WPAaddRsnIeGroupCipherField
**
** PARAMETERS psRsnCaps - pointer to structure with the RsnCaps
** for this Network
** pu8OutGroupCipher - pointer to start of output field
**
** RETURNS pointer to start of next field
**
** DESCRIPTION This function inserts the Group Cipher field into the RSN IE.
**
******************************************************************************/
static uint8 *pu8WPAaddRsnIeGroupCipherField(const UMI_RSN_CAPS *psRsnCaps, uint8 *pu8OutGroupCipher)
{
bool bouseWECAoui = (psRsnCaps->u32CapsMap & UMI_RSN_CAPS_IE_TYPE_WECA) ? TRUE : FALSE;
uint8 * pu8payload = pu8OutGroupCipher;
// Add in OUI
pu8payload = pu8WPAaddRsnIeOuiField(bouseWECAoui, pu8payload);
/* Add cipher suite type */
if (psRsnCaps->u32CapsMap & UMI_RSN_CAPS_GROUP_CIPHER_SUITE_NONE)
{
DBG_LEV0(("ERROR: Invalid RSN IE Group Cipher Suite Type, u32CapsMap = 0x%lx.\n", psRsnCaps->u32CapsMap));
// error - this is invalid for a Group Cipher. Use the default instead...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -