Re-initialize hostapd/wpa_supplicant git repository based on 0.6.3 release
[wpasupplicant] / src / eap_server / eap_peap.c
1 /*
2  * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
3  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19 #include "eap_tls_common.h"
20 #include "eap_common/eap_tlv_common.h"
21 #include "tls.h"
22
23
24 /* Maximum supported PEAP version
25  * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
26  * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
27  * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
28  */
29 #define EAP_PEAP_VERSION 1
30
31
32 static void eap_peap_reset(struct eap_sm *sm, void *priv);
33
34
35 struct eap_peap_data {
36         struct eap_ssl_data ssl;
37         enum {
38                 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
39                 PHASE2_METHOD,
40                 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
41         } state;
42
43         int peap_version;
44         const struct eap_method *phase2_method;
45         void *phase2_priv;
46         int force_version;
47         struct wpabuf *pending_phase2_resp;
48 };
49
50
51 static const char * eap_peap_state_txt(int state)
52 {
53         switch (state) {
54         case START:
55                 return "START";
56         case PHASE1:
57                 return "PHASE1";
58         case PHASE1_ID2:
59                 return "PHASE1_ID2";
60         case PHASE2_START:
61                 return "PHASE2_START";
62         case PHASE2_ID:
63                 return "PHASE2_ID";
64         case PHASE2_METHOD:
65                 return "PHASE2_METHOD";
66         case PHASE2_TLV:
67                 return "PHASE2_TLV";
68         case SUCCESS_REQ:
69                 return "SUCCESS_REQ";
70         case FAILURE_REQ:
71                 return "FAILURE_REQ";
72         case SUCCESS:
73                 return "SUCCESS";
74         case FAILURE:
75                 return "FAILURE";
76         default:
77                 return "Unknown?!";
78         }
79 }
80
81
82 static void eap_peap_state(struct eap_peap_data *data, int state)
83 {
84         wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
85                    eap_peap_state_txt(data->state),
86                    eap_peap_state_txt(state));
87         data->state = state;
88 }
89
90
91 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
92 {
93         struct wpabuf *e;
94         struct eap_tlv_hdr *tlv;
95
96         if (buf == NULL)
97                 return NULL;
98
99         /* Encapsulate EAP packet in EAP-Payload TLV */
100         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
101         e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
102         if (e == NULL) {
103                 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
104                            "for TLV encapsulation");
105                 wpabuf_free(buf);
106                 return NULL;
107         }
108         tlv = wpabuf_put(e, sizeof(*tlv));
109         tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
110                                      EAP_TLV_EAP_PAYLOAD_TLV);
111         tlv->length = host_to_be16(wpabuf_len(buf));
112         wpabuf_put_buf(e, buf);
113         wpabuf_free(buf);
114         return e;
115 }
116
117
118 static EapType eap_peap_req_success(struct eap_sm *sm,
119                                     struct eap_peap_data *data)
120 {
121         if (data->state == FAILURE || data->state == FAILURE_REQ) {
122                 eap_peap_state(data, FAILURE);
123                 return EAP_TYPE_NONE;
124         }
125
126         if (data->peap_version == 0) {
127                 sm->tlv_request = TLV_REQ_SUCCESS;
128                 eap_peap_state(data, PHASE2_TLV);
129                 return EAP_TYPE_TLV;
130         } else {
131                 eap_peap_state(data, SUCCESS_REQ);
132                 return EAP_TYPE_NONE;
133         }
134 }
135
136
137 static EapType eap_peap_req_failure(struct eap_sm *sm,
138                                     struct eap_peap_data *data)
139 {
140         if (data->state == FAILURE || data->state == FAILURE_REQ ||
141             data->state == SUCCESS_REQ ||
142             (data->phase2_method &&
143              data->phase2_method->method == EAP_TYPE_TLV)) {
144                 eap_peap_state(data, FAILURE);
145                 return EAP_TYPE_NONE;
146         }
147
148         if (data->peap_version == 0) {
149                 sm->tlv_request = TLV_REQ_FAILURE;
150                 eap_peap_state(data, PHASE2_TLV);
151                 return EAP_TYPE_TLV;
152         } else {
153                 eap_peap_state(data, FAILURE_REQ);
154                 return EAP_TYPE_NONE;
155         }
156 }
157
158
159 static void * eap_peap_init(struct eap_sm *sm)
160 {
161         struct eap_peap_data *data;
162
163         data = os_zalloc(sizeof(*data));
164         if (data == NULL)
165                 return NULL;
166         data->peap_version = EAP_PEAP_VERSION;
167         data->force_version = -1;
168         if (sm->user && sm->user->force_version >= 0) {
169                 data->force_version = sm->user->force_version;
170                 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
171                            data->force_version);
172                 data->peap_version = data->force_version;
173         }
174         data->state = START;
175
176         if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
177                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
178                 eap_peap_reset(sm, data);
179                 return NULL;
180         }
181
182         return data;
183 }
184
185
186 static void eap_peap_reset(struct eap_sm *sm, void *priv)
187 {
188         struct eap_peap_data *data = priv;
189         if (data == NULL)
190                 return;
191         if (data->phase2_priv && data->phase2_method)
192                 data->phase2_method->reset(sm, data->phase2_priv);
193         eap_server_tls_ssl_deinit(sm, &data->ssl);
194         wpabuf_free(data->pending_phase2_resp);
195         os_free(data);
196 }
197
198
199 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
200                                             struct eap_peap_data *data, u8 id)
201 {
202         struct wpabuf *req;
203
204         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
205                             EAP_CODE_REQUEST, id);
206         if (req == NULL) {
207                 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
208                            " request");
209                 eap_peap_state(data, FAILURE);
210                 return NULL;
211         }
212
213         wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
214
215         eap_peap_state(data, PHASE1);
216
217         return req;
218 }
219
220
221 static struct wpabuf * eap_peap_build_req(struct eap_sm *sm,
222                                           struct eap_peap_data *data, u8 id)
223 {
224         int res;
225         struct wpabuf *req;
226
227         res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_PEAP,
228                                              data->peap_version, id, &req);
229
230         if (data->peap_version < 2 &&
231             tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
232                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, starting "
233                            "Phase2");
234                 eap_peap_state(data, PHASE2_START);
235         }
236
237         if (res == 1)
238                 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
239                                                 data->peap_version);
240         return req;
241 }
242
243
244 static struct wpabuf * eap_peap_encrypt(struct eap_sm *sm,
245                                         struct eap_peap_data *data,
246                                         u8 id, const u8 *plain,
247                                         size_t plain_len)
248 {
249         int res;
250         struct wpabuf *buf;
251
252         /* TODO: add support for fragmentation, if needed. This will need to
253          * add TLS Message Length field, if the frame is fragmented. */
254         buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP,
255                             1 + data->ssl.tls_out_limit,
256                             EAP_CODE_REQUEST, id);
257         if (buf == NULL)
258                 return NULL;
259
260         wpabuf_put_u8(buf, data->peap_version);
261
262         res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
263                                      plain, plain_len, wpabuf_put(buf, 0),
264                                      data->ssl.tls_out_limit);
265         if (res < 0) {
266                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
267                            "data");
268                 wpabuf_free(buf);
269                 return NULL;
270         }
271
272         wpabuf_put(buf, res);
273         eap_update_len(buf);
274
275         return buf;
276 }
277
278
279 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
280                                                  struct eap_peap_data *data,
281                                                  u8 id)
282 {
283         struct wpabuf *buf, *encr_req;
284         const u8 *req;
285         size_t req_len;
286
287         buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
288         if (data->peap_version >= 2 && buf)
289                 buf = eap_peapv2_tlv_eap_payload(buf);
290         if (buf == NULL)
291                 return NULL;
292
293         req = wpabuf_head(buf);
294         req_len = wpabuf_len(buf);
295         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
296                         req, req_len);
297
298         if (data->peap_version == 0 &&
299             data->phase2_method->method != EAP_TYPE_TLV) {
300                 req += sizeof(struct eap_hdr);
301                 req_len -= sizeof(struct eap_hdr);
302         }
303
304         encr_req = eap_peap_encrypt(sm, data, id, req, req_len);
305         wpabuf_free(buf);
306
307         return encr_req;
308 }
309
310
311 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
312                                                   struct eap_peap_data *data,
313                                                   u8 id, int success)
314 {
315         struct wpabuf *encr_req;
316         size_t req_len;
317         struct eap_hdr *hdr;
318
319         req_len = sizeof(*hdr);
320         hdr = os_zalloc(req_len);
321         if (hdr == NULL)
322                 return NULL;
323
324         hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
325         hdr->identifier = id;
326         hdr->length = host_to_be16(req_len);
327
328         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
329                         (u8 *) hdr, req_len);
330
331         encr_req = eap_peap_encrypt(sm, data, id, (u8 *) hdr, req_len);
332         os_free(hdr);
333
334         return encr_req;
335 }
336
337
338 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
339 {
340         struct eap_peap_data *data = priv;
341
342         switch (data->state) {
343         case START:
344                 return eap_peap_build_start(sm, data, id);
345         case PHASE1:
346         case PHASE1_ID2:
347                 return eap_peap_build_req(sm, data, id);
348         case PHASE2_ID:
349         case PHASE2_METHOD:
350         case PHASE2_TLV:
351                 return eap_peap_build_phase2_req(sm, data, id);
352         case SUCCESS_REQ:
353                 return eap_peap_build_phase2_term(sm, data, id, 1);
354         case FAILURE_REQ:
355                 return eap_peap_build_phase2_term(sm, data, id, 0);
356         default:
357                 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
358                            __func__, data->state);
359                 return NULL;
360         }
361 }
362
363
364 static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
365                               struct wpabuf *respData)
366 {
367         const u8 *pos;
368         size_t len;
369
370         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
371         if (pos == NULL || len < 1) {
372                 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
373                 return TRUE;
374         }
375
376         return FALSE;
377 }
378
379
380 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
381                                 EapType eap_type)
382 {
383         if (data->phase2_priv && data->phase2_method) {
384                 data->phase2_method->reset(sm, data->phase2_priv);
385                 data->phase2_method = NULL;
386                 data->phase2_priv = NULL;
387         }
388         data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
389                                                         eap_type);
390         if (!data->phase2_method)
391                 return -1;
392
393         sm->init_phase2 = 1;
394         data->phase2_priv = data->phase2_method->init(sm);
395         sm->init_phase2 = 0;
396         return 0;
397 }
398
399
400 static void eap_peap_process_phase2_response(struct eap_sm *sm,
401                                              struct eap_peap_data *data,
402                                              struct wpabuf *in_data)
403 {
404         u8 next_type = EAP_TYPE_NONE;
405         const struct eap_hdr *hdr;
406         const u8 *pos;
407         size_t left;
408
409         if (data->phase2_priv == NULL) {
410                 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
411                            "initialized?!", __func__);
412                 return;
413         }
414
415         hdr = wpabuf_head(in_data);
416         pos = (const u8 *) (hdr + 1);
417
418         if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
419                 left = wpabuf_len(in_data) - sizeof(*hdr);
420                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
421                             "allowed types", pos + 1, left - 1);
422                 eap_sm_process_nak(sm, pos + 1, left - 1);
423                 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
424                     sm->user->methods[sm->user_eap_method_index].method !=
425                     EAP_TYPE_NONE) {
426                         next_type = sm->user->methods[
427                                 sm->user_eap_method_index++].method;
428                         wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
429                                    next_type);
430                 } else {
431                         next_type = eap_peap_req_failure(sm, data);
432                 }
433                 eap_peap_phase2_init(sm, data, next_type);
434                 return;
435         }
436
437         if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
438                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
439                            "ignore the packet");
440                 return;
441         }
442
443         data->phase2_method->process(sm, data->phase2_priv, in_data);
444
445         if (sm->method_pending == METHOD_PENDING_WAIT) {
446                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
447                            "pending wait state - save decrypted response");
448                 wpabuf_free(data->pending_phase2_resp);
449                 data->pending_phase2_resp = wpabuf_dup(in_data);
450         }
451
452         if (!data->phase2_method->isDone(sm, data->phase2_priv))
453                 return;
454
455         if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
456                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
457                 next_type = eap_peap_req_failure(sm, data);
458                 eap_peap_phase2_init(sm, data, next_type);
459                 return;
460         }
461
462         switch (data->state) {
463         case PHASE1_ID2:
464         case PHASE2_ID:
465                 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
466                         wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
467                                           "Identity not found in the user "
468                                           "database",
469                                           sm->identity, sm->identity_len);
470                         next_type = eap_peap_req_failure(sm, data);
471                         break;
472                 }
473
474                 eap_peap_state(data, PHASE2_METHOD);
475                 next_type = sm->user->methods[0].method;
476                 sm->user_eap_method_index = 1;
477                 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
478                 break;
479         case PHASE2_METHOD:
480                 next_type = eap_peap_req_success(sm, data);
481                 break;
482         case PHASE2_TLV:
483                 if (sm->tlv_request == TLV_REQ_SUCCESS ||
484                     data->state == SUCCESS_REQ) {
485                         eap_peap_state(data, SUCCESS);
486                 } else {
487                         eap_peap_state(data, FAILURE);
488                 }
489                 break;
490         case FAILURE:
491                 break;
492         default:
493                 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
494                            __func__, data->state);
495                 break;
496         }
497
498         eap_peap_phase2_init(sm, data, next_type);
499 }
500
501
502 static void eap_peap_process_phase2(struct eap_sm *sm,
503                                     struct eap_peap_data *data,
504                                     const struct wpabuf *respData,
505                                     const u8 *in_data, size_t in_len)
506 {
507         struct wpabuf *in_decrypted;
508         int len_decrypted, res;
509         const struct eap_hdr *hdr;
510         size_t buf_len, len;
511
512         wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
513                    " Phase 2", (unsigned long) in_len);
514
515         if (data->pending_phase2_resp) {
516                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
517                            "skip decryption and use old data");
518                 eap_peap_process_phase2_response(sm, data,
519                                                  data->pending_phase2_resp);
520                 wpabuf_free(data->pending_phase2_resp);
521                 data->pending_phase2_resp = NULL;
522                 return;
523         }
524
525         /* FIX: get rid of const -> non-const typecast */
526         res = eap_server_tls_data_reassemble(sm, &data->ssl, (u8 **) &in_data,
527                                              &in_len);
528         if (res < 0 || res == 1)
529                 return;
530
531         buf_len = in_len;
532         if (data->ssl.tls_in_total > buf_len)
533                 buf_len = data->ssl.tls_in_total;
534         in_decrypted = wpabuf_alloc(buf_len);
535         if (in_decrypted == NULL) {
536                 os_free(data->ssl.tls_in);
537                 data->ssl.tls_in = NULL;
538                 data->ssl.tls_in_len = 0;
539                 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
540                            "for decryption");
541                 return;
542         }
543
544         len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
545                                                in_data, in_len,
546                                                wpabuf_mhead(in_decrypted),
547                                                buf_len);
548         os_free(data->ssl.tls_in);
549         data->ssl.tls_in = NULL;
550         data->ssl.tls_in_len = 0;
551         if (len_decrypted < 0) {
552                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
553                            "data");
554                 wpabuf_free(in_decrypted);
555                 eap_peap_state(data, FAILURE);
556                 return;
557         }
558         wpabuf_put(in_decrypted, len_decrypted);
559
560         wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
561                             in_decrypted);
562
563         hdr = wpabuf_head(in_decrypted);
564
565         if (data->peap_version == 0 && data->state != PHASE2_TLV) {
566                 const struct eap_hdr *resp;
567                 struct eap_hdr *nhdr;
568                 struct wpabuf *nbuf =
569                         wpabuf_alloc(sizeof(struct eap_hdr) +
570                                      wpabuf_len(in_decrypted));
571                 if (nbuf == NULL) {
572                         wpabuf_free(in_decrypted);
573                         return;
574                 }
575
576                 resp = wpabuf_head(respData);
577                 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
578                 nhdr->code = resp->code;
579                 nhdr->identifier = resp->identifier;
580                 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
581                                             wpabuf_len(in_decrypted));
582                 wpabuf_put_buf(nbuf, in_decrypted);
583                 wpabuf_free(in_decrypted);
584
585                 in_decrypted = nbuf;
586         } else if (data->peap_version >= 2) {
587                 struct eap_tlv_hdr *tlv;
588                 struct wpabuf *nmsg;
589
590                 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
591                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
592                                    "EAP TLV");
593                         wpabuf_free(in_decrypted);
594                         return;
595                 }
596                 tlv = wpabuf_mhead(in_decrypted);
597                 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
598                     EAP_TLV_EAP_PAYLOAD_TLV) {
599                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
600                         wpabuf_free(in_decrypted);
601                         return;
602                 }
603                 if (sizeof(*tlv) + be_to_host16(tlv->length) >
604                     wpabuf_len(in_decrypted)) {
605                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
606                                    "length");
607                         wpabuf_free(in_decrypted);
608                         return;
609                 }
610                 hdr = (struct eap_hdr *) (tlv + 1);
611                 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
612                         wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
613                                    "EAP packet in EAP TLV");
614                         wpabuf_free(in_decrypted);
615                         return;
616                 }
617
618                 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
619                 if (nmsg == NULL) {
620                         wpabuf_free(in_decrypted);
621                         return;
622                 }
623
624                 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
625                 wpabuf_free(in_decrypted);
626                 in_decrypted = nmsg;
627         }
628
629         hdr = wpabuf_head(in_decrypted);
630         if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
631                 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
632                            "EAP frame (len=%lu)",
633                            (unsigned long) wpabuf_len(in_decrypted));
634                 wpabuf_free(in_decrypted);
635                 eap_peap_req_failure(sm, data);
636                 return;
637         }
638         len = be_to_host16(hdr->length);
639         if (len > wpabuf_len(in_decrypted)) {
640                 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
641                            "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
642                            (unsigned long) wpabuf_len(in_decrypted),
643                            (unsigned long) len);
644                 wpabuf_free(in_decrypted);
645                 eap_peap_req_failure(sm, data);
646                 return;
647         }
648         wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
649                    "identifier=%d length=%lu", hdr->code, hdr->identifier,
650                    (unsigned long) len);
651         switch (hdr->code) {
652         case EAP_CODE_RESPONSE:
653                 eap_peap_process_phase2_response(sm, data, in_decrypted);
654                 break;
655         case EAP_CODE_SUCCESS:
656                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
657                 if (data->state == SUCCESS_REQ) {
658                         eap_peap_state(data, SUCCESS);
659                 }
660                 break;
661         case EAP_CODE_FAILURE:
662                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
663                 eap_peap_state(data, FAILURE);
664                 break;
665         default:
666                 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
667                            "Phase 2 EAP header", hdr->code);
668                 break;
669         }
670
671         os_free(in_decrypted);
672 }
673
674
675 static int eap_peapv2_start_phase2(struct eap_sm *sm,
676                                    struct eap_peap_data *data)
677 {
678         struct wpabuf *buf, *buf2;
679         int res;
680         u8 *tls_out;
681
682         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
683                    "payload in the same message");
684         eap_peap_state(data, PHASE1_ID2);
685         if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
686                 return -1;
687
688         /* TODO: which Id to use here? */
689         buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
690         if (buf == NULL)
691                 return -1;
692
693         buf2 = eap_peapv2_tlv_eap_payload(buf);
694         if (buf2 == NULL)
695                 return -1;
696
697         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
698
699         buf = wpabuf_alloc(data->ssl.tls_out_limit);
700         if (buf == NULL) {
701                 wpabuf_free(buf2);
702                 return -1;
703         }
704
705         res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
706                                      wpabuf_head(buf2), wpabuf_len(buf2),
707                                      wpabuf_put(buf, 0),
708                                      data->ssl.tls_out_limit);
709         wpabuf_free(buf2);
710
711         if (res < 0) {
712                 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
713                            "data");
714                 wpabuf_free(buf);
715                 return -1;
716         }
717
718         wpabuf_put(buf, res);
719         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
720                         buf);
721
722         /* Append TLS data into the pending buffer after the Server Finished */
723         tls_out = os_realloc(data->ssl.tls_out,
724                              data->ssl.tls_out_len + wpabuf_len(buf));
725         if (tls_out == NULL) {
726                 wpabuf_free(buf);
727                 return -1;
728         }
729
730         os_memcpy(tls_out + data->ssl.tls_out_len, wpabuf_head(buf),
731                   wpabuf_len(buf));
732         data->ssl.tls_out = tls_out;
733         data->ssl.tls_out_len += wpabuf_len(buf);
734
735         wpabuf_free(buf);
736
737         return 0;
738 }
739
740
741 static void eap_peap_process(struct eap_sm *sm, void *priv,
742                              struct wpabuf *respData)
743 {
744         struct eap_peap_data *data = priv;
745         const u8 *pos;
746         u8 flags;
747         size_t left;
748         unsigned int tls_msg_len;
749         int peer_version;
750
751         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
752                                &left);
753         if (pos == NULL || left < 1)
754                 return;
755         flags = *pos++;
756         left--;
757         wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
758                    "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
759                    flags);
760         peer_version = flags & EAP_PEAP_VERSION_MASK;
761         if (data->force_version >= 0 && peer_version != data->force_version) {
762                 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
763                            " version (forced=%d peer=%d) - reject",
764                            data->force_version, peer_version);
765                 eap_peap_state(data, FAILURE);
766                 return;
767         }
768         if (peer_version < data->peap_version) {
769                 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
770                            "use version %d",
771                            peer_version, data->peap_version, peer_version);
772                 data->peap_version = peer_version;
773         }
774         if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
775                 if (left < 4) {
776                         wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS "
777                                    "length");
778                         eap_peap_state(data, FAILURE);
779                         return;
780                 }
781                 tls_msg_len = WPA_GET_BE32(pos);
782                 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d",
783                            tls_msg_len);
784                 if (data->ssl.tls_in_left == 0) {
785                         data->ssl.tls_in_total = tls_msg_len;
786                         data->ssl.tls_in_left = tls_msg_len;
787                         os_free(data->ssl.tls_in);
788                         data->ssl.tls_in = NULL;
789                         data->ssl.tls_in_len = 0;
790                 }
791                 pos += 4;
792                 left -= 4;
793         }
794
795         switch (data->state) {
796         case PHASE1:
797                 if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
798                     0) {
799                         wpa_printf(MSG_INFO, "EAP-PEAP: TLS processing "
800                                    "failed");
801                         eap_peap_state(data, FAILURE);
802                         break;
803                 }
804
805                 if (data->peap_version >= 2 &&
806                     tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
807                         if (eap_peapv2_start_phase2(sm, data)) {
808                                 eap_peap_state(data, FAILURE);
809                                 break;
810                         }
811                 }
812                 break;
813         case PHASE2_START:
814                 eap_peap_state(data, PHASE2_ID);
815                 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
816                 break;
817         case PHASE1_ID2:
818         case PHASE2_ID:
819         case PHASE2_METHOD:
820         case PHASE2_TLV:
821                 eap_peap_process_phase2(sm, data, respData, pos, left);
822                 break;
823         case SUCCESS_REQ:
824                 eap_peap_state(data, SUCCESS);
825                 break;
826         case FAILURE_REQ:
827                 eap_peap_state(data, FAILURE);
828                 break;
829         default:
830                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
831                            data->state, __func__);
832                 break;
833         }
834
835         if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
836                 wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
837                            "in TLS processing");
838                 eap_peap_state(data, FAILURE);
839         }
840 }
841
842
843 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
844 {
845         struct eap_peap_data *data = priv;
846         return data->state == SUCCESS || data->state == FAILURE;
847 }
848
849
850 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
851 {
852         struct eap_peap_data *data = priv;
853         u8 *eapKeyData;
854
855         if (data->state != SUCCESS)
856                 return NULL;
857
858         /* TODO: PEAPv1 - different label in some cases */
859         eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
860                                                "client EAP encryption",
861                                                EAP_TLS_KEY_LEN);
862         if (eapKeyData) {
863                 *len = EAP_TLS_KEY_LEN;
864                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
865                             eapKeyData, EAP_TLS_KEY_LEN);
866         } else {
867                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
868         }
869
870         return eapKeyData;
871 }
872
873
874 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
875 {
876         struct eap_peap_data *data = priv;
877         return data->state == SUCCESS;
878 }
879
880
881 int eap_server_peap_register(void)
882 {
883         struct eap_method *eap;
884         int ret;
885
886         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
887                                       EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
888         if (eap == NULL)
889                 return -1;
890
891         eap->init = eap_peap_init;
892         eap->reset = eap_peap_reset;
893         eap->buildReq = eap_peap_buildReq;
894         eap->check = eap_peap_check;
895         eap->process = eap_peap_process;
896         eap->isDone = eap_peap_isDone;
897         eap->getKey = eap_peap_getKey;
898         eap->isSuccess = eap_peap_isSuccess;
899
900         ret = eap_server_method_register(eap);
901         if (ret)
902                 eap_server_method_free(eap);
903         return ret;
904 }