/** @file pmkcache_rom.c
|
*
|
* @brief This file defines function for pmk cache
|
*
|
* 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 "wltypes.h"
|
#include "pass_phrase.h"
|
#include "pmkCache_rom.h"
|
|
#include "hostsa_ext_def.h"
|
#include "authenticator.h"
|
|
#define BSSID_FLAG 0xff
|
|
SINT8 replacementRankMax;
|
|
SINT32 ramHook_MAX_PMK_CACHE_ENTRIES;
|
|
pmkElement_t *ramHook_pmkCache;
|
char *ramHook_PSKPassPhrase;
|
|
//void (*ramHook_hal_SetCpuMaxSpeed)(void);
|
//void (*ramHook_hal_RestoreCpuSpeed)(void);
|
|
/*!
|
** \brief creates a new PMK cache entry with given SSID.
|
** \param pSsid pointer to desired SSID.
|
** \param ssidLen length of the desired SSID string.
|
** \return pointer to newly created PMK cache entry,
|
** NULL if PMK cache is full.
|
*/
|
pmkElement_t *
|
pmkCacheNewElement(void *priv)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
UINT8 index;
|
pmkElement_t *pPMK = NULL;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (pmkCacheNewElement_hook(&pPMK)) {
|
return pPMK;
|
}
|
#endif
|
|
for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
|
/* If the cache is full the least recently used entry
|
** will be replaced. Decrement all the replacement ranks
|
** to have a free cache entry.
|
*/
|
if (ramHook_MAX_PMK_CACHE_ENTRIES == replacementRankMax) {
|
(ramHook_pmkCache[index].replacementRank)--;
|
}
|
|
/* Either the entry is free or it can be replaced */
|
if (NULL == pPMK &&
|
0 == ramHook_pmkCache[index].replacementRank) {
|
/* empty entry found */
|
pPMK = &ramHook_pmkCache[index];
|
|
/* clear the entry in case this is a replacement */
|
memset(util_fns, pPMK, 0x00, sizeof(pmkElement_t));
|
|
if (ramHook_MAX_PMK_CACHE_ENTRIES > replacementRankMax) {
|
/* Cache isn't full so increment the max possible rank */
|
replacementRankMax++;
|
}
|
|
/* Set the rank so it is the last to be replaced */
|
ramHook_pmkCache[index].replacementRank =
|
replacementRankMax;
|
}
|
}
|
|
return pPMK;
|
}
|
|
void
|
pmkCacheUpdateReplacementRank(pmkElement_t *pPMKElement)
|
{
|
UINT8 index;
|
|
/* Update the replacementRank field if the PMK is found */
|
if (pPMKElement && pPMKElement->replacementRank != replacementRankMax) {
|
/*
|
** The cache entry with a larger rank value needs to
|
** to be adjusted. The cache entry given will have the
|
** largest rank value
|
*/
|
for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
|
if (ramHook_pmkCache[index].replacementRank
|
> pPMKElement->replacementRank) {
|
(ramHook_pmkCache[index].replacementRank)--;
|
}
|
}
|
|
pPMKElement->replacementRank = replacementRankMax;
|
}
|
}
|
|
/*!
|
** \brief Finds a PMK entry matching given BSSID
|
** \param pBssid pointer to the desired BSSID
|
** \return pointer to key data field of the matching PMK cache entry.
|
** NULL, if no matching PMK entry is found
|
*/
|
pmkElement_t *
|
pmkCacheFindPMKElement(void *priv, IEEEtypes_MacAddr_t *pBssid)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
UINT8 index = 0;
|
pmkElement_t *pPMKElement = NULL;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (pmkCacheFindPMKElement_hook(pBssid, &pPMKElement)) {
|
return pPMKElement;
|
}
|
#endif
|
|
for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
|
/* See if the entry is valid.
|
** See if the entry is a PMK
|
** See if the BSSID matches
|
*/
|
if (ramHook_pmkCache[index].replacementRank > 0
|
&& ramHook_pmkCache[index].length == BSSID_FLAG
|
&& (0 == memcmp(util_fns, ramHook_pmkCache[index].key.Bssid,
|
pBssid,
|
sizeof(ramHook_pmkCache[index].key.Bssid))))
|
{
|
pPMKElement = (ramHook_pmkCache + index);
|
}
|
}
|
|
/* Update the rank if an entry is found. Null is an accepted
|
** input for the function
|
*/
|
pmkCacheUpdateReplacementRank(pPMKElement);
|
|
return pPMKElement;
|
}
|
|
/*!
|
** \brief If a matching SSID entry is present in the PMK Cache, returns a
|
** pointer to its key field.
|
** \param pSsid pointer to string containing desired SSID.
|
** \param ssidLen length of the SSID string *pSsid.
|
** \exception Does not handle the case when multiple matching SSID entries are
|
** found. Returns the first match.
|
** \return pointer to pmkElement with matching SSID entry from PMK cache,
|
** NULL if no matching entry found.
|
*/
|
pmkElement_t *
|
pmkCacheFindPSKElement(void *priv, UINT8 *pSsid, UINT8 ssidLen)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
UINT8 index = 0;
|
pmkElement_t *pPMKElement = NULL;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (pmkCacheFindPSKElement_hook(pSsid, ssidLen, &pPMKElement)) {
|
return pPMKElement;
|
}
|
#endif
|
|
for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
|
/* See if the entry is valid.
|
** See if the entry is a PSK
|
** See if the SSID matches
|
*/
|
if (ramHook_pmkCache[index].replacementRank
|
&& ramHook_pmkCache[index].length == ssidLen
|
&& (0 == memcmp(util_fns, ramHook_pmkCache[index].key.Ssid,
|
pSsid, ssidLen))) {
|
pPMKElement = (ramHook_pmkCache + index);
|
}
|
}
|
|
/* Update the rank if an entry is found. Null is an accepted
|
** input for the function
|
*/
|
pmkCacheUpdateReplacementRank(pPMKElement);
|
|
return pPMKElement;
|
}
|
|
UINT8 *
|
pmkCacheFindPMK(void *priv, IEEEtypes_MacAddr_t *pBssid)
|
{
|
UINT8 *pPMK = NULL;
|
pmkElement_t *pPMKElement = pmkCacheFindPMKElement(priv, pBssid);
|
|
/* extract the PMK from the cache entry */
|
if (pPMKElement) {
|
pPMK = pPMKElement->PMK;
|
}
|
|
return pPMK;
|
}
|
|
void
|
pmkCacheAddPMK(void *priv, IEEEtypes_MacAddr_t *pBssid, UINT8 *pPMK)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
pmkElement_t *pPMKElement;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (pmkCacheAddPMK_hook(pBssid, pPMK)) {
|
return;
|
}
|
#endif
|
|
pPMKElement = pmkCacheFindPMKElement(priv, pBssid);
|
|
if (!pPMKElement) {
|
/* Entry not found. Create a new entry and fill it in */
|
pPMKElement = pmkCacheNewElement(priv);
|
|
/* Update the key union with the BSSID */
|
memcpy(util_fns, pPMKElement->key.Bssid,
|
pBssid, sizeof(pPMKElement->key.Bssid));
|
|
/* Set the length to a value that is invalid for
|
** an SSID. The invalid value will flag the entry as a PMK
|
*/
|
pPMKElement->length = BSSID_FLAG;
|
}
|
|
if (pPMK) {
|
memcpy(util_fns, pPMKElement->PMK, pPMK, MAX_PMK_SIZE);
|
}
|
}
|
|
void
|
pmkCacheAddPSK(void *priv, UINT8 *pSsid, UINT8 ssidLen, UINT8 *pPSK,
|
UINT8 *pPassphrase)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
pmkElement_t *pPMKElement;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (pmkCacheAddPSK_hook(pSsid, ssidLen, pPSK)) {
|
return;
|
}
|
#endif
|
|
pPMKElement = pmkCacheFindPSKElement(priv, pSsid, ssidLen);
|
|
if (NULL == pPMKElement) {
|
/* Entry not found. Create a new entry and fill it in */
|
pPMKElement = pmkCacheNewElement(priv);
|
|
/* Update the key portion with the SSID */
|
memcpy(util_fns, pPMKElement->key.Ssid, pSsid, ssidLen);
|
|
pPMKElement->length = ssidLen;
|
}
|
|
if (pPSK) {
|
memcpy(util_fns, pPMKElement->PMK, pPSK, MAX_PMK_SIZE);
|
}
|
|
if (pPassphrase)
|
memcpy(util_fns, pPMKElement->passphrase, pPassphrase,
|
PSK_PASS_PHRASE_LEN_MAX);
|
|
}
|
|
void
|
pmkCacheDeletePMK(void *priv, t_u8 *pBssid)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
pmkElement_t *pPMKElement =
|
pmkCacheFindPMKElement(priv, (IEEEtypes_MacAddr_t *)pBssid);
|
|
if (pPMKElement) {
|
/* Invalidate the enrty by setting the memory for the
|
** cache entry to zero.
|
** This will ensure that the replacementRank is zero
|
*/
|
memset(util_fns, pPMKElement, 0x00, sizeof(pmkElement_t));
|
replacementRankMax--;
|
}
|
}
|
|
void
|
pmkCacheDeletePSK(void *priv, UINT8 *pSsid, UINT8 ssidLen)
|
{
|
phostsa_private psapriv = (phostsa_private)priv;
|
hostsa_util_fns *util_fns = &psapriv->util_fns;
|
pmkElement_t *pPMKElement =
|
pmkCacheFindPSKElement(priv, pSsid, ssidLen);
|
|
if (pPMKElement) {
|
/* Invalidate the enrty by setting the memory for the
|
** cache entry to zero.
|
** This will ensure that the replacementRank is zero
|
*/
|
memset(util_fns, pPMKElement, 0x00, sizeof(pmkElement_t));
|
replacementRankMax--;
|
}
|
}
|
|
UINT8
|
pmkCacheGetHexNibble(UINT8 nibble)
|
{
|
if (nibble >= 'a') {
|
return (nibble - 'a' + 10);
|
}
|
|
if (nibble >= 'A') {
|
return (nibble - 'A' + 10);
|
}
|
|
return (nibble - '0');
|
}
|
|
void
|
pmkCacheGeneratePSK(void *priv, UINT8 *pSsid,
|
UINT8 ssidLen, char *pPassphrase, UINT8 *pPSK)
|
{
|
int i;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (pmkCacheGeneratePSK_hook(pSsid, ssidLen, pPassphrase, pPSK)) {
|
return;
|
}
|
#endif
|
|
if (pPSK && pPassphrase) {
|
for (i = 0; i < PSK_PASS_PHRASE_LEN_MAX; i++) {
|
if (pPassphrase[i] == 0) {
|
break;
|
}
|
}
|
|
if (i > 7 && i < PSK_PASS_PHRASE_LEN_MAX) {
|
/* bump the CPU speed for the PSK generation */
|
//ramHook_hal_SetCpuMaxSpeed();
|
Mrvl_PasswordHash((void *)priv, pPassphrase,
|
(UINT8 *)pSsid, ssidLen, pPSK);
|
//ramHook_hal_RestoreCpuSpeed();
|
} else if (i == PSK_PASS_PHRASE_LEN_MAX) {
|
/* Convert ASCII to binary */
|
for (i = 0; i < PSK_PASS_PHRASE_LEN_MAX; i += 2) {
|
pPSK[i / 2] =
|
((pmkCacheGetHexNibble(pPassphrase[i])
|
<< 4)
|
|
|
pmkCacheGetHexNibble(pPassphrase
|
[i + 1]));
|
|
}
|
}
|
}
|
}
|