1 /** @file pmkcache.c
2 *
3 * @brief This file defines pmk cache functions
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 "pass_phrase.h"
27 #include "pmkCache.h"
28 #include "hostsa_ext_def.h"
29 #include "authenticator.h"
30 #include "tlv.h"
31 #include "keyMgmtApStaCommon.h"
32
33 #define MAX_PMK_CACHE_ENTRIES 10
34
35 pmkElement_t pmkCache[MAX_PMK_CACHE_ENTRIES];
36
37 char PSKPassPhrase[PSK_PASS_PHRASE_LEN_MAX];
38 /*
39 ** Replacement rank is used to determine which cache entry to replace
40 ** once the cache is full. The rank order is determined by usage. The
41 ** least recently used cache element is the first to be replaced.
42 **
43 ** replacementRankMax is an indication of the number of cache entries used.
44 ** It is used to determine the rank of the current cache entry used.
45 **
46 ** Rank order goes from 1 to MAX_PMK_CACHE_ENTRIES. If the cache is full,
47 ** the element with rank 1 is first to be replaced.
48 **
49 ** Replacement rank of zero indicates that the entry is invalid.
50 */
51
52 UINT8 *
pmkCacheFindPSK(void * priv,UINT8 * pSsid,UINT8 ssidLen)53 pmkCacheFindPSK(void *priv, UINT8 *pSsid, UINT8 ssidLen)
54 {
55 UINT8 *pPMK = NULL;
56 pmkElement_t *pPMKElement;
57
58 if (!pPMK) {
59 /* extract the PSK from the cache entry */
60 pPMKElement =
61 pmkCacheFindPSKElement((void *)priv, pSsid, ssidLen);
62 if (pPMKElement) {
63 pPMK = pPMKElement->PMK;
64 } else if ('\0' != PSKPassPhrase[0]) {
65 /* Generate a new PSK entry with the
66 ** provided passphrase.
67 */
68 pmkCacheAddPSK((void *)priv, pSsid, ssidLen, NULL,
69 PSKPassPhrase);
70 pPMKElement =
71 pmkCacheFindPSKElement((void *)priv, pSsid,
72 ssidLen);
73 pmkCacheGeneratePSK((void *)priv, pSsid, ssidLen,
74 PSKPassPhrase, pPMKElement->PMK);
75 pPMK = pPMKElement->PMK;
76 }
77 }
78
79 return pPMK;
80 }
81
82 UINT8 *
pmkCacheFindPassphrase(void * priv,UINT8 * pSsid,UINT8 ssidLen)83 pmkCacheFindPassphrase(void *priv, UINT8 *pSsid, UINT8 ssidLen)
84 {
85 UINT8 *pPassphrase = NULL;
86 pmkElement_t *pPMKElement;
87
88 if (!pPassphrase) {
89 /* extract the PSK from the cache entry */
90 pPMKElement =
91 pmkCacheFindPSKElement((void *)priv, pSsid, ssidLen);
92 if (pPMKElement) {
93 pPassphrase = pPMKElement->passphrase;
94 }
95
96 }
97
98 return pPassphrase;
99 }
100
101 void
pmkCacheSetPassphrase(void * priv,char * pPassphrase)102 pmkCacheSetPassphrase(void *priv, char *pPassphrase)
103 {
104 phostsa_private psapriv = (phostsa_private)priv;
105 hostsa_util_fns *util_fns = &psapriv->util_fns;
106
107 if (pPassphrase != NULL) {
108 memcpy(util_fns, PSKPassPhrase,
109 pPassphrase, sizeof(PSKPassPhrase));
110 }
111 }
112
113 void
pmkCacheGetPassphrase(void * priv,char * pPassphrase)114 pmkCacheGetPassphrase(void *priv, char *pPassphrase)
115 {
116 phostsa_private psapriv = (phostsa_private)priv;
117 hostsa_util_fns *util_fns = &psapriv->util_fns;
118
119 if (pPassphrase != NULL) {
120 memcpy(util_fns, pPassphrase,
121 PSKPassPhrase, sizeof(PSKPassPhrase));
122 }
123 }
124
125 void
pmkCacheInit(void * priv)126 pmkCacheInit(void *priv)
127 {
128 phostsa_private psapriv = (phostsa_private)priv;
129 hostsa_util_fns *util_fns = &psapriv->util_fns;
130
131 memset(util_fns, pmkCache, 0x00, sizeof(pmkCache));
132 memset(util_fns, PSKPassPhrase, 0x00, sizeof(PSKPassPhrase));
133 replacementRankMax = 0;
134 }
135
136 void
pmkCacheFlush(void * priv)137 pmkCacheFlush(void *priv)
138 {
139 phostsa_private psapriv = (phostsa_private)priv;
140 hostsa_util_fns *util_fns = &psapriv->util_fns;
141
142 memset(util_fns, pmkCache, 0x00, sizeof(pmkCache));
143 replacementRankMax = 0;
144 }
145
146 //#pragma arm section code = ".init"
147 void
pmkCacheRomInit(void)148 pmkCacheRomInit(void)
149 {
150 ramHook_MAX_PMK_CACHE_ENTRIES = MAX_PMK_CACHE_ENTRIES;
151 ramHook_pmkCache = &pmkCache[0];
152 ramHook_PSKPassPhrase = &PSKPassPhrase[0];
153 // ramHook_hal_SetCpuMaxSpeed = hal_SetCpuOpToSecuritySpeed;
154 // ramHook_hal_RestoreCpuSpeed = cm_SetPerformanceParams;
155 }
156
157 //#pragma arm section code
158
159 #ifdef DRV_EMBEDDED_SUPPLICANT
160
161 t_u16
SupplicantSetPassphrase(void * priv,void * pPassphraseBuf)162 SupplicantSetPassphrase(void *priv, void *pPassphraseBuf)
163 {
164 phostsa_private psapriv = (phostsa_private)priv;
165 hostsa_util_fns *util_fns = NULL;
166 mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pPassphraseBuf;
167 IEEEtypes_MacAddr_t *pBssid = NULL;
168 UINT8 *pPMK = NULL;
169 UINT8 Passphrase[PSK_PASS_PHRASE_LEN_MAX], *pPassphrase = NULL;
170 UINT8 *pSsid = NULL;
171 UINT8 ssidLen = 0;
172 UINT16 retVal = 0;
173 t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
174
175 if (!psapriv)
176 return retVal;
177 util_fns = &psapriv->util_fns;
178
179 if (memcmp(util_fns, (t_u8 *)&psk->bssid, zero_mac, sizeof(zero_mac)))
180 pBssid = (IEEEtypes_MacAddr_t *)&psk->bssid;
181
182 ssidLen = psk->ssid.ssid_len;
183 if (ssidLen > 0)
184 pSsid = psk->ssid.ssid;
185
186 if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
187 pPassphrase = psk->psk.passphrase.passphrase;
188 memset(util_fns, Passphrase, 0x00, sizeof(Passphrase));
189 memcpy(util_fns, Passphrase, pPassphrase,
190 MIN(MLAN_MAX_PASSPHRASE_LENGTH,
191 psk->psk.passphrase.passphrase_len));
192 }
193
194 if (psk->psk_type == MLAN_PSK_PMK)
195 pPMK = psk->psk.pmk.pmk;
196
197 /* Always enable the supplicant on a set */
198 // supplicantEnable(priv);
199
200 if (pBssid && pPMK) {
201 pmkCacheAddPMK(priv, pBssid, pPMK);
202 } else if (pSsid) {
203 if (pPMK) {
204 pmkCacheAddPSK(priv, pSsid, ssidLen, pPMK, NULL);
205 } else if (pPassphrase) {
206 pmkCacheAddPSK(priv, pSsid, ssidLen, NULL, Passphrase);
207 pPMK = pmkCacheFindPSK(priv, pSsid, ssidLen);
208 pmkCacheGeneratePSK(priv, pSsid, ssidLen,
209 (char *)Passphrase, pPMK);
210 } else {
211 /* Just an SSID so we can't set anything in the cache */
212 retVal = 1;
213 }
214 } else if (pPassphrase) {
215 memcpy(util_fns, PSKPassPhrase, Passphrase, sizeof(Passphrase));
216 } else {
217 /* Not enough data to set anything in the cache */
218 retVal = 1;
219 }
220
221 return retVal;
222 }
223
224 BOOLEAN
SupplicantClearPMK_internal(void * priv,void * pPassphraseBuf)225 SupplicantClearPMK_internal(void *priv, void *pPassphraseBuf)
226 {
227 phostsa_private psapriv = (phostsa_private)priv;
228 hostsa_util_fns *util_fns = &psapriv->util_fns;
229 mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pPassphraseBuf;
230 IEEEtypes_MacAddr_t *pBssid = NULL;
231 UINT8 *pPassphrase = NULL;
232 UINT8 *pSsid = NULL;
233 UINT8 ssidLen = 0;
234 t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
235
236 if (memcmp(util_fns, (t_u8 *)&psk->bssid, zero_mac, sizeof(zero_mac)))
237 pBssid = (IEEEtypes_MacAddr_t *)&psk->bssid;
238
239 ssidLen = psk->ssid.ssid_len;
240 if (ssidLen > 0)
241 pSsid = psk->ssid.ssid;
242
243 if (psk->psk_type == MLAN_PSK_PASSPHRASE)
244 pPassphrase = psk->psk.passphrase.passphrase;
245
246 if (pBssid) {
247 pmkCacheDeletePMK(priv, (UINT8 *)pBssid);
248 } else if (pSsid) {
249 pmkCacheDeletePSK(priv, pSsid, ssidLen);
250 } else if (pPassphrase) {
251 /* Clear the global passphrase by setting it to blank */
252 memset(util_fns, ramHook_PSKPassPhrase, 0x00,
253 PSK_PASS_PHRASE_LEN_MAX);
254 } else {
255 return FALSE;
256 }
257
258 return TRUE;
259 }
260
261 void
SupplicantClearPMK(void * priv,void * pPassphrase)262 SupplicantClearPMK(void *priv, void *pPassphrase)
263 {
264 if (!priv)
265 return;
266
267 if (!SupplicantClearPMK_internal(priv, pPassphrase)) {
268 /* Always disable the supplicant on a flush */
269 supplicantDisable(priv);
270 pmkCacheFlush(priv);
271 }
272 }
273
274 void
SupplicantQueryPassphrase(void * priv,void * pPassphraseBuf)275 SupplicantQueryPassphrase(void *priv, void *pPassphraseBuf)
276 {
277 phostsa_private psapriv = (phostsa_private)priv;
278 hostsa_util_fns *util_fns = NULL;
279 mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pPassphraseBuf;
280 UINT8 *pPassphrase = NULL;
281 UINT8 *pSsid = NULL;
282 UINT8 ssidLen = 0;
283
284 if (!psapriv)
285 return;
286
287 util_fns = &psapriv->util_fns;
288 ssidLen = psk->ssid.ssid_len;
289 pSsid = psk->ssid.ssid;
290
291 if (ssidLen) {
292 pPassphrase = pmkCacheFindPassphrase(priv, pSsid, ssidLen);
293 if (pPassphrase) {
294 psk->psk_type = MLAN_PSK_PASSPHRASE;
295 memcpy(util_fns, psk->psk.passphrase.passphrase,
296 pPassphrase, PSK_PASS_PHRASE_LEN_MAX);
297 psk->psk.passphrase.passphrase_len =
298 wlan_strlen(pPassphrase);
299 }
300 }
301
302 }
303 #endif
304