Line data Source code
1 : /*
2 : * hostapd / EAP-GPSK (RFC 5433) server
3 : * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "crypto/random.h"
13 : #include "eap_server/eap_i.h"
14 : #include "eap_common/eap_gpsk_common.h"
15 :
16 :
17 : struct eap_gpsk_data {
18 : enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state;
19 : u8 rand_server[EAP_GPSK_RAND_LEN];
20 : u8 rand_peer[EAP_GPSK_RAND_LEN];
21 : u8 msk[EAP_MSK_LEN];
22 : u8 emsk[EAP_EMSK_LEN];
23 : u8 sk[EAP_GPSK_MAX_SK_LEN];
24 : size_t sk_len;
25 : u8 pk[EAP_GPSK_MAX_PK_LEN];
26 : size_t pk_len;
27 : u8 *id_peer;
28 : size_t id_peer_len;
29 : #define MAX_NUM_CSUITES 2
30 : struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES];
31 : size_t csuite_count;
32 : int vendor; /* CSuite/Vendor */
33 : int specifier; /* CSuite/Specifier */
34 : };
35 :
36 :
37 78 : static const char * eap_gpsk_state_txt(int state)
38 : {
39 78 : switch (state) {
40 : case GPSK_1:
41 20 : return "GPSK-1";
42 : case GPSK_3:
43 38 : return "GPSK-3";
44 : case SUCCESS:
45 19 : return "SUCCESS";
46 : case FAILURE:
47 1 : return "FAILURE";
48 : default:
49 0 : return "?";
50 : }
51 : }
52 :
53 :
54 39 : static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
55 : {
56 78 : wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
57 39 : eap_gpsk_state_txt(data->state),
58 : eap_gpsk_state_txt(state));
59 39 : data->state = state;
60 39 : }
61 :
62 :
63 21 : static void * eap_gpsk_init(struct eap_sm *sm)
64 : {
65 : struct eap_gpsk_data *data;
66 :
67 21 : data = os_zalloc(sizeof(*data));
68 21 : if (data == NULL)
69 0 : return NULL;
70 21 : data->state = GPSK_1;
71 :
72 21 : data->csuite_count = 0;
73 21 : if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
74 : EAP_GPSK_CIPHER_AES)) {
75 21 : WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
76 : EAP_GPSK_VENDOR_IETF);
77 21 : WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
78 : EAP_GPSK_CIPHER_AES);
79 21 : data->csuite_count++;
80 : }
81 21 : if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
82 : EAP_GPSK_CIPHER_SHA256)) {
83 21 : WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
84 : EAP_GPSK_VENDOR_IETF);
85 21 : WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
86 : EAP_GPSK_CIPHER_SHA256);
87 21 : data->csuite_count++;
88 : }
89 :
90 21 : return data;
91 : }
92 :
93 :
94 21 : static void eap_gpsk_reset(struct eap_sm *sm, void *priv)
95 : {
96 21 : struct eap_gpsk_data *data = priv;
97 21 : os_free(data->id_peer);
98 21 : os_free(data);
99 21 : }
100 :
101 :
102 21 : static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm,
103 : struct eap_gpsk_data *data, u8 id)
104 : {
105 : size_t len;
106 : struct wpabuf *req;
107 :
108 21 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1");
109 :
110 21 : if (random_get_bytes(data->rand_server, EAP_GPSK_RAND_LEN)) {
111 0 : wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data");
112 0 : eap_gpsk_state(data, FAILURE);
113 0 : return NULL;
114 : }
115 21 : wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
116 21 : data->rand_server, EAP_GPSK_RAND_LEN);
117 :
118 42 : len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
119 21 : data->csuite_count * sizeof(struct eap_gpsk_csuite);
120 21 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
121 : EAP_CODE_REQUEST, id);
122 21 : if (req == NULL) {
123 0 : wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
124 : "for request/GPSK-1");
125 0 : eap_gpsk_state(data, FAILURE);
126 0 : return NULL;
127 : }
128 :
129 21 : wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
130 21 : wpabuf_put_be16(req, sm->server_id_len);
131 21 : wpabuf_put_data(req, sm->server_id, sm->server_id_len);
132 21 : wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
133 21 : wpabuf_put_be16(req,
134 21 : data->csuite_count * sizeof(struct eap_gpsk_csuite));
135 21 : wpabuf_put_data(req, data->csuite_list,
136 21 : data->csuite_count * sizeof(struct eap_gpsk_csuite));
137 :
138 21 : return req;
139 : }
140 :
141 :
142 19 : static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm,
143 : struct eap_gpsk_data *data, u8 id)
144 : {
145 : u8 *pos, *start;
146 : size_t len, miclen;
147 : struct eap_gpsk_csuite *csuite;
148 : struct wpabuf *req;
149 :
150 19 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
151 :
152 19 : miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
153 38 : len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
154 19 : sizeof(struct eap_gpsk_csuite) + 2 + miclen;
155 19 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
156 : EAP_CODE_REQUEST, id);
157 19 : if (req == NULL) {
158 0 : wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
159 : "for request/GPSK-3");
160 0 : eap_gpsk_state(data, FAILURE);
161 0 : return NULL;
162 : }
163 :
164 19 : wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3);
165 19 : start = wpabuf_put(req, 0);
166 :
167 19 : wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
168 19 : wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
169 19 : wpabuf_put_be16(req, sm->server_id_len);
170 19 : wpabuf_put_data(req, sm->server_id, sm->server_id_len);
171 19 : csuite = wpabuf_put(req, sizeof(*csuite));
172 19 : WPA_PUT_BE32(csuite->vendor, data->vendor);
173 19 : WPA_PUT_BE16(csuite->specifier, data->specifier);
174 :
175 : /* no PD_Payload_2 */
176 19 : wpabuf_put_be16(req, 0);
177 :
178 19 : pos = wpabuf_put(req, miclen);
179 19 : if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
180 19 : data->specifier, start, pos - start, pos) < 0)
181 : {
182 0 : os_free(req);
183 0 : eap_gpsk_state(data, FAILURE);
184 0 : return NULL;
185 : }
186 :
187 19 : return req;
188 : }
189 :
190 :
191 40 : static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id)
192 : {
193 40 : struct eap_gpsk_data *data = priv;
194 :
195 40 : switch (data->state) {
196 : case GPSK_1:
197 21 : return eap_gpsk_build_gpsk_1(sm, data, id);
198 : case GPSK_3:
199 19 : return eap_gpsk_build_gpsk_3(sm, data, id);
200 : default:
201 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq",
202 0 : data->state);
203 0 : break;
204 : }
205 0 : return NULL;
206 : }
207 :
208 :
209 39 : static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv,
210 : struct wpabuf *respData)
211 : {
212 39 : struct eap_gpsk_data *data = priv;
213 : const u8 *pos;
214 : size_t len;
215 :
216 39 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
217 39 : if (pos == NULL || len < 1) {
218 0 : wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame");
219 0 : return TRUE;
220 : }
221 :
222 39 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos);
223 :
224 39 : if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2)
225 20 : return FALSE;
226 :
227 19 : if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4)
228 19 : return FALSE;
229 :
230 0 : wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d",
231 0 : *pos, data->state);
232 :
233 0 : return TRUE;
234 : }
235 :
236 :
237 20 : static void eap_gpsk_process_gpsk_2(struct eap_sm *sm,
238 : struct eap_gpsk_data *data,
239 : const u8 *payload, size_t payloadlen)
240 : {
241 : const u8 *pos, *end;
242 : u16 alen;
243 : const struct eap_gpsk_csuite *csuite;
244 : size_t i, miclen;
245 : u8 mic[EAP_GPSK_MAX_MIC_LEN];
246 :
247 20 : if (data->state != GPSK_1)
248 1 : return;
249 :
250 20 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2");
251 :
252 20 : pos = payload;
253 20 : end = payload + payloadlen;
254 :
255 20 : if (end - pos < 2) {
256 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
257 : "ID_Peer length");
258 0 : eap_gpsk_state(data, FAILURE);
259 0 : return;
260 : }
261 20 : alen = WPA_GET_BE16(pos);
262 20 : pos += 2;
263 20 : if (end - pos < alen) {
264 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
265 : "ID_Peer");
266 0 : eap_gpsk_state(data, FAILURE);
267 0 : return;
268 : }
269 20 : os_free(data->id_peer);
270 20 : data->id_peer = os_malloc(alen);
271 20 : if (data->id_peer == NULL) {
272 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store "
273 : "%d-octet ID_Peer", alen);
274 0 : return;
275 : }
276 20 : os_memcpy(data->id_peer, pos, alen);
277 20 : data->id_peer_len = alen;
278 40 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
279 20 : data->id_peer, data->id_peer_len);
280 20 : pos += alen;
281 :
282 20 : if (end - pos < 2) {
283 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
284 : "ID_Server length");
285 0 : eap_gpsk_state(data, FAILURE);
286 0 : return;
287 : }
288 20 : alen = WPA_GET_BE16(pos);
289 20 : pos += 2;
290 20 : if (end - pos < alen) {
291 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
292 : "ID_Server");
293 0 : eap_gpsk_state(data, FAILURE);
294 0 : return;
295 : }
296 40 : if (alen != sm->server_id_len ||
297 20 : os_memcmp(pos, sm->server_id, alen) != 0) {
298 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
299 : "GPSK-2 did not match");
300 0 : eap_gpsk_state(data, FAILURE);
301 0 : return;
302 : }
303 20 : pos += alen;
304 :
305 20 : if (end - pos < EAP_GPSK_RAND_LEN) {
306 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
307 : "RAND_Peer");
308 0 : eap_gpsk_state(data, FAILURE);
309 0 : return;
310 : }
311 20 : os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
312 20 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
313 20 : data->rand_peer, EAP_GPSK_RAND_LEN);
314 20 : pos += EAP_GPSK_RAND_LEN;
315 :
316 20 : if (end - pos < EAP_GPSK_RAND_LEN) {
317 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
318 : "RAND_Server");
319 0 : eap_gpsk_state(data, FAILURE);
320 0 : return;
321 : }
322 20 : if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) {
323 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
324 : "GPSK-2 did not match");
325 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
326 0 : data->rand_server, EAP_GPSK_RAND_LEN);
327 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2",
328 : pos, EAP_GPSK_RAND_LEN);
329 0 : eap_gpsk_state(data, FAILURE);
330 0 : return;
331 : }
332 20 : pos += EAP_GPSK_RAND_LEN;
333 :
334 20 : if (end - pos < 2) {
335 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
336 : "CSuite_List length");
337 0 : eap_gpsk_state(data, FAILURE);
338 0 : return;
339 : }
340 20 : alen = WPA_GET_BE16(pos);
341 20 : pos += 2;
342 20 : if (end - pos < alen) {
343 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
344 : "CSuite_List");
345 0 : eap_gpsk_state(data, FAILURE);
346 0 : return;
347 : }
348 40 : if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
349 20 : os_memcmp(pos, data->csuite_list, alen) != 0) {
350 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and "
351 : "GPSK-2 did not match");
352 0 : eap_gpsk_state(data, FAILURE);
353 0 : return;
354 : }
355 20 : pos += alen;
356 :
357 20 : if (end - pos < (int) sizeof(*csuite)) {
358 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
359 : "CSuite_Sel");
360 0 : eap_gpsk_state(data, FAILURE);
361 0 : return;
362 : }
363 20 : csuite = (const struct eap_gpsk_csuite *) pos;
364 21 : for (i = 0; i < data->csuite_count; i++) {
365 21 : if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
366 : == 0)
367 20 : break;
368 : }
369 20 : if (i == data->csuite_count) {
370 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported "
371 : "ciphersuite %d:%d",
372 0 : WPA_GET_BE32(csuite->vendor),
373 0 : WPA_GET_BE16(csuite->specifier));
374 0 : eap_gpsk_state(data, FAILURE);
375 0 : return;
376 : }
377 20 : data->vendor = WPA_GET_BE32(csuite->vendor);
378 20 : data->specifier = WPA_GET_BE16(csuite->specifier);
379 20 : wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
380 : data->vendor, data->specifier);
381 20 : pos += sizeof(*csuite);
382 :
383 20 : if (end - pos < 2) {
384 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
385 : "PD_Payload_1 length");
386 0 : eap_gpsk_state(data, FAILURE);
387 0 : return;
388 : }
389 20 : alen = WPA_GET_BE16(pos);
390 20 : pos += 2;
391 20 : if (end - pos < alen) {
392 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
393 : "PD_Payload_1");
394 0 : eap_gpsk_state(data, FAILURE);
395 0 : return;
396 : }
397 20 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
398 20 : pos += alen;
399 :
400 20 : if (sm->user == NULL || sm->user->password == NULL) {
401 0 : wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured "
402 : "for the user");
403 0 : eap_gpsk_state(data, FAILURE);
404 0 : return;
405 : }
406 :
407 80 : if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
408 : data->vendor, data->specifier,
409 20 : data->rand_peer, data->rand_server,
410 20 : data->id_peer, data->id_peer_len,
411 : sm->server_id, sm->server_id_len,
412 20 : data->msk, data->emsk,
413 20 : data->sk, &data->sk_len,
414 20 : data->pk, &data->pk_len) < 0) {
415 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
416 0 : eap_gpsk_state(data, FAILURE);
417 0 : return;
418 : }
419 :
420 20 : miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
421 20 : if (end - pos < (int) miclen) {
422 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
423 : "(left=%lu miclen=%lu)",
424 0 : (unsigned long) (end - pos),
425 : (unsigned long) miclen);
426 0 : eap_gpsk_state(data, FAILURE);
427 0 : return;
428 : }
429 20 : if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
430 20 : data->specifier, payload, pos - payload, mic)
431 : < 0) {
432 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
433 0 : eap_gpsk_state(data, FAILURE);
434 0 : return;
435 : }
436 20 : if (os_memcmp(mic, pos, miclen) != 0) {
437 1 : wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
438 1 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
439 1 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
440 1 : eap_gpsk_state(data, FAILURE);
441 1 : return;
442 : }
443 19 : pos += miclen;
444 :
445 19 : if (pos != end) {
446 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
447 : "data in the end of GPSK-2",
448 0 : (unsigned long) (end - pos));
449 : }
450 :
451 19 : eap_gpsk_state(data, GPSK_3);
452 : }
453 :
454 :
455 19 : static void eap_gpsk_process_gpsk_4(struct eap_sm *sm,
456 : struct eap_gpsk_data *data,
457 : const u8 *payload, size_t payloadlen)
458 : {
459 : const u8 *pos, *end;
460 : u16 alen;
461 : size_t miclen;
462 : u8 mic[EAP_GPSK_MAX_MIC_LEN];
463 :
464 19 : if (data->state != GPSK_3)
465 0 : return;
466 :
467 19 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");
468 :
469 19 : pos = payload;
470 19 : end = payload + payloadlen;
471 :
472 19 : if (end - pos < 2) {
473 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
474 : "PD_Payload_1 length");
475 0 : eap_gpsk_state(data, FAILURE);
476 0 : return;
477 : }
478 19 : alen = WPA_GET_BE16(pos);
479 19 : pos += 2;
480 19 : if (end - pos < alen) {
481 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
482 : "PD_Payload_1");
483 0 : eap_gpsk_state(data, FAILURE);
484 0 : return;
485 : }
486 19 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
487 19 : pos += alen;
488 :
489 19 : miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
490 19 : if (end - pos < (int) miclen) {
491 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
492 : "(left=%lu miclen=%lu)",
493 0 : (unsigned long) (end - pos),
494 : (unsigned long) miclen);
495 0 : eap_gpsk_state(data, FAILURE);
496 0 : return;
497 : }
498 19 : if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
499 19 : data->specifier, payload, pos - payload, mic)
500 : < 0) {
501 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
502 0 : eap_gpsk_state(data, FAILURE);
503 0 : return;
504 : }
505 19 : if (os_memcmp(mic, pos, miclen) != 0) {
506 0 : wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4");
507 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
508 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
509 0 : eap_gpsk_state(data, FAILURE);
510 0 : return;
511 : }
512 19 : pos += miclen;
513 :
514 19 : if (pos != end) {
515 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
516 : "data in the end of GPSK-4",
517 0 : (unsigned long) (end - pos));
518 : }
519 :
520 19 : eap_gpsk_state(data, SUCCESS);
521 : }
522 :
523 :
524 39 : static void eap_gpsk_process(struct eap_sm *sm, void *priv,
525 : struct wpabuf *respData)
526 : {
527 39 : struct eap_gpsk_data *data = priv;
528 : const u8 *pos;
529 : size_t len;
530 :
531 39 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
532 39 : if (pos == NULL || len < 1)
533 39 : return;
534 :
535 39 : switch (*pos) {
536 : case EAP_GPSK_OPCODE_GPSK_2:
537 20 : eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1);
538 20 : break;
539 : case EAP_GPSK_OPCODE_GPSK_4:
540 19 : eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1);
541 19 : break;
542 : }
543 : }
544 :
545 :
546 40 : static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv)
547 : {
548 40 : struct eap_gpsk_data *data = priv;
549 40 : return data->state == SUCCESS || data->state == FAILURE;
550 : }
551 :
552 :
553 20 : static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
554 : {
555 20 : struct eap_gpsk_data *data = priv;
556 : u8 *key;
557 :
558 20 : if (data->state != SUCCESS)
559 1 : return NULL;
560 :
561 19 : key = os_malloc(EAP_MSK_LEN);
562 19 : if (key == NULL)
563 0 : return NULL;
564 19 : os_memcpy(key, data->msk, EAP_MSK_LEN);
565 19 : *len = EAP_MSK_LEN;
566 :
567 19 : return key;
568 : }
569 :
570 :
571 0 : static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
572 : {
573 0 : struct eap_gpsk_data *data = priv;
574 : u8 *key;
575 :
576 0 : if (data->state != SUCCESS)
577 0 : return NULL;
578 :
579 0 : key = os_malloc(EAP_EMSK_LEN);
580 0 : if (key == NULL)
581 0 : return NULL;
582 0 : os_memcpy(key, data->emsk, EAP_EMSK_LEN);
583 0 : *len = EAP_EMSK_LEN;
584 :
585 0 : return key;
586 : }
587 :
588 :
589 21 : static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv)
590 : {
591 21 : struct eap_gpsk_data *data = priv;
592 21 : return data->state == SUCCESS;
593 : }
594 :
595 :
596 2 : int eap_server_gpsk_register(void)
597 : {
598 : struct eap_method *eap;
599 : int ret;
600 :
601 2 : eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
602 : EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
603 2 : if (eap == NULL)
604 0 : return -1;
605 :
606 2 : eap->init = eap_gpsk_init;
607 2 : eap->reset = eap_gpsk_reset;
608 2 : eap->buildReq = eap_gpsk_buildReq;
609 2 : eap->check = eap_gpsk_check;
610 2 : eap->process = eap_gpsk_process;
611 2 : eap->isDone = eap_gpsk_isDone;
612 2 : eap->getKey = eap_gpsk_getKey;
613 2 : eap->isSuccess = eap_gpsk_isSuccess;
614 2 : eap->get_emsk = eap_gpsk_get_emsk;
615 :
616 2 : ret = eap_server_method_register(eap);
617 2 : if (ret)
618 0 : eap_server_method_free(eap);
619 2 : return ret;
620 : }
|