/** @file pmkcache.c
|
*
|
* @brief This file defines pmk cache functions
|
*
|
* Copyright (C) 2014-2017, Marvell International Ltd.
|
*
|
* This software file (the "File") is distributed by Marvell International
|
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
* (the "License"). You may use, redistribute and/or modify this File in
|
* accordance with the terms and conditions of the License, a copy of which
|
* is available by writing to the Free Software Foundation, Inc.,
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
*
|
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
* this warranty disclaimer.
|
*/
|
|
/******************************************************
|
Change log:
|
03/07/2014: Initial version
|
******************************************************/
|
#include "wl_macros.h"
|
#include "pass_phrase.h"
|
#include "pmkCache.h"
|
#include "hostsa_ext_def.h"
|
#include "authenticator.h"
|
#include "tlv.h"
|
#include "keyMgmtApStaCommon.h"
|
|
#define MAX_PMK_CACHE_ENTRIES 10
|
|
pmkElement_t pmkCache[MAX_PMK_CACHE_ENTRIES];
|
|
char PSKPassPhrase[PSK_PASS_PHRASE_LEN_MAX];
|
/*
|
** Replacement rank is used to determine which cache entry to replace
|
** once the cache is full. The rank order is determined by usage. The
|
** least recently used cache element is the first to be replaced.
|
**
|
** replacementRankMax is an indication of the number of cache entries used.
|
** It is used to determine the rank of the current cache entry used.
|
**
|
** Rank order goes from 1 to MAX_PMK_CACHE_ENTRIES. If the cache is full,
|
** the element with rank 1 is first to be replaced.
|
**
|
** Replacement rank of zero indicates that the entry is invalid.
|
*/
|
|
UINT8 *
|
pmkCacheFindPSK(void *priv, UINT8 *pSsid, UINT8 ssidLen)
|
{
|
UINT8 *pPMK = NULL;
|
pmkElement_t *pPMKElement;
|
|
if (!pPMK) {
|
/* extract the PSK from the cache entry */
|
pPMKElement =
|
pmkCacheFindPSKElement((void *)priv, pSsid, ssidLen);
|
if (pPMKElement) {
|
pPMK = pPMKElement->PMK;
|
} else if ('\0' != PSKPassPhrase[0]) {
|
/* Generate a new PSK entry with the
|
** provided passphrase.
|
*/
|
pmkCacheAddPSK((void *)priv, pSsid, ssidLen, NULL,
|
PSKPassPhrase);
|
pPMKElement =
|
pmkCacheFindPSKElement((void *)priv, pSsid,
|
ssidLen);
|
pmkCacheGeneratePSK((void *)priv, pSsid, ssidLen,
|
PSKPassPhrase, pPMKElement->PMK);
|
pPMK = pPMKElement->PMK;
|
}
|
}
|
|
return pPMK;
|
}
|
|
UINT8 *
|
pmkCacheFindPassphrase(void *priv, UINT8 *pSsid, UINT8 ssidLen)
|
{
|
UINT8 *pPassphrase = NULL;
|
pmkElement_t *pPMKElement;
|
|
if (!pPassphrase) {
|
/* extract the PSK from the cache entry */
|
pPMKElement =
|
pmkCacheFindPSKElement((void *)priv, pSsid, ssidLen);
|
if (pPMKElement) {
|
pPassphrase = pPMKElement->passphrase;
|
}
|
|
}
|
|
return pPassphrase;
|
}
|
|
void
|
pmkCacheSetPassphrase(void *priv, char *pPassphrase)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
|
if (pPassphrase != NULL) {
|
memcpy(util_fns, PSKPassPhrase,
|
pPassphrase, sizeof(PSKPassPhrase));
|
}
|
}
|
|
void
|
pmkCacheGetPassphrase(void *priv, char *pPassphrase)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
|
if (pPassphrase != NULL) {
|
memcpy(util_fns, pPassphrase,
|
PSKPassPhrase, sizeof(PSKPassPhrase));
|
}
|
}
|
|
void
|
pmkCacheInit(void *priv)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
|
memset(util_fns, pmkCache, 0x00, sizeof(pmkCache));
|
memset(util_fns, PSKPassPhrase, 0x00, sizeof(PSKPassPhrase));
|
replacementRankMax = 0;
|
}
|
|
void
|
pmkCacheFlush(void *priv)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
|
memset(util_fns, pmkCache, 0x00, sizeof(pmkCache));
|
replacementRankMax = 0;
|
}
|
|
//#pragma arm section code = ".init"
|
void
|
pmkCacheRomInit(void)
|
{
|
ramHook_MAX_PMK_CACHE_ENTRIES = MAX_PMK_CACHE_ENTRIES;
|
ramHook_pmkCache = &pmkCache[0];
|
ramHook_PSKPassPhrase = &PSKPassPhrase[0];
|
// ramHook_hal_SetCpuMaxSpeed = hal_SetCpuOpToSecuritySpeed;
|
// ramHook_hal_RestoreCpuSpeed = cm_SetPerformanceParams;
|
}
|
|
//#pragma arm section code
|
|
#ifdef DRV_EMBEDDED_SUPPLICANT
|
|
t_u16
|
SupplicantSetPassphrase(void *priv, void *pPassphraseBuf)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = NULL;
|
mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pPassphraseBuf;
|
IEEEtypes_MacAddr_t *pBssid = NULL;
|
UINT8 *pPMK = NULL;
|
UINT8 Passphrase[PSK_PASS_PHRASE_LEN_MAX], *pPassphrase = NULL;
|
UINT8 *pSsid = NULL;
|
UINT8 ssidLen = 0;
|
UINT16 retVal = 0;
|
t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
|
|
if (!psapriv)
|
return retVal;
|
util_fns = &psapriv->util_fns;
|
|
if (memcmp(util_fns, (t_u8 *)&psk->bssid, zero_mac, sizeof(zero_mac)))
|
pBssid = (IEEEtypes_MacAddr_t *)&psk->bssid;
|
|
ssidLen = psk->ssid.ssid_len;
|
if (ssidLen > 0)
|
pSsid = psk->ssid.ssid;
|
|
if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
|
pPassphrase = psk->psk.passphrase.passphrase;
|
memset(util_fns, Passphrase, 0x00, sizeof(Passphrase));
|
memcpy(util_fns, Passphrase, pPassphrase,
|
MIN(MLAN_MAX_PASSPHRASE_LENGTH,
|
psk->psk.passphrase.passphrase_len));
|
}
|
|
if (psk->psk_type == MLAN_PSK_PMK)
|
pPMK = psk->psk.pmk.pmk;
|
|
/* Always enable the supplicant on a set */
|
// supplicantEnable(priv);
|
|
if (pBssid && pPMK) {
|
pmkCacheAddPMK(priv, pBssid, pPMK);
|
} else if (pSsid) {
|
if (pPMK) {
|
pmkCacheAddPSK(priv, pSsid, ssidLen, pPMK, NULL);
|
} else if (pPassphrase) {
|
pmkCacheAddPSK(priv, pSsid, ssidLen, NULL, Passphrase);
|
pPMK = pmkCacheFindPSK(priv, pSsid, ssidLen);
|
pmkCacheGeneratePSK(priv, pSsid, ssidLen,
|
(char *)Passphrase, pPMK);
|
} else {
|
/* Just an SSID so we can't set anything in the cache */
|
retVal = 1;
|
}
|
} else if (pPassphrase) {
|
memcpy(util_fns, PSKPassPhrase, Passphrase, sizeof(Passphrase));
|
} else {
|
/* Not enough data to set anything in the cache */
|
retVal = 1;
|
}
|
|
return retVal;
|
}
|
|
BOOLEAN
|
SupplicantClearPMK_internal(void *priv, void *pPassphraseBuf)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pPassphraseBuf;
|
IEEEtypes_MacAddr_t *pBssid = NULL;
|
UINT8 *pPassphrase = NULL;
|
UINT8 *pSsid = NULL;
|
UINT8 ssidLen = 0;
|
t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
|
|
if (memcmp(util_fns, (t_u8 *)&psk->bssid, zero_mac, sizeof(zero_mac)))
|
pBssid = (IEEEtypes_MacAddr_t *)&psk->bssid;
|
|
ssidLen = psk->ssid.ssid_len;
|
if (ssidLen > 0)
|
pSsid = psk->ssid.ssid;
|
|
if (psk->psk_type == MLAN_PSK_PASSPHRASE)
|
pPassphrase = psk->psk.passphrase.passphrase;
|
|
if (pBssid) {
|
pmkCacheDeletePMK(priv, (UINT8 *)pBssid);
|
} else if (pSsid) {
|
pmkCacheDeletePSK(priv, pSsid, ssidLen);
|
} else if (pPassphrase) {
|
/* Clear the global passphrase by setting it to blank */
|
memset(util_fns, ramHook_PSKPassPhrase, 0x00,
|
PSK_PASS_PHRASE_LEN_MAX);
|
} else {
|
return FALSE;
|
}
|
|
return TRUE;
|
}
|
|
void
|
SupplicantClearPMK(void *priv, void *pPassphrase)
|
{
|
if (!priv)
|
return;
|
|
if (!SupplicantClearPMK_internal(priv, pPassphrase)) {
|
/* Always disable the supplicant on a flush */
|
supplicantDisable(priv);
|
pmkCacheFlush(priv);
|
}
|
}
|
|
void
|
SupplicantQueryPassphrase(void *priv, void *pPassphraseBuf)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = NULL;
|
mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pPassphraseBuf;
|
UINT8 *pPassphrase = NULL;
|
UINT8 *pSsid = NULL;
|
UINT8 ssidLen = 0;
|
|
if (!psapriv)
|
return;
|
|
util_fns = &psapriv->util_fns;
|
ssidLen = psk->ssid.ssid_len;
|
pSsid = psk->ssid.ssid;
|
|
if (ssidLen) {
|
pPassphrase = pmkCacheFindPassphrase(priv, pSsid, ssidLen);
|
if (pPassphrase) {
|
psk->psk_type = MLAN_PSK_PASSPHRASE;
|
memcpy(util_fns, psk->psk.passphrase.passphrase,
|
pPassphrase, PSK_PASS_PHRASE_LEN_MAX);
|
psk->psk.passphrase.passphrase_len =
|
wlan_strlen(pPassphrase);
|
}
|
}
|
|
}
|
#endif
|