blob: dff076913abe4d80cfc6392ffa99cf9b5278ce1e [file] [log] [blame]
/** @file pmkcache_rom.c
*
* @brief This file defines function for pmk cache
*
* Copyright (C) 2014, 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]));
}
}
}
}