xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlan/esa/common/pmkCache_rom.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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