Branch data Line data Source code
1 : : /*
2 : : * hostapd / EAP-pwd (RFC 5931) server
3 : : * Copyright (c) 2010, Dan Harkins <dharkins@lounge.org>
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/sha256.h"
13 : : #include "eap_server/eap_i.h"
14 : : #include "eap_common/eap_pwd_common.h"
15 : :
16 : :
17 : : struct eap_pwd_data {
18 : : enum {
19 : : PWD_ID_Req, PWD_Commit_Req, PWD_Confirm_Req, SUCCESS, FAILURE
20 : : } state;
21 : : u8 *id_peer;
22 : : size_t id_peer_len;
23 : : u8 *id_server;
24 : : size_t id_server_len;
25 : : u8 *password;
26 : : size_t password_len;
27 : : u32 token;
28 : : u16 group_num;
29 : : EAP_PWD_group *grp;
30 : :
31 : : struct wpabuf *inbuf;
32 : : size_t in_frag_pos;
33 : : struct wpabuf *outbuf;
34 : : size_t out_frag_pos;
35 : : size_t mtu;
36 : :
37 : : BIGNUM *k;
38 : : BIGNUM *private_value;
39 : : BIGNUM *peer_scalar;
40 : : BIGNUM *my_scalar;
41 : : EC_POINT *my_element;
42 : : EC_POINT *peer_element;
43 : :
44 : : u8 my_confirm[SHA256_MAC_LEN];
45 : :
46 : : u8 msk[EAP_MSK_LEN];
47 : : u8 emsk[EAP_EMSK_LEN];
48 : :
49 : : BN_CTX *bnctx;
50 : : };
51 : :
52 : :
53 : 12 : static const char * eap_pwd_state_txt(int state)
54 : : {
55 [ + + + + : 12 : switch (state) {
- - ]
56 : : case PWD_ID_Req:
57 : 2 : return "PWD-ID-Req";
58 : : case PWD_Commit_Req:
59 : 4 : return "PWD-Commit-Req";
60 : : case PWD_Confirm_Req:
61 : 4 : return "PWD-Confirm-Req";
62 : : case SUCCESS:
63 : 2 : return "SUCCESS";
64 : : case FAILURE:
65 : 0 : return "FAILURE";
66 : : default:
67 : 12 : return "PWD-Unk";
68 : : }
69 : : }
70 : :
71 : :
72 : 6 : static void eap_pwd_state(struct eap_pwd_data *data, int state)
73 : : {
74 : 6 : wpa_printf(MSG_DEBUG, "EAP-pwd: %s -> %s",
75 : 6 : eap_pwd_state_txt(data->state), eap_pwd_state_txt(state));
76 : 6 : data->state = state;
77 : 6 : }
78 : :
79 : :
80 : 2 : static void * eap_pwd_init(struct eap_sm *sm)
81 : : {
82 : : struct eap_pwd_data *data;
83 : :
84 [ + - ][ + - ]: 2 : if (sm->user == NULL || sm->user->password == NULL ||
[ - + ]
85 : 2 : sm->user->password_len == 0) {
86 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): Password is not "
87 : : "configured");
88 : 0 : return NULL;
89 : : }
90 : :
91 : 2 : data = os_zalloc(sizeof(*data));
92 [ - + ]: 2 : if (data == NULL)
93 : 0 : return NULL;
94 : :
95 : 2 : data->group_num = sm->pwd_group;
96 : 2 : wpa_printf(MSG_DEBUG, "EAP-pwd: Selected group number %d",
97 : 2 : data->group_num);
98 : 2 : data->state = PWD_ID_Req;
99 : :
100 : 2 : data->id_server = (u8 *) os_strdup("server");
101 [ + - ]: 2 : if (data->id_server)
102 : 2 : data->id_server_len = os_strlen((char *) data->id_server);
103 : :
104 : 2 : data->password = os_malloc(sm->user->password_len);
105 [ - + ]: 2 : if (data->password == NULL) {
106 : 0 : wpa_printf(MSG_INFO, "EAP-PWD: Memory allocation password "
107 : : "fail");
108 : 0 : os_free(data->id_server);
109 : 0 : os_free(data);
110 : 0 : return NULL;
111 : : }
112 : 2 : data->password_len = sm->user->password_len;
113 : 2 : os_memcpy(data->password, sm->user->password, data->password_len);
114 : :
115 : 2 : data->bnctx = BN_CTX_new();
116 [ - + ]: 2 : if (data->bnctx == NULL) {
117 : 0 : wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
118 : 0 : os_free(data->password);
119 : 0 : os_free(data->id_server);
120 : 0 : os_free(data);
121 : 0 : return NULL;
122 : : }
123 : :
124 : 2 : data->in_frag_pos = data->out_frag_pos = 0;
125 : 2 : data->inbuf = data->outbuf = NULL;
126 : 2 : data->mtu = 1020; /* default from RFC 5931, make it configurable! */
127 : :
128 : 2 : return data;
129 : : }
130 : :
131 : :
132 : 2 : static void eap_pwd_reset(struct eap_sm *sm, void *priv)
133 : : {
134 : 2 : struct eap_pwd_data *data = priv;
135 : :
136 : 2 : BN_free(data->private_value);
137 : 2 : BN_free(data->peer_scalar);
138 : 2 : BN_free(data->my_scalar);
139 : 2 : BN_free(data->k);
140 : 2 : BN_CTX_free(data->bnctx);
141 : 2 : EC_POINT_free(data->my_element);
142 : 2 : EC_POINT_free(data->peer_element);
143 : 2 : os_free(data->id_peer);
144 : 2 : os_free(data->id_server);
145 : 2 : os_free(data->password);
146 [ + - ]: 2 : if (data->grp) {
147 : 2 : EC_GROUP_free(data->grp->group);
148 : 2 : EC_POINT_free(data->grp->pwe);
149 : 2 : BN_free(data->grp->order);
150 : 2 : BN_free(data->grp->prime);
151 : 2 : os_free(data->grp);
152 : : }
153 : 2 : os_free(data);
154 : 2 : }
155 : :
156 : :
157 : 2 : static void eap_pwd_build_id_req(struct eap_sm *sm, struct eap_pwd_data *data,
158 : : u8 id)
159 : : {
160 : 2 : wpa_printf(MSG_DEBUG, "EAP-pwd: ID/Request");
161 : : /*
162 : : * if we're fragmenting then we already have an id request, just return
163 : : */
164 [ - + ]: 2 : if (data->out_frag_pos)
165 : 0 : return;
166 : :
167 : 2 : data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
168 : 2 : data->id_server_len);
169 [ - + ]: 2 : if (data->outbuf == NULL) {
170 : 0 : eap_pwd_state(data, FAILURE);
171 : 0 : return;
172 : : }
173 : :
174 : : /* an lfsr is good enough to generate unpredictable tokens */
175 : 2 : data->token = os_random();
176 : 2 : wpabuf_put_be16(data->outbuf, data->group_num);
177 : 2 : wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
178 : 2 : wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
179 : 2 : wpabuf_put_data(data->outbuf, &data->token, sizeof(data->token));
180 : 2 : wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE);
181 : 2 : wpabuf_put_data(data->outbuf, data->id_server, data->id_server_len);
182 : : }
183 : :
184 : :
185 : 2 : static void eap_pwd_build_commit_req(struct eap_sm *sm,
186 : : struct eap_pwd_data *data, u8 id)
187 : : {
188 : 2 : BIGNUM *mask = NULL, *x = NULL, *y = NULL;
189 : 2 : u8 *scalar = NULL, *element = NULL;
190 : : u16 offset;
191 : :
192 : 2 : wpa_printf(MSG_DEBUG, "EAP-pwd: Commit/Request");
193 : : /*
194 : : * if we're fragmenting then we already have an commit request, just
195 : : * return
196 : : */
197 [ - + ]: 2 : if (data->out_frag_pos)
198 : 2 : return;
199 : :
200 [ + - + - ]: 4 : if (((data->private_value = BN_new()) == NULL) ||
201 [ + - ]: 4 : ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
202 [ - + ]: 4 : ((data->my_scalar = BN_new()) == NULL) ||
203 : : ((mask = BN_new()) == NULL)) {
204 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): scalar allocation "
205 : : "fail");
206 : 0 : goto fin;
207 : : }
208 : :
209 : 2 : BN_rand_range(data->private_value, data->grp->order);
210 : 2 : BN_rand_range(mask, data->grp->order);
211 : 2 : BN_add(data->my_scalar, data->private_value, mask);
212 : 2 : BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
213 : : data->bnctx);
214 : :
215 [ - + ]: 2 : if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
216 : 2 : data->grp->pwe, mask, data->bnctx)) {
217 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): element allocation "
218 : : "fail");
219 : 0 : eap_pwd_state(data, FAILURE);
220 : 0 : goto fin;
221 : : }
222 : :
223 [ - + ]: 2 : if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
224 : : {
225 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): element inversion "
226 : : "fail");
227 : 0 : goto fin;
228 : : }
229 : 2 : BN_free(mask);
230 : :
231 [ + - ][ - + ]: 2 : if (((x = BN_new()) == NULL) ||
232 : : ((y = BN_new()) == NULL)) {
233 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): point allocation "
234 : : "fail");
235 : 0 : goto fin;
236 : : }
237 [ - + ]: 2 : if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
238 : 2 : data->my_element, x, y,
239 : : data->bnctx)) {
240 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): point assignment "
241 : : "fail");
242 : 0 : goto fin;
243 : : }
244 : :
245 [ + - - + ]: 4 : if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
246 : 2 : ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
247 : : NULL)) {
248 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail");
249 : 0 : goto fin;
250 : : }
251 : :
252 : : /*
253 : : * bignums occupy as little memory as possible so one that is
254 : : * sufficiently smaller than the prime or order might need pre-pending
255 : : * with zeros.
256 : : */
257 : 2 : os_memset(scalar, 0, BN_num_bytes(data->grp->order));
258 : 2 : os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
259 : 2 : offset = BN_num_bytes(data->grp->order) -
260 : 2 : BN_num_bytes(data->my_scalar);
261 : 2 : BN_bn2bin(data->my_scalar, scalar + offset);
262 : :
263 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
264 : 2 : BN_bn2bin(x, element + offset);
265 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
266 : 2 : BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
267 : :
268 : 4 : data->outbuf = wpabuf_alloc(2 * BN_num_bytes(data->grp->prime) +
269 : 2 : BN_num_bytes(data->grp->order));
270 [ - + ]: 2 : if (data->outbuf == NULL)
271 : 0 : goto fin;
272 : :
273 : : /* We send the element as (x,y) followed by the scalar */
274 : 2 : wpabuf_put_data(data->outbuf, element,
275 : 2 : 2 * BN_num_bytes(data->grp->prime));
276 : 2 : wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
277 : :
278 : : fin:
279 : 2 : os_free(scalar);
280 : 2 : os_free(element);
281 : 2 : BN_free(x);
282 : 2 : BN_free(y);
283 [ - + ]: 2 : if (data->outbuf == NULL)
284 : 0 : eap_pwd_state(data, FAILURE);
285 : : }
286 : :
287 : :
288 : 2 : static void eap_pwd_build_confirm_req(struct eap_sm *sm,
289 : : struct eap_pwd_data *data, u8 id)
290 : : {
291 : 2 : BIGNUM *x = NULL, *y = NULL;
292 : : struct crypto_hash *hash;
293 : 2 : u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
294 : : u16 grp;
295 : : int offset;
296 : :
297 : 2 : wpa_printf(MSG_DEBUG, "EAP-pwd: Confirm/Request");
298 : : /*
299 : : * if we're fragmenting then we already have an confirm request, just
300 : : * return
301 : : */
302 [ - + ]: 2 : if (data->out_frag_pos)
303 : 2 : return;
304 : :
305 : : /* Each component of the cruft will be at most as big as the prime */
306 [ + - ][ + - ]: 2 : if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
307 [ - + ]: 2 : ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
308 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation "
309 : : "fail");
310 : 0 : goto fin;
311 : : }
312 : :
313 : : /*
314 : : * commit is H(k | server_element | server_scalar | peer_element |
315 : : * peer_scalar | ciphersuite)
316 : : */
317 : 2 : hash = eap_pwd_h_init();
318 [ - + ]: 2 : if (hash == NULL)
319 : 0 : goto fin;
320 : :
321 : : /*
322 : : * Zero the memory each time because this is mod prime math and some
323 : : * value may start with a few zeros and the previous one did not.
324 : : *
325 : : * First is k
326 : : */
327 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
328 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
329 : 2 : BN_bn2bin(data->k, cruft + offset);
330 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
331 : :
332 : : /* server element: x, y */
333 [ - + ]: 2 : if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
334 : 2 : data->my_element, x, y,
335 : : data->bnctx)) {
336 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
337 : : "assignment fail");
338 : 0 : goto fin;
339 : : }
340 : :
341 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
342 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
343 : 2 : BN_bn2bin(x, cruft + offset);
344 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
345 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
346 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
347 : 2 : BN_bn2bin(y, cruft + offset);
348 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
349 : :
350 : : /* server scalar */
351 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
352 : 2 : offset = BN_num_bytes(data->grp->order) -
353 : 2 : BN_num_bytes(data->my_scalar);
354 : 2 : BN_bn2bin(data->my_scalar, cruft + offset);
355 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
356 : :
357 : : /* peer element: x, y */
358 [ - + ]: 2 : if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
359 : 2 : data->peer_element, x, y,
360 : : data->bnctx)) {
361 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
362 : : "assignment fail");
363 : 0 : goto fin;
364 : : }
365 : :
366 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
367 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
368 : 2 : BN_bn2bin(x, cruft + offset);
369 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
370 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
371 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
372 : 2 : BN_bn2bin(y, cruft + offset);
373 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
374 : :
375 : : /* peer scalar */
376 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
377 : 2 : offset = BN_num_bytes(data->grp->order) -
378 : 2 : BN_num_bytes(data->peer_scalar);
379 : 2 : BN_bn2bin(data->peer_scalar, cruft + offset);
380 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
381 : :
382 : : /* ciphersuite */
383 : 2 : grp = htons(data->group_num);
384 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
385 : 2 : ptr = cruft;
386 : 2 : os_memcpy(ptr, &grp, sizeof(u16));
387 : 2 : ptr += sizeof(u16);
388 : 2 : *ptr = EAP_PWD_DEFAULT_RAND_FUNC;
389 : 2 : ptr += sizeof(u8);
390 : 2 : *ptr = EAP_PWD_DEFAULT_PRF;
391 : 2 : ptr += sizeof(u8);
392 : 2 : eap_pwd_h_update(hash, cruft, ptr - cruft);
393 : :
394 : : /* all done with the random function */
395 : 2 : eap_pwd_h_final(hash, conf);
396 : 2 : os_memcpy(data->my_confirm, conf, SHA256_MAC_LEN);
397 : :
398 : 2 : data->outbuf = wpabuf_alloc(SHA256_MAC_LEN);
399 [ - + ]: 2 : if (data->outbuf == NULL)
400 : 0 : goto fin;
401 : :
402 : 2 : wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
403 : :
404 : : fin:
405 : 2 : os_free(cruft);
406 : 2 : BN_free(x);
407 : 2 : BN_free(y);
408 [ - + ]: 2 : if (data->outbuf == NULL)
409 : 0 : eap_pwd_state(data, FAILURE);
410 : : }
411 : :
412 : :
413 : : static struct wpabuf *
414 : 6 : eap_pwd_build_req(struct eap_sm *sm, void *priv, u8 id)
415 : : {
416 : 6 : struct eap_pwd_data *data = priv;
417 : : struct wpabuf *req;
418 : : u8 lm_exch;
419 : : const u8 *buf;
420 : 6 : u16 totlen = 0;
421 : : size_t len;
422 : :
423 : : /*
424 : : * if we're buffering response fragments then just ACK
425 : : */
426 [ - + ]: 6 : if (data->in_frag_pos) {
427 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a fragment!!");
428 : 0 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
429 : : EAP_PWD_HDR_SIZE, EAP_CODE_REQUEST, id);
430 [ # # ]: 0 : if (req == NULL) {
431 : 0 : eap_pwd_state(data, FAILURE);
432 : 0 : return NULL;
433 : : }
434 [ # # # # ]: 0 : switch (data->state) {
435 : : case PWD_ID_Req:
436 : 0 : wpabuf_put_u8(req, EAP_PWD_OPCODE_ID_EXCH);
437 : 0 : break;
438 : : case PWD_Commit_Req:
439 : 0 : wpabuf_put_u8(req, EAP_PWD_OPCODE_COMMIT_EXCH);
440 : 0 : break;
441 : : case PWD_Confirm_Req:
442 : 0 : wpabuf_put_u8(req, EAP_PWD_OPCODE_CONFIRM_EXCH);
443 : 0 : break;
444 : : default:
445 : 0 : eap_pwd_state(data, FAILURE); /* just to be sure */
446 : 0 : wpabuf_free(req);
447 : 0 : return NULL;
448 : : }
449 : 0 : return req;
450 : : }
451 : :
452 : : /*
453 : : * build the data portion of a request
454 : : */
455 [ + + + - ]: 6 : switch (data->state) {
456 : : case PWD_ID_Req:
457 : 2 : eap_pwd_build_id_req(sm, data, id);
458 : 2 : lm_exch = EAP_PWD_OPCODE_ID_EXCH;
459 : 2 : break;
460 : : case PWD_Commit_Req:
461 : 2 : eap_pwd_build_commit_req(sm, data, id);
462 : 2 : lm_exch = EAP_PWD_OPCODE_COMMIT_EXCH;
463 : 2 : break;
464 : : case PWD_Confirm_Req:
465 : 2 : eap_pwd_build_confirm_req(sm, data, id);
466 : 2 : lm_exch = EAP_PWD_OPCODE_CONFIRM_EXCH;
467 : 2 : break;
468 : : default:
469 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: Unknown state %d in build_req",
470 : 0 : data->state);
471 : 0 : eap_pwd_state(data, FAILURE);
472 : 0 : lm_exch = 0; /* hush now, sweet compiler */
473 : 0 : break;
474 : : }
475 : :
476 [ - + ]: 6 : if (data->state == FAILURE)
477 : 0 : return NULL;
478 : :
479 : : /*
480 : : * determine whether that data needs to be fragmented
481 : : */
482 : 6 : len = wpabuf_len(data->outbuf) - data->out_frag_pos;
483 [ - + ]: 6 : if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
484 : 0 : len = data->mtu - EAP_PWD_HDR_SIZE;
485 : 0 : EAP_PWD_SET_MORE_BIT(lm_exch);
486 : : /*
487 : : * if this is the first fragment, need to set the M bit
488 : : * and add the total length to the eap_pwd_hdr
489 : : */
490 [ # # ]: 0 : if (data->out_frag_pos == 0) {
491 : 0 : EAP_PWD_SET_LENGTH_BIT(lm_exch);
492 : 0 : totlen = wpabuf_len(data->outbuf) +
493 : : EAP_PWD_HDR_SIZE + sizeof(u16);
494 : 0 : len -= sizeof(u16);
495 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, "
496 : : "total length = %d", totlen);
497 : : }
498 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: Send a %d byte fragment",
499 : : (int) len);
500 : : }
501 : :
502 : : /*
503 : : * alloc an eap request and populate it with the data
504 : : */
505 : 6 : req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
506 : 6 : EAP_PWD_HDR_SIZE + len +
507 [ - + ]: 6 : (totlen ? sizeof(u16) : 0),
508 : : EAP_CODE_REQUEST, id);
509 [ - + ]: 6 : if (req == NULL) {
510 : 0 : eap_pwd_state(data, FAILURE);
511 : 0 : return NULL;
512 : : }
513 : :
514 : 6 : wpabuf_put_u8(req, lm_exch);
515 [ - + ]: 6 : if (EAP_PWD_GET_LENGTH_BIT(lm_exch))
516 : 0 : wpabuf_put_be16(req, totlen);
517 : :
518 : 6 : buf = wpabuf_head_u8(data->outbuf);
519 : 6 : wpabuf_put_data(req, buf + data->out_frag_pos, len);
520 : 6 : data->out_frag_pos += len;
521 : : /*
522 : : * either not fragged or last fragment, either way free up the data
523 : : */
524 [ + - ]: 6 : if (data->out_frag_pos >= wpabuf_len(data->outbuf)) {
525 : 6 : wpabuf_free(data->outbuf);
526 : 6 : data->out_frag_pos = 0;
527 : : }
528 : :
529 : 6 : return req;
530 : : }
531 : :
532 : :
533 : 6 : static Boolean eap_pwd_check(struct eap_sm *sm, void *priv,
534 : : struct wpabuf *respData)
535 : : {
536 : 6 : struct eap_pwd_data *data = priv;
537 : : const u8 *pos;
538 : : size_t len;
539 : :
540 : 6 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len);
541 [ + - ][ - + ]: 6 : if (pos == NULL || len < 1) {
542 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: Invalid frame");
543 : 0 : return TRUE;
544 : : }
545 : :
546 : 6 : wpa_printf(MSG_DEBUG, "EAP-pwd: Received frame: exch = %d, len = %d",
547 : 6 : EAP_PWD_GET_EXCHANGE(*pos), (int) len);
548 : :
549 [ + + ][ + - ]: 6 : if (data->state == PWD_ID_Req &&
550 : 2 : ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_ID_EXCH))
551 : 2 : return FALSE;
552 : :
553 [ + + ][ + - ]: 4 : if (data->state == PWD_Commit_Req &&
554 : 2 : ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_COMMIT_EXCH))
555 : 2 : return FALSE;
556 : :
557 [ + - ][ + - ]: 2 : if (data->state == PWD_Confirm_Req &&
558 : 2 : ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_CONFIRM_EXCH))
559 : 2 : return FALSE;
560 : :
561 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: Unexpected opcode=%d in state=%d",
562 : 0 : *pos, data->state);
563 : :
564 : 6 : return TRUE;
565 : : }
566 : :
567 : :
568 : 2 : static void eap_pwd_process_id_resp(struct eap_sm *sm,
569 : : struct eap_pwd_data *data,
570 : : const u8 *payload, size_t payload_len)
571 : : {
572 : : struct eap_pwd_id *id;
573 : :
574 [ - + ]: 2 : if (payload_len < sizeof(struct eap_pwd_id)) {
575 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: Invalid ID response");
576 : 0 : return;
577 : : }
578 : :
579 : 2 : id = (struct eap_pwd_id *) payload;
580 [ + - ][ + - ]: 2 : if ((data->group_num != be_to_host16(id->group_num)) ||
581 [ + - ]: 2 : (id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
582 [ - + ]: 2 : (os_memcmp(id->token, (u8 *)&data->token, sizeof(data->token))) ||
583 : 2 : (id->prf != EAP_PWD_DEFAULT_PRF)) {
584 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: peer changed parameters");
585 : 0 : eap_pwd_state(data, FAILURE);
586 : 0 : return;
587 : : }
588 : 2 : data->id_peer = os_malloc(payload_len - sizeof(struct eap_pwd_id));
589 [ - + ]: 2 : if (data->id_peer == NULL) {
590 : 0 : wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
591 : 0 : return;
592 : : }
593 : 2 : data->id_peer_len = payload_len - sizeof(struct eap_pwd_id);
594 : 2 : os_memcpy(data->id_peer, id->identity, data->id_peer_len);
595 : 2 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-PWD (server): peer sent id of",
596 : 2 : data->id_peer, data->id_peer_len);
597 : :
598 [ - + ]: 2 : if ((data->grp = os_malloc(sizeof(EAP_PWD_group))) == NULL) {
599 : 0 : wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
600 : : "group");
601 : 0 : return;
602 : : }
603 [ - + ]: 2 : if (compute_password_element(data->grp, data->group_num,
604 : 2 : data->password, data->password_len,
605 : 2 : data->id_server, data->id_server_len,
606 : 2 : data->id_peer, data->id_peer_len,
607 : 2 : (u8 *) &data->token)) {
608 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): unable to compute "
609 : : "PWE");
610 : 0 : return;
611 : : }
612 : 2 : wpa_printf(MSG_DEBUG, "EAP-PWD (server): computed %d bit PWE...",
613 : 2 : BN_num_bits(data->grp->prime));
614 : :
615 : 2 : eap_pwd_state(data, PWD_Commit_Req);
616 : : }
617 : :
618 : :
619 : : static void
620 : 2 : eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
621 : : const u8 *payload, size_t payload_len)
622 : : {
623 : : u8 *ptr;
624 : 2 : BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;
625 : 2 : EC_POINT *K = NULL, *point = NULL;
626 : 2 : int res = 0;
627 : :
628 : 2 : wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response");
629 : :
630 [ + - + - ]: 4 : if (((data->peer_scalar = BN_new()) == NULL) ||
631 [ + - ]: 4 : ((data->k = BN_new()) == NULL) ||
632 [ + - ]: 2 : ((cofactor = BN_new()) == NULL) ||
633 [ + - ]: 2 : ((x = BN_new()) == NULL) ||
634 [ + - ]: 2 : ((y = BN_new()) == NULL) ||
635 [ + - ]: 2 : ((point = EC_POINT_new(data->grp->group)) == NULL) ||
636 [ - + ]: 2 : ((K = EC_POINT_new(data->grp->group)) == NULL) ||
637 : 2 : ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) {
638 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
639 : : "fail");
640 : 0 : goto fin;
641 : : }
642 : :
643 [ - + ]: 2 : if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
644 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "
645 : : "cofactor for curve");
646 : 0 : goto fin;
647 : : }
648 : :
649 : : /* element, x then y, followed by scalar */
650 : 2 : ptr = (u8 *) payload;
651 : 2 : BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
652 : 2 : ptr += BN_num_bytes(data->grp->prime);
653 : 2 : BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
654 : 2 : ptr += BN_num_bytes(data->grp->prime);
655 : 2 : BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar);
656 [ - + ]: 2 : if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
657 : : data->peer_element, x, y,
658 : : data->bnctx)) {
659 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
660 : : "fail");
661 : 0 : goto fin;
662 : : }
663 : :
664 : : /* check to ensure peer's element is not in a small sub-group */
665 [ - + ]: 2 : if (BN_cmp(cofactor, BN_value_one())) {
666 [ # # ]: 0 : if (!EC_POINT_mul(data->grp->group, point, NULL,
667 : 0 : data->peer_element, cofactor, NULL)) {
668 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
669 : : "multiply peer element by order");
670 : 0 : goto fin;
671 : : }
672 [ # # ]: 0 : if (EC_POINT_is_at_infinity(data->grp->group, point)) {
673 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
674 : : "is at infinity!\n");
675 : 0 : goto fin;
676 : : }
677 : : }
678 : :
679 : : /* compute the shared key, k */
680 [ + - ]: 2 : if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
681 [ + - ]: 2 : data->peer_scalar, data->bnctx)) ||
682 : 2 : (!EC_POINT_add(data->grp->group, K, K, data->peer_element,
683 [ - + ]: 2 : data->bnctx)) ||
684 : 2 : (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
685 : : data->bnctx))) {
686 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key "
687 : : "fail");
688 : 0 : goto fin;
689 : : }
690 : :
691 : : /* ensure that the shared key isn't in a small sub-group */
692 [ - + ]: 2 : if (BN_cmp(cofactor, BN_value_one())) {
693 [ # # ]: 0 : if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
694 : : NULL)) {
695 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
696 : : "multiply shared key point by order!\n");
697 : 0 : goto fin;
698 : : }
699 : : }
700 : :
701 : : /*
702 : : * This check is strictly speaking just for the case above where
703 : : * co-factor > 1 but it was suggested that even though this is probably
704 : : * never going to happen it is a simple and safe check "just to be
705 : : * sure" so let's be safe.
706 : : */
707 [ - + ]: 2 : if (EC_POINT_is_at_infinity(data->grp->group, K)) {
708 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is "
709 : : "at infinity");
710 : 0 : goto fin;
711 : : }
712 [ - + ]: 2 : if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
713 : : NULL, data->bnctx)) {
714 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract "
715 : : "shared secret from secret point");
716 : 0 : goto fin;
717 : : }
718 : 2 : res = 1;
719 : :
720 : : fin:
721 : 2 : EC_POINT_free(K);
722 : 2 : EC_POINT_free(point);
723 : 2 : BN_free(cofactor);
724 : 2 : BN_free(x);
725 : 2 : BN_free(y);
726 : :
727 [ + - ]: 2 : if (res)
728 : 2 : eap_pwd_state(data, PWD_Confirm_Req);
729 : : else
730 : 0 : eap_pwd_state(data, FAILURE);
731 : 2 : }
732 : :
733 : :
734 : : static void
735 : 2 : eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
736 : : const u8 *payload, size_t payload_len)
737 : : {
738 : 2 : BIGNUM *x = NULL, *y = NULL;
739 : : struct crypto_hash *hash;
740 : : u32 cs;
741 : : u16 grp;
742 : 2 : u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
743 : : int offset;
744 : :
745 : : /* build up the ciphersuite: group | random_function | prf */
746 : 2 : grp = htons(data->group_num);
747 : 2 : ptr = (u8 *) &cs;
748 : 2 : os_memcpy(ptr, &grp, sizeof(u16));
749 : 2 : ptr += sizeof(u16);
750 : 2 : *ptr = EAP_PWD_DEFAULT_RAND_FUNC;
751 : 2 : ptr += sizeof(u8);
752 : 2 : *ptr = EAP_PWD_DEFAULT_PRF;
753 : :
754 : : /* each component of the cruft will be at most as big as the prime */
755 [ + - ][ + - ]: 2 : if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
756 [ - + ]: 2 : ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
757 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");
758 : 0 : goto fin;
759 : : }
760 : :
761 : : /*
762 : : * commit is H(k | peer_element | peer_scalar | server_element |
763 : : * server_scalar | ciphersuite)
764 : : */
765 : 2 : hash = eap_pwd_h_init();
766 [ - + ]: 2 : if (hash == NULL)
767 : 0 : goto fin;
768 : :
769 : : /* k */
770 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
771 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
772 : 2 : BN_bn2bin(data->k, cruft + offset);
773 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
774 : :
775 : : /* peer element: x, y */
776 [ - + ]: 2 : if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
777 : 2 : data->peer_element, x, y,
778 : : data->bnctx)) {
779 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
780 : : "assignment fail");
781 : 0 : goto fin;
782 : : }
783 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
784 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
785 : 2 : BN_bn2bin(x, cruft + offset);
786 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
787 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
788 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
789 : 2 : BN_bn2bin(y, cruft + offset);
790 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
791 : :
792 : : /* peer scalar */
793 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
794 : 2 : offset = BN_num_bytes(data->grp->order) -
795 : 2 : BN_num_bytes(data->peer_scalar);
796 : 2 : BN_bn2bin(data->peer_scalar, cruft + offset);
797 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
798 : :
799 : : /* server element: x, y */
800 [ - + ]: 2 : if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
801 : 2 : data->my_element, x, y,
802 : : data->bnctx)) {
803 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
804 : : "assignment fail");
805 : 0 : goto fin;
806 : : }
807 : :
808 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
809 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
810 : 2 : BN_bn2bin(x, cruft + offset);
811 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
812 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
813 : 2 : offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
814 : 2 : BN_bn2bin(y, cruft + offset);
815 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
816 : :
817 : : /* server scalar */
818 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
819 : 2 : offset = BN_num_bytes(data->grp->order) -
820 : 2 : BN_num_bytes(data->my_scalar);
821 : 2 : BN_bn2bin(data->my_scalar, cruft + offset);
822 : 2 : eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
823 : :
824 : : /* ciphersuite */
825 : 2 : os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
826 : 2 : eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
827 : :
828 : : /* all done */
829 : 2 : eap_pwd_h_final(hash, conf);
830 : :
831 : 2 : ptr = (u8 *) payload;
832 [ - + ]: 2 : if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) {
833 : 0 : wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not "
834 : : "verify");
835 : 0 : goto fin;
836 : : }
837 : :
838 : 2 : wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");
839 [ - + ]: 2 : if (compute_keys(data->grp, data->bnctx, data->k,
840 : : data->peer_scalar, data->my_scalar, conf,
841 : 2 : data->my_confirm, &cs, data->msk, data->emsk) < 0)
842 : 0 : eap_pwd_state(data, FAILURE);
843 : : else
844 : 2 : eap_pwd_state(data, SUCCESS);
845 : :
846 : : fin:
847 : 2 : os_free(cruft);
848 : 2 : BN_free(x);
849 : 2 : BN_free(y);
850 : 2 : }
851 : :
852 : :
853 : 6 : static void eap_pwd_process(struct eap_sm *sm, void *priv,
854 : : struct wpabuf *respData)
855 : : {
856 : 6 : struct eap_pwd_data *data = priv;
857 : : const u8 *pos;
858 : : size_t len;
859 : : u8 lm_exch;
860 : : u16 tot_len;
861 : :
862 : 6 : pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len);
863 [ + - ][ - + ]: 6 : if ((pos == NULL) || (len < 1)) {
864 [ # # ]: 0 : wpa_printf(MSG_INFO, "Bad EAP header! pos %s and len = %d",
865 : : (pos == NULL) ? "is NULL" : "is not NULL",
866 : : (int) len);
867 : 0 : return;
868 : : }
869 : :
870 : 6 : lm_exch = *pos;
871 : 6 : pos++; /* skip over the bits and the exch */
872 : 6 : len--;
873 : :
874 : : /*
875 : : * if we're fragmenting then this should be an ACK with no data,
876 : : * just return and continue fragmenting in the "build" section above
877 : : */
878 [ - + ]: 6 : if (data->out_frag_pos) {
879 [ # # ]: 0 : if (len > 1)
880 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: Bad response! "
881 : : "Fragmenting but not an ACK");
882 : : else
883 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: received ACK from "
884 : : "peer");
885 : 0 : return;
886 : : }
887 : : /*
888 : : * if we're receiving fragmented packets then we need to buffer...
889 : : *
890 : : * the first fragment has a total length
891 : : */
892 [ - + ]: 6 : if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) {
893 : 0 : tot_len = WPA_GET_BE16(pos);
894 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments, total "
895 : : "length = %d", tot_len);
896 : 0 : data->inbuf = wpabuf_alloc(tot_len);
897 [ # # ]: 0 : if (data->inbuf == NULL) {
898 : 0 : wpa_printf(MSG_INFO, "EAP-pwd: Out of memory to "
899 : : "buffer fragments!");
900 : 0 : return;
901 : : }
902 : 0 : pos += sizeof(u16);
903 : 0 : len -= sizeof(u16);
904 : : }
905 : : /*
906 : : * the first and all intermediate fragments have the M bit set
907 : : */
908 [ - + ]: 6 : if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
909 [ # # ]: 0 : if ((data->in_frag_pos + len) > wpabuf_size(data->inbuf)) {
910 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: Buffer overflow "
911 : : "attack detected! (%d+%d > %d)",
912 : 0 : (int) data->in_frag_pos, (int) len,
913 : 0 : (int) wpabuf_size(data->inbuf));
914 : 0 : eap_pwd_state(data, FAILURE);
915 : 0 : return;
916 : : }
917 : 0 : wpabuf_put_data(data->inbuf, pos, len);
918 : 0 : data->in_frag_pos += len;
919 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: Got a %d byte fragment",
920 : : (int) len);
921 : 0 : return;
922 : : }
923 : : /*
924 : : * last fragment won't have the M bit set (but we're obviously
925 : : * buffering fragments so that's how we know it's the last)
926 : : */
927 [ - + ]: 6 : if (data->in_frag_pos) {
928 : 0 : wpabuf_put_data(data->inbuf, pos, len);
929 : 0 : data->in_frag_pos += len;
930 : 0 : pos = wpabuf_head_u8(data->inbuf);
931 : 0 : len = data->in_frag_pos;
932 : 0 : wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
933 : : (int) len);
934 : : }
935 [ + + + - ]: 6 : switch (EAP_PWD_GET_EXCHANGE(lm_exch)) {
936 : : case EAP_PWD_OPCODE_ID_EXCH:
937 : 2 : eap_pwd_process_id_resp(sm, data, pos, len);
938 : 2 : break;
939 : : case EAP_PWD_OPCODE_COMMIT_EXCH:
940 : 2 : eap_pwd_process_commit_resp(sm, data, pos, len);
941 : 2 : break;
942 : : case EAP_PWD_OPCODE_CONFIRM_EXCH:
943 : 2 : eap_pwd_process_confirm_resp(sm, data, pos, len);
944 : 2 : break;
945 : : }
946 : : /*
947 : : * if we had been buffering fragments, here's a great place
948 : : * to clean up
949 : : */
950 [ - + ]: 6 : if (data->in_frag_pos) {
951 : 0 : wpabuf_free(data->inbuf);
952 : 6 : data->in_frag_pos = 0;
953 : : }
954 : : }
955 : :
956 : :
957 : 2 : static u8 * eap_pwd_getkey(struct eap_sm *sm, void *priv, size_t *len)
958 : : {
959 : 2 : struct eap_pwd_data *data = priv;
960 : : u8 *key;
961 : :
962 [ - + ]: 2 : if (data->state != SUCCESS)
963 : 0 : return NULL;
964 : :
965 : 2 : key = os_malloc(EAP_MSK_LEN);
966 [ - + ]: 2 : if (key == NULL)
967 : 0 : return NULL;
968 : :
969 : 2 : os_memcpy(key, data->msk, EAP_MSK_LEN);
970 : 2 : *len = EAP_MSK_LEN;
971 : :
972 : 2 : return key;
973 : : }
974 : :
975 : :
976 : 0 : static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
977 : : {
978 : 0 : struct eap_pwd_data *data = priv;
979 : : u8 *key;
980 : :
981 [ # # ]: 0 : if (data->state != SUCCESS)
982 : 0 : return NULL;
983 : :
984 : 0 : key = os_malloc(EAP_EMSK_LEN);
985 [ # # ]: 0 : if (key == NULL)
986 : 0 : return NULL;
987 : :
988 : 0 : os_memcpy(key, data->emsk, EAP_EMSK_LEN);
989 : 0 : *len = EAP_EMSK_LEN;
990 : :
991 : 0 : return key;
992 : : }
993 : :
994 : :
995 : 2 : static Boolean eap_pwd_is_success(struct eap_sm *sm, void *priv)
996 : : {
997 : 2 : struct eap_pwd_data *data = priv;
998 : 2 : return data->state == SUCCESS;
999 : : }
1000 : :
1001 : :
1002 : 6 : static Boolean eap_pwd_is_done(struct eap_sm *sm, void *priv)
1003 : : {
1004 : 6 : struct eap_pwd_data *data = priv;
1005 [ + + ][ - + ]: 6 : return (data->state == SUCCESS) || (data->state == FAILURE);
1006 : : }
1007 : :
1008 : :
1009 : 1 : int eap_server_pwd_register(void)
1010 : : {
1011 : : struct eap_method *eap;
1012 : : int ret;
1013 : : struct timeval tp;
1014 : : struct timezone tz;
1015 : : u32 sr;
1016 : :
1017 : 1 : EVP_add_digest(EVP_sha256());
1018 : :
1019 : 1 : sr = 0xdeaddada;
1020 : 1 : (void) gettimeofday(&tp, &tz);
1021 : 1 : sr ^= (tp.tv_sec ^ tp.tv_usec);
1022 : 1 : srandom(sr);
1023 : :
1024 : 1 : eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1025 : : EAP_VENDOR_IETF, EAP_TYPE_PWD,
1026 : : "PWD");
1027 [ - + ]: 1 : if (eap == NULL)
1028 : 0 : return -1;
1029 : :
1030 : 1 : eap->init = eap_pwd_init;
1031 : 1 : eap->reset = eap_pwd_reset;
1032 : 1 : eap->buildReq = eap_pwd_build_req;
1033 : 1 : eap->check = eap_pwd_check;
1034 : 1 : eap->process = eap_pwd_process;
1035 : 1 : eap->isDone = eap_pwd_is_done;
1036 : 1 : eap->getKey = eap_pwd_getkey;
1037 : 1 : eap->get_emsk = eap_pwd_get_emsk;
1038 : 1 : eap->isSuccess = eap_pwd_is_success;
1039 : :
1040 : 1 : ret = eap_server_method_register(eap);
1041 [ - + ]: 1 : if (ret)
1042 : 0 : eap_server_method_free(eap);
1043 : 1 : return ret;
1044 : : }
1045 : :
|