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 0 : static const char * eap_gpsk_state_txt(int state)
38 : {
39 0 : switch (state) {
40 : case GPSK_1:
41 0 : return "GPSK-1";
42 : case GPSK_3:
43 0 : return "GPSK-3";
44 : case SUCCESS:
45 0 : return "SUCCESS";
46 : case FAILURE:
47 0 : return "FAILURE";
48 : default:
49 0 : return "?";
50 : }
51 : }
52 :
53 :
54 0 : static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
55 : {
56 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
57 0 : eap_gpsk_state_txt(data->state),
58 : eap_gpsk_state_txt(state));
59 0 : data->state = state;
60 0 : }
61 :
62 :
63 0 : static void * eap_gpsk_init(struct eap_sm *sm)
64 : {
65 : struct eap_gpsk_data *data;
66 :
67 0 : data = os_zalloc(sizeof(*data));
68 0 : if (data == NULL)
69 0 : return NULL;
70 0 : data->state = GPSK_1;
71 :
72 0 : data->csuite_count = 0;
73 0 : if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
74 : EAP_GPSK_CIPHER_AES)) {
75 0 : WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
76 : EAP_GPSK_VENDOR_IETF);
77 0 : WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
78 : EAP_GPSK_CIPHER_AES);
79 0 : data->csuite_count++;
80 : }
81 0 : if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
82 : EAP_GPSK_CIPHER_SHA256)) {
83 0 : WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
84 : EAP_GPSK_VENDOR_IETF);
85 0 : WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
86 : EAP_GPSK_CIPHER_SHA256);
87 0 : data->csuite_count++;
88 : }
89 :
90 0 : return data;
91 : }
92 :
93 :
94 0 : static void eap_gpsk_reset(struct eap_sm *sm, void *priv)
95 : {
96 0 : struct eap_gpsk_data *data = priv;
97 0 : os_free(data->id_peer);
98 0 : os_free(data);
99 0 : }
100 :
101 :
102 0 : 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 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1");
109 :
110 0 : 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 0 : wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
116 0 : data->rand_server, EAP_GPSK_RAND_LEN);
117 :
118 0 : len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
119 0 : data->csuite_count * sizeof(struct eap_gpsk_csuite);
120 0 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
121 : EAP_CODE_REQUEST, id);
122 0 : 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 0 : wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
130 0 : wpabuf_put_be16(req, sm->server_id_len);
131 0 : wpabuf_put_data(req, sm->server_id, sm->server_id_len);
132 0 : wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
133 0 : wpabuf_put_be16(req,
134 0 : data->csuite_count * sizeof(struct eap_gpsk_csuite));
135 0 : wpabuf_put_data(req, data->csuite_list,
136 0 : data->csuite_count * sizeof(struct eap_gpsk_csuite));
137 :
138 0 : return req;
139 : }
140 :
141 :
142 0 : 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 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
151 :
152 0 : miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
153 0 : len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
154 0 : sizeof(struct eap_gpsk_csuite) + 2 + miclen;
155 0 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
156 : EAP_CODE_REQUEST, id);
157 0 : 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 0 : wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3);
165 0 : start = wpabuf_put(req, 0);
166 :
167 0 : wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
168 0 : wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
169 0 : wpabuf_put_be16(req, sm->server_id_len);
170 0 : wpabuf_put_data(req, sm->server_id, sm->server_id_len);
171 0 : csuite = wpabuf_put(req, sizeof(*csuite));
172 0 : WPA_PUT_BE32(csuite->vendor, data->vendor);
173 0 : WPA_PUT_BE16(csuite->specifier, data->specifier);
174 :
175 : /* no PD_Payload_2 */
176 0 : wpabuf_put_be16(req, 0);
177 :
178 0 : pos = wpabuf_put(req, miclen);
179 0 : if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
180 0 : 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 0 : return req;
188 : }
189 :
190 :
191 0 : static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id)
192 : {
193 0 : struct eap_gpsk_data *data = priv;
194 :
195 0 : switch (data->state) {
196 : case GPSK_1:
197 0 : return eap_gpsk_build_gpsk_1(sm, data, id);
198 : case GPSK_3:
199 0 : 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 0 : static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv,
210 : struct wpabuf *respData)
211 : {
212 0 : struct eap_gpsk_data *data = priv;
213 : const u8 *pos;
214 : size_t len;
215 :
216 0 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
217 0 : if (pos == NULL || len < 1) {
218 0 : wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame");
219 0 : return TRUE;
220 : }
221 :
222 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos);
223 :
224 0 : if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2)
225 0 : return FALSE;
226 :
227 0 : if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4)
228 0 : 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 0 : 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 0 : if (data->state != GPSK_1)
248 0 : return;
249 :
250 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2");
251 :
252 0 : pos = payload;
253 0 : end = payload + payloadlen;
254 :
255 0 : 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 0 : alen = WPA_GET_BE16(pos);
262 0 : pos += 2;
263 0 : 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 0 : os_free(data->id_peer);
270 0 : data->id_peer = os_malloc(alen);
271 0 : 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 0 : os_memcpy(data->id_peer, pos, alen);
277 0 : data->id_peer_len = alen;
278 0 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
279 0 : data->id_peer, data->id_peer_len);
280 0 : pos += alen;
281 :
282 0 : 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 0 : alen = WPA_GET_BE16(pos);
289 0 : pos += 2;
290 0 : 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 0 : if (alen != sm->server_id_len ||
297 0 : 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 0 : pos += alen;
304 :
305 0 : 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 0 : os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
312 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
313 0 : data->rand_peer, EAP_GPSK_RAND_LEN);
314 0 : pos += EAP_GPSK_RAND_LEN;
315 :
316 0 : 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 0 : 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 0 : pos += EAP_GPSK_RAND_LEN;
333 :
334 0 : 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 0 : alen = WPA_GET_BE16(pos);
341 0 : pos += 2;
342 0 : 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 0 : if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
349 0 : 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 0 : pos += alen;
356 :
357 0 : 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 0 : csuite = (const struct eap_gpsk_csuite *) pos;
364 0 : for (i = 0; i < data->csuite_count; i++) {
365 0 : if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
366 : == 0)
367 0 : break;
368 : }
369 0 : 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 0 : data->vendor = WPA_GET_BE32(csuite->vendor);
378 0 : data->specifier = WPA_GET_BE16(csuite->specifier);
379 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
380 : data->vendor, data->specifier);
381 0 : pos += sizeof(*csuite);
382 :
383 0 : 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 0 : alen = WPA_GET_BE16(pos);
390 0 : pos += 2;
391 0 : 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 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
398 0 : pos += alen;
399 :
400 0 : 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 0 : if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
408 : data->vendor, data->specifier,
409 0 : data->rand_peer, data->rand_server,
410 0 : data->id_peer, data->id_peer_len,
411 : sm->server_id, sm->server_id_len,
412 0 : data->msk, data->emsk,
413 0 : data->sk, &data->sk_len,
414 0 : 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 0 : miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
421 0 : 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 0 : if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
430 0 : 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 0 : if (os_memcmp(mic, pos, miclen) != 0) {
437 0 : wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
438 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
439 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
440 0 : eap_gpsk_state(data, FAILURE);
441 0 : return;
442 : }
443 0 : pos += miclen;
444 :
445 0 : 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 0 : eap_gpsk_state(data, GPSK_3);
452 : }
453 :
454 :
455 0 : 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 0 : if (data->state != GPSK_3)
465 0 : return;
466 :
467 0 : wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");
468 :
469 0 : pos = payload;
470 0 : end = payload + payloadlen;
471 :
472 0 : 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 0 : alen = WPA_GET_BE16(pos);
479 0 : pos += 2;
480 0 : 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 0 : wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
487 0 : pos += alen;
488 :
489 0 : miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
490 0 : 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 0 : if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
499 0 : 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 0 : 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 0 : pos += miclen;
513 :
514 0 : 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 0 : eap_gpsk_state(data, SUCCESS);
521 : }
522 :
523 :
524 0 : static void eap_gpsk_process(struct eap_sm *sm, void *priv,
525 : struct wpabuf *respData)
526 : {
527 0 : struct eap_gpsk_data *data = priv;
528 : const u8 *pos;
529 : size_t len;
530 :
531 0 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
532 0 : if (pos == NULL || len < 1)
533 0 : return;
534 :
535 0 : switch (*pos) {
536 : case EAP_GPSK_OPCODE_GPSK_2:
537 0 : eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1);
538 0 : break;
539 : case EAP_GPSK_OPCODE_GPSK_4:
540 0 : eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1);
541 0 : break;
542 : }
543 : }
544 :
545 :
546 0 : static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv)
547 : {
548 0 : struct eap_gpsk_data *data = priv;
549 0 : return data->state == SUCCESS || data->state == FAILURE;
550 : }
551 :
552 :
553 0 : static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
554 : {
555 0 : struct eap_gpsk_data *data = priv;
556 : u8 *key;
557 :
558 0 : if (data->state != SUCCESS)
559 0 : return NULL;
560 :
561 0 : key = os_malloc(EAP_MSK_LEN);
562 0 : if (key == NULL)
563 0 : return NULL;
564 0 : os_memcpy(key, data->msk, EAP_MSK_LEN);
565 0 : *len = EAP_MSK_LEN;
566 :
567 0 : 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 0 : static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv)
590 : {
591 0 : struct eap_gpsk_data *data = priv;
592 0 : return data->state == SUCCESS;
593 : }
594 :
595 :
596 1 : int eap_server_gpsk_register(void)
597 : {
598 : struct eap_method *eap;
599 : int ret;
600 :
601 1 : eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
602 : EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
603 1 : if (eap == NULL)
604 0 : return -1;
605 :
606 1 : eap->init = eap_gpsk_init;
607 1 : eap->reset = eap_gpsk_reset;
608 1 : eap->buildReq = eap_gpsk_buildReq;
609 1 : eap->check = eap_gpsk_check;
610 1 : eap->process = eap_gpsk_process;
611 1 : eap->isDone = eap_gpsk_isDone;
612 1 : eap->getKey = eap_gpsk_getKey;
613 1 : eap->isSuccess = eap_gpsk_isSuccess;
614 1 : eap->get_emsk = eap_gpsk_get_emsk;
615 :
616 1 : ret = eap_server_method_register(eap);
617 1 : if (ret)
618 0 : eap_server_method_free(eap);
619 1 : return ret;
620 : }
|