1 /** @file pmkcache_rom.c
2 *
3 * @brief This file defines function for pmk cache
4 *
5 * Copyright (C) 2014-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 */
20
21 /******************************************************
22 Change log:
23 03/07/2014: Initial version
24 ******************************************************/
25 #include "wl_macros.h"
26 #include "wltypes.h"
27 #include "pass_phrase.h"
28 #include "pmkCache_rom.h"
29
30 #include "hostsa_ext_def.h"
31 #include "authenticator.h"
32
33 #define BSSID_FLAG 0xff
34
35 SINT8 replacementRankMax;
36
37 SINT32 ramHook_MAX_PMK_CACHE_ENTRIES;
38
39 pmkElement_t *ramHook_pmkCache;
40 char *ramHook_PSKPassPhrase;
41
42 //void (*ramHook_hal_SetCpuMaxSpeed)(void);
43 //void (*ramHook_hal_RestoreCpuSpeed)(void);
44
45 /*!
46 ** \brief creates a new PMK cache entry with given SSID.
47 ** \param pSsid pointer to desired SSID.
48 ** \param ssidLen length of the desired SSID string.
49 ** \return pointer to newly created PMK cache entry,
50 ** NULL if PMK cache is full.
51 */
52 pmkElement_t *
pmkCacheNewElement(void * priv)53 pmkCacheNewElement(void *priv)
54 {
55 phostsa_private psapriv = (phostsa_private)priv;
56 hostsa_util_fns *util_fns = &psapriv->util_fns;
57 UINT8 index;
58 pmkElement_t *pPMK = NULL;
59
60 #if 0 //!defined(REMOVE_PATCH_HOOKS)
61 if (pmkCacheNewElement_hook(&pPMK)) {
62 return pPMK;
63 }
64 #endif
65
66 for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
67 /* If the cache is full the least recently used entry
68 ** will be replaced. Decrement all the replacement ranks
69 ** to have a free cache entry.
70 */
71 if (ramHook_MAX_PMK_CACHE_ENTRIES == replacementRankMax) {
72 (ramHook_pmkCache[index].replacementRank)--;
73 }
74
75 /* Either the entry is free or it can be replaced */
76 if (NULL == pPMK &&
77 0 == ramHook_pmkCache[index].replacementRank) {
78 /* empty entry found */
79 pPMK = &ramHook_pmkCache[index];
80
81 /* clear the entry in case this is a replacement */
82 memset(util_fns, pPMK, 0x00, sizeof(pmkElement_t));
83
84 if (ramHook_MAX_PMK_CACHE_ENTRIES > replacementRankMax) {
85 /* Cache isn't full so increment the max possible rank */
86 replacementRankMax++;
87 }
88
89 /* Set the rank so it is the last to be replaced */
90 ramHook_pmkCache[index].replacementRank =
91 replacementRankMax;
92 }
93 }
94
95 return pPMK;
96 }
97
98 void
pmkCacheUpdateReplacementRank(pmkElement_t * pPMKElement)99 pmkCacheUpdateReplacementRank(pmkElement_t *pPMKElement)
100 {
101 UINT8 index;
102
103 /* Update the replacementRank field if the PMK is found */
104 if (pPMKElement && pPMKElement->replacementRank != replacementRankMax) {
105 /*
106 ** The cache entry with a larger rank value needs to
107 ** to be adjusted. The cache entry given will have the
108 ** largest rank value
109 */
110 for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
111 if (ramHook_pmkCache[index].replacementRank
112 > pPMKElement->replacementRank) {
113 (ramHook_pmkCache[index].replacementRank)--;
114 }
115 }
116
117 pPMKElement->replacementRank = replacementRankMax;
118 }
119 }
120
121 /*!
122 ** \brief Finds a PMK entry matching given BSSID
123 ** \param pBssid pointer to the desired BSSID
124 ** \return pointer to key data field of the matching PMK cache entry.
125 ** NULL, if no matching PMK entry is found
126 */
127 pmkElement_t *
pmkCacheFindPMKElement(void * priv,IEEEtypes_MacAddr_t * pBssid)128 pmkCacheFindPMKElement(void *priv, IEEEtypes_MacAddr_t *pBssid)
129 {
130 phostsa_private psapriv = (phostsa_private)priv;
131 hostsa_util_fns *util_fns = &psapriv->util_fns;
132 UINT8 index = 0;
133 pmkElement_t *pPMKElement = NULL;
134
135 #if 0 //!defined(REMOVE_PATCH_HOOKS)
136 if (pmkCacheFindPMKElement_hook(pBssid, &pPMKElement)) {
137 return pPMKElement;
138 }
139 #endif
140
141 for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
142 /* See if the entry is valid.
143 ** See if the entry is a PMK
144 ** See if the BSSID matches
145 */
146 if (ramHook_pmkCache[index].replacementRank > 0
147 && ramHook_pmkCache[index].length == BSSID_FLAG
148 && (0 == memcmp(util_fns, ramHook_pmkCache[index].key.Bssid,
149 pBssid,
150 sizeof(ramHook_pmkCache[index].key.Bssid))))
151 {
152 pPMKElement = (ramHook_pmkCache + index);
153 }
154 }
155
156 /* Update the rank if an entry is found. Null is an accepted
157 ** input for the function
158 */
159 pmkCacheUpdateReplacementRank(pPMKElement);
160
161 return pPMKElement;
162 }
163
164 /*!
165 ** \brief If a matching SSID entry is present in the PMK Cache, returns a
166 ** pointer to its key field.
167 ** \param pSsid pointer to string containing desired SSID.
168 ** \param ssidLen length of the SSID string *pSsid.
169 ** \exception Does not handle the case when multiple matching SSID entries are
170 ** found. Returns the first match.
171 ** \return pointer to pmkElement with matching SSID entry from PMK cache,
172 ** NULL if no matching entry found.
173 */
174 pmkElement_t *
pmkCacheFindPSKElement(void * priv,UINT8 * pSsid,UINT8 ssidLen)175 pmkCacheFindPSKElement(void *priv, UINT8 *pSsid, UINT8 ssidLen)
176 {
177 phostsa_private psapriv = (phostsa_private)priv;
178 hostsa_util_fns *util_fns = &psapriv->util_fns;
179 UINT8 index = 0;
180 pmkElement_t *pPMKElement = NULL;
181
182 #if 0 //!defined(REMOVE_PATCH_HOOKS)
183 if (pmkCacheFindPSKElement_hook(pSsid, ssidLen, &pPMKElement)) {
184 return pPMKElement;
185 }
186 #endif
187
188 for (index = 0; index < ramHook_MAX_PMK_CACHE_ENTRIES; index++) {
189 /* See if the entry is valid.
190 ** See if the entry is a PSK
191 ** See if the SSID matches
192 */
193 if (ramHook_pmkCache[index].replacementRank
194 && ramHook_pmkCache[index].length == ssidLen
195 && (0 == memcmp(util_fns, ramHook_pmkCache[index].key.Ssid,
196 pSsid, ssidLen))) {
197 pPMKElement = (ramHook_pmkCache + index);
198 }
199 }
200
201 /* Update the rank if an entry is found. Null is an accepted
202 ** input for the function
203 */
204 pmkCacheUpdateReplacementRank(pPMKElement);
205
206 return pPMKElement;
207 }
208
209 UINT8 *
pmkCacheFindPMK(void * priv,IEEEtypes_MacAddr_t * pBssid)210 pmkCacheFindPMK(void *priv, IEEEtypes_MacAddr_t *pBssid)
211 {
212 UINT8 *pPMK = NULL;
213 pmkElement_t *pPMKElement = pmkCacheFindPMKElement(priv, pBssid);
214
215 /* extract the PMK from the cache entry */
216 if (pPMKElement) {
217 pPMK = pPMKElement->PMK;
218 }
219
220 return pPMK;
221 }
222
223 void
pmkCacheAddPMK(void * priv,IEEEtypes_MacAddr_t * pBssid,UINT8 * pPMK)224 pmkCacheAddPMK(void *priv, IEEEtypes_MacAddr_t *pBssid, UINT8 *pPMK)
225 {
226 phostsa_private psapriv = (phostsa_private)priv;
227 hostsa_util_fns *util_fns = &psapriv->util_fns;
228 pmkElement_t *pPMKElement;
229
230 #if 0 //!defined(REMOVE_PATCH_HOOKS)
231 if (pmkCacheAddPMK_hook(pBssid, pPMK)) {
232 return;
233 }
234 #endif
235
236 pPMKElement = pmkCacheFindPMKElement(priv, pBssid);
237
238 if (!pPMKElement) {
239 /* Entry not found. Create a new entry and fill it in */
240 pPMKElement = pmkCacheNewElement(priv);
241
242 /* Update the key union with the BSSID */
243 memcpy(util_fns, pPMKElement->key.Bssid,
244 pBssid, sizeof(pPMKElement->key.Bssid));
245
246 /* Set the length to a value that is invalid for
247 ** an SSID. The invalid value will flag the entry as a PMK
248 */
249 pPMKElement->length = BSSID_FLAG;
250 }
251
252 if (pPMK) {
253 memcpy(util_fns, pPMKElement->PMK, pPMK, MAX_PMK_SIZE);
254 }
255 }
256
257 void
pmkCacheAddPSK(void * priv,UINT8 * pSsid,UINT8 ssidLen,UINT8 * pPSK,UINT8 * pPassphrase)258 pmkCacheAddPSK(void *priv, UINT8 *pSsid, UINT8 ssidLen, UINT8 *pPSK,
259 UINT8 *pPassphrase)
260 {
261 phostsa_private psapriv = (phostsa_private)priv;
262 hostsa_util_fns *util_fns = &psapriv->util_fns;
263 pmkElement_t *pPMKElement;
264
265 #if 0 //!defined(REMOVE_PATCH_HOOKS)
266 if (pmkCacheAddPSK_hook(pSsid, ssidLen, pPSK)) {
267 return;
268 }
269 #endif
270
271 pPMKElement = pmkCacheFindPSKElement(priv, pSsid, ssidLen);
272
273 if (NULL == pPMKElement) {
274 /* Entry not found. Create a new entry and fill it in */
275 pPMKElement = pmkCacheNewElement(priv);
276
277 /* Update the key portion with the SSID */
278 memcpy(util_fns, pPMKElement->key.Ssid, pSsid, ssidLen);
279
280 pPMKElement->length = ssidLen;
281 }
282
283 if (pPSK) {
284 memcpy(util_fns, pPMKElement->PMK, pPSK, MAX_PMK_SIZE);
285 }
286
287 if (pPassphrase)
288 memcpy(util_fns, pPMKElement->passphrase, pPassphrase,
289 PSK_PASS_PHRASE_LEN_MAX);
290
291 }
292
293 void
pmkCacheDeletePMK(void * priv,t_u8 * pBssid)294 pmkCacheDeletePMK(void *priv, t_u8 *pBssid)
295 {
296 phostsa_private psapriv = (phostsa_private)priv;
297 hostsa_util_fns *util_fns = &psapriv->util_fns;
298 pmkElement_t *pPMKElement =
299 pmkCacheFindPMKElement(priv, (IEEEtypes_MacAddr_t *)pBssid);
300
301 if (pPMKElement) {
302 /* Invalidate the enrty by setting the memory for the
303 ** cache entry to zero.
304 ** This will ensure that the replacementRank is zero
305 */
306 memset(util_fns, pPMKElement, 0x00, sizeof(pmkElement_t));
307 replacementRankMax--;
308 }
309 }
310
311 void
pmkCacheDeletePSK(void * priv,UINT8 * pSsid,UINT8 ssidLen)312 pmkCacheDeletePSK(void *priv, UINT8 *pSsid, UINT8 ssidLen)
313 {
314 phostsa_private psapriv = (phostsa_private)priv;
315 hostsa_util_fns *util_fns = &psapriv->util_fns;
316 pmkElement_t *pPMKElement =
317 pmkCacheFindPSKElement(priv, pSsid, ssidLen);
318
319 if (pPMKElement) {
320 /* Invalidate the enrty by setting the memory for the
321 ** cache entry to zero.
322 ** This will ensure that the replacementRank is zero
323 */
324 memset(util_fns, pPMKElement, 0x00, sizeof(pmkElement_t));
325 replacementRankMax--;
326 }
327 }
328
329 UINT8
pmkCacheGetHexNibble(UINT8 nibble)330 pmkCacheGetHexNibble(UINT8 nibble)
331 {
332 if (nibble >= 'a') {
333 return (nibble - 'a' + 10);
334 }
335
336 if (nibble >= 'A') {
337 return (nibble - 'A' + 10);
338 }
339
340 return (nibble - '0');
341 }
342
343 void
pmkCacheGeneratePSK(void * priv,UINT8 * pSsid,UINT8 ssidLen,char * pPassphrase,UINT8 * pPSK)344 pmkCacheGeneratePSK(void *priv, UINT8 *pSsid,
345 UINT8 ssidLen, char *pPassphrase, UINT8 *pPSK)
346 {
347 int i;
348
349 #if 0 //!defined(REMOVE_PATCH_HOOKS)
350 if (pmkCacheGeneratePSK_hook(pSsid, ssidLen, pPassphrase, pPSK)) {
351 return;
352 }
353 #endif
354
355 if (pPSK && pPassphrase) {
356 for (i = 0; i < PSK_PASS_PHRASE_LEN_MAX; i++) {
357 if (pPassphrase[i] == 0) {
358 break;
359 }
360 }
361
362 if (i > 7 && i < PSK_PASS_PHRASE_LEN_MAX) {
363 /* bump the CPU speed for the PSK generation */
364 //ramHook_hal_SetCpuMaxSpeed();
365 Mrvl_PasswordHash((void *)priv, pPassphrase,
366 (UINT8 *)pSsid, ssidLen, pPSK);
367 //ramHook_hal_RestoreCpuSpeed();
368 } else if (i == PSK_PASS_PHRASE_LEN_MAX) {
369 /* Convert ASCII to binary */
370 for (i = 0; i < PSK_PASS_PHRASE_LEN_MAX; i += 2) {
371 pPSK[i / 2] =
372 ((pmkCacheGetHexNibble(pPassphrase[i])
373 << 4)
374 |
375 pmkCacheGetHexNibble(pPassphrase
376 [i + 1]));
377
378 }
379 }
380 }
381 }
382