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