Do not refer to Flags::Version field as 'PEAP version'
[libeap.git] / 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 "sha1.h"
19 #include "eap_i.h"
20 #include "eap_tls_common.h"
21 #include "eap_common/eap_tlv_common.h"
22 #include "tls.h"
23 #include "tncs.h"
24
25
26 /* Maximum supported PEAP version
27  * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
28  * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
29  * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
30  */
31 #define EAP_PEAP_VERSION 1
32
33
34 static void eap_peap_reset(struct eap_sm *sm, void *priv);
35
36
37 struct eap_peap_data {
38         struct eap_ssl_data ssl;
39         enum {
40                 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
41                 PHASE2_METHOD, PHASE2_SOH,
42                 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
43         } state;
44
45         int peap_version;
46         int recv_version;
47         const struct eap_method *phase2_method;
48         void *phase2_priv;
49         int force_version;
50         struct wpabuf *pending_phase2_resp;
51         enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request;
52         int crypto_binding_sent;
53         int crypto_binding_used;
54         enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
55         u8 binding_nonce[32];
56         u8 ipmk[40];
57         u8 cmk[20];
58         u8 *phase2_key;
59         size_t phase2_key_len;
60         struct wpabuf *soh_response;
61 };
62
63
64 static const char * eap_peap_state_txt(int state)
65 {
66         switch (state) {
67         case START:
68                 return "START";
69         case PHASE1:
70                 return "PHASE1";
71         case PHASE1_ID2:
72                 return "PHASE1_ID2";
73         case PHASE2_START:
74                 return "PHASE2_START";
75         case PHASE2_ID:
76                 return "PHASE2_ID";
77         case PHASE2_METHOD:
78                 return "PHASE2_METHOD";
79         case PHASE2_SOH:
80                 return "PHASE2_SOH";
81         case PHASE2_TLV:
82                 return "PHASE2_TLV";
83         case SUCCESS_REQ:
84                 return "SUCCESS_REQ";
85         case FAILURE_REQ:
86                 return "FAILURE_REQ";
87         case SUCCESS:
88                 return "SUCCESS";
89         case FAILURE:
90                 return "FAILURE";
91         default:
92                 return "Unknown?!";
93         }
94 }
95
96
97 static void eap_peap_state(struct eap_peap_data *data, int state)
98 {
99         wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
100                    eap_peap_state_txt(data->state),
101                    eap_peap_state_txt(state));
102         data->state = state;
103 }
104
105
106 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
107 {
108         struct wpabuf *e;
109         struct eap_tlv_hdr *tlv;
110
111         if (buf == NULL)
112                 return NULL;
113
114         /* Encapsulate EAP packet in EAP-Payload TLV */
115         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
116         e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
117         if (e == NULL) {
118                 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
119                            "for TLV encapsulation");
120                 wpabuf_free(buf);
121                 return NULL;
122         }
123         tlv = wpabuf_put(e, sizeof(*tlv));
124         tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
125                                      EAP_TLV_EAP_PAYLOAD_TLV);
126         tlv->length = host_to_be16(wpabuf_len(buf));
127         wpabuf_put_buf(e, buf);
128         wpabuf_free(buf);
129         return e;
130 }
131
132
133 static void eap_peap_req_success(struct eap_sm *sm,
134                                  struct eap_peap_data *data)
135 {
136         if (data->state == FAILURE || data->state == FAILURE_REQ) {
137                 eap_peap_state(data, FAILURE);
138                 return;
139         }
140
141         if (data->peap_version == 0) {
142                 data->tlv_request = TLV_REQ_SUCCESS;
143                 eap_peap_state(data, PHASE2_TLV);
144         } else {
145                 eap_peap_state(data, SUCCESS_REQ);
146         }
147 }
148
149
150 static void eap_peap_req_failure(struct eap_sm *sm,
151                                  struct eap_peap_data *data)
152 {
153         if (data->state == FAILURE || data->state == FAILURE_REQ ||
154             data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) {
155                 eap_peap_state(data, FAILURE);
156                 return;
157         }
158
159         if (data->peap_version == 0) {
160                 data->tlv_request = TLV_REQ_FAILURE;
161                 eap_peap_state(data, PHASE2_TLV);
162         } else {
163                 eap_peap_state(data, FAILURE_REQ);
164         }
165 }
166
167
168 static void * eap_peap_init(struct eap_sm *sm)
169 {
170         struct eap_peap_data *data;
171
172         data = os_zalloc(sizeof(*data));
173         if (data == NULL)
174                 return NULL;
175         data->peap_version = EAP_PEAP_VERSION;
176         data->force_version = -1;
177         if (sm->user && sm->user->force_version >= 0) {
178                 data->force_version = sm->user->force_version;
179                 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
180                            data->force_version);
181                 data->peap_version = data->force_version;
182         }
183         data->state = START;
184         data->crypto_binding = OPTIONAL_BINDING;
185
186         if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
187                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
188                 eap_peap_reset(sm, data);
189                 return NULL;
190         }
191
192         return data;
193 }
194
195
196 static void eap_peap_reset(struct eap_sm *sm, void *priv)
197 {
198         struct eap_peap_data *data = priv;
199         if (data == NULL)
200                 return;
201         if (data->phase2_priv && data->phase2_method)
202                 data->phase2_method->reset(sm, data->phase2_priv);
203         eap_server_tls_ssl_deinit(sm, &data->ssl);
204         wpabuf_free(data->pending_phase2_resp);
205         os_free(data->phase2_key);
206         wpabuf_free(data->soh_response);
207         os_free(data);
208 }
209
210
211 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
212                                             struct eap_peap_data *data, u8 id)
213 {
214         struct wpabuf *req;
215
216         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
217                             EAP_CODE_REQUEST, id);
218         if (req == NULL) {
219                 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
220                            " request");
221                 eap_peap_state(data, FAILURE);
222                 return NULL;
223         }
224
225         wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
226
227         eap_peap_state(data, PHASE1);
228
229         return req;
230 }
231
232
233 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
234                                                  struct eap_peap_data *data,
235                                                  u8 id)
236 {
237         struct wpabuf *buf, *encr_req;
238         const u8 *req;
239         size_t req_len;
240
241         if (data->phase2_method == NULL || data->phase2_priv == NULL) {
242                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready");
243                 return NULL;
244         }
245         buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
246         if (data->peap_version >= 2 && buf)
247                 buf = eap_peapv2_tlv_eap_payload(buf);
248         if (buf == NULL)
249                 return NULL;
250
251         req = wpabuf_head(buf);
252         req_len = wpabuf_len(buf);
253         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
254                         req, req_len);
255
256         if (data->peap_version == 0 &&
257             data->phase2_method->method != EAP_TYPE_TLV) {
258                 req += sizeof(struct eap_hdr);
259                 req_len -= sizeof(struct eap_hdr);
260         }
261
262         encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
263         wpabuf_free(buf);
264
265         return encr_req;
266 }
267
268
269 #ifdef EAP_TNC
270 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
271                                                  struct eap_peap_data *data,
272                                                  u8 id)
273 {
274         struct wpabuf *buf1, *buf, *encr_req;
275         const u8 *req;
276         size_t req_len;
277
278         buf1 = tncs_build_soh_request();
279         if (buf1 == NULL)
280                 return NULL;
281
282         buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1),
283                             EAP_CODE_REQUEST, id);
284         if (buf == NULL) {
285                 wpabuf_free(buf1);
286                 return NULL;
287         }
288         wpabuf_put_buf(buf, buf1);
289         wpabuf_free(buf1);
290
291         req = wpabuf_head(buf);
292         req_len = wpabuf_len(buf);
293
294         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data",
295                         req, req_len);
296
297         req += sizeof(struct eap_hdr);
298         req_len -= sizeof(struct eap_hdr);
299
300         encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
301         wpabuf_free(buf);
302
303         return encr_req;
304 }
305 #endif /* EAP_TNC */
306
307
308 static void eap_peap_get_isk(struct eap_peap_data *data,
309                              u8 *isk, size_t isk_len)
310 {
311         size_t key_len;
312
313         os_memset(isk, 0, isk_len);
314         if (data->phase2_key == NULL)
315                 return;
316
317         key_len = data->phase2_key_len;
318         if (key_len > isk_len)
319                 key_len = isk_len;
320         os_memcpy(isk, data->phase2_key, key_len);
321 }
322
323
324 void peap_prfplus(int version, const u8 *key, size_t key_len,
325                   const char *label, const u8 *seed, size_t seed_len,
326                   u8 *buf, size_t buf_len)
327 {
328         unsigned char counter = 0;
329         size_t pos, plen;
330         u8 hash[SHA1_MAC_LEN];
331         size_t label_len = os_strlen(label);
332         u8 extra[2];
333         const unsigned char *addr[5];
334         size_t len[5];
335
336         addr[0] = hash;
337         len[0] = 0;
338         addr[1] = (unsigned char *) label;
339         len[1] = label_len;
340         addr[2] = seed;
341         len[2] = seed_len;
342
343         if (version == 0) {
344                 /*
345                  * PRF+(K, S, LEN) = T1 | T2 | ... | Tn
346                  * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00)
347                  * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00)
348                  * ...
349                  * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00)
350                  */
351
352                 extra[0] = 0;
353                 extra[1] = 0;
354
355                 addr[3] = &counter;
356                 len[3] = 1;
357                 addr[4] = extra;
358                 len[4] = 2;
359         } else {
360                 /*
361                  * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where:
362                  * T1 = HMAC-SHA1(K, S | LEN | 0x01)
363                  * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02)
364                  * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03)
365                  * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04)
366                  *   ...
367                  */
368
369                 extra[0] = buf_len & 0xff;
370
371                 addr[3] = extra;
372                 len[3] = 1;
373                 addr[4] = &counter;
374                 len[4] = 1;
375         }
376
377         pos = 0;
378         while (pos < buf_len) {
379                 counter++;
380                 plen = buf_len - pos;
381                 hmac_sha1_vector(key, key_len, 5, addr, len, hash);
382                 if (plen >= SHA1_MAC_LEN) {
383                         os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
384                         pos += SHA1_MAC_LEN;
385                 } else {
386                         os_memcpy(&buf[pos], hash, plen);
387                         break;
388                 }
389                 len[0] = SHA1_MAC_LEN;
390         }
391 }
392
393
394 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
395 {
396         u8 *tk;
397         u8 isk[32], imck[60];
398
399         /*
400          * Tunnel key (TK) is the first 60 octets of the key generated by
401          * phase 1 of PEAP (based on TLS).
402          */
403         tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
404                                        EAP_TLS_KEY_LEN);
405         if (tk == NULL)
406                 return -1;
407         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
408
409         eap_peap_get_isk(data, isk, sizeof(isk));
410         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
411
412         /*
413          * IPMK Seed = "Inner Methods Compound Keys" | ISK
414          * TempKey = First 40 octets of TK
415          * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
416          * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
417          * in the end of the label just before ISK; is that just a typo?)
418          */
419         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
420         peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
421                      isk, sizeof(isk), imck, sizeof(imck));
422         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
423                         imck, sizeof(imck));
424
425         os_free(tk);
426
427         /* TODO: fast-connect: IPMK|CMK = TK */
428         os_memcpy(data->ipmk, imck, 40);
429         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
430         os_memcpy(data->cmk, imck + 40, 20);
431         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
432
433         return 0;
434 }
435
436
437 static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
438                                                  struct eap_peap_data *data,
439                                                  u8 id)
440 {
441         struct wpabuf *buf, *encr_req;
442         size_t len;
443
444         len = 6; /* Result TLV */
445         if (data->crypto_binding != NO_BINDING)
446                 len += 60; /* Cryptobinding TLV */
447 #ifdef EAP_TNC
448         if (data->soh_response)
449                 len += wpabuf_len(data->soh_response);
450 #endif /* EAP_TNC */
451
452         buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
453                             EAP_CODE_REQUEST, id);
454         if (buf == NULL)
455                 return NULL;
456
457         wpabuf_put_u8(buf, 0x80); /* Mandatory */
458         wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
459         /* Length */
460         wpabuf_put_be16(buf, 2);
461         /* Status */
462         wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
463                         EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);
464
465         if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
466             data->crypto_binding != NO_BINDING) {
467                 u8 *mac;
468                 u8 eap_type = EAP_TYPE_PEAP;
469                 const u8 *addr[2];
470                 size_t len[2];
471                 u16 tlv_type;
472
473 #ifdef EAP_TNC
474                 if (data->soh_response) {
475                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
476                                    "Response TLV");
477                         wpabuf_put_buf(buf, data->soh_response);
478                         wpabuf_free(data->soh_response);
479                         data->soh_response = NULL;
480                 }
481 #endif /* EAP_TNC */
482
483                 if (eap_peap_derive_cmk(sm, data) < 0 ||
484                     os_get_random(data->binding_nonce, 32)) {
485                         wpabuf_free(buf);
486                         return NULL;
487                 }
488
489                 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
490                 addr[0] = wpabuf_put(buf, 0);
491                 len[0] = 60;
492                 addr[1] = &eap_type;
493                 len[1] = 1;
494
495                 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
496                 if (data->peap_version >= 2)
497                         tlv_type |= EAP_TLV_TYPE_MANDATORY;
498                 wpabuf_put_be16(buf, tlv_type);
499                 wpabuf_put_be16(buf, 56);
500
501                 wpabuf_put_u8(buf, 0); /* Reserved */
502                 wpabuf_put_u8(buf, data->peap_version); /* Version */
503                 wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
504                 wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
505                 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
506                 mac = wpabuf_put(buf, 20); /* Compound_MAC */
507                 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
508                             data->cmk, 20);
509                 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
510                             addr[0], len[0]);
511                 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
512                             addr[1], len[1]);
513                 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
514                 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
515                             mac, SHA1_MAC_LEN);
516                 data->crypto_binding_sent = 1;
517         }
518
519         wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
520                             buf);
521
522         encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
523                                           wpabuf_len(buf));
524         wpabuf_free(buf);
525
526         return encr_req;
527 }
528
529
530 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
531                                                   struct eap_peap_data *data,
532                                                   u8 id, int success)
533 {
534         struct wpabuf *encr_req;
535         size_t req_len;
536         struct eap_hdr *hdr;
537
538         req_len = sizeof(*hdr);
539         hdr = os_zalloc(req_len);
540         if (hdr == NULL)
541                 return NULL;
542
543         hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
544         hdr->identifier = id;
545         hdr->length = host_to_be16(req_len);
546
547         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
548                         (u8 *) hdr, req_len);
549
550         encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len);
551         os_free(hdr);
552
553         return encr_req;
554 }
555
556
557 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
558 {
559         struct eap_peap_data *data = priv;
560
561         if (data->ssl.state == FRAG_ACK) {
562                 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
563                                                 data->peap_version);
564         }
565
566         if (data->ssl.state == WAIT_FRAG_ACK) {
567                 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
568                                                 data->peap_version, id);
569         }
570
571         switch (data->state) {
572         case START:
573                 return eap_peap_build_start(sm, data, id);
574         case PHASE1:
575         case PHASE1_ID2:
576                 if (data->peap_version < 2 &&
577                     tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
578                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
579                                    "starting Phase2");
580                         eap_peap_state(data, PHASE2_START);
581                 }
582                 break;
583         case PHASE2_ID:
584         case PHASE2_METHOD:
585                 wpabuf_free(data->ssl.out_buf);
586                 data->ssl.out_used = 0;
587                 data->ssl.out_buf = eap_peap_build_phase2_req(sm, data, id);
588                 break;
589 #ifdef EAP_TNC
590         case PHASE2_SOH:
591                 wpabuf_free(data->ssl.out_buf);
592                 data->ssl.out_used = 0;
593                 data->ssl.out_buf = eap_peap_build_phase2_soh(sm, data, id);
594                 break;
595 #endif /* EAP_TNC */
596         case PHASE2_TLV:
597                 wpabuf_free(data->ssl.out_buf);
598                 data->ssl.out_used = 0;
599                 data->ssl.out_buf = eap_peap_build_phase2_tlv(sm, data, id);
600                 break;
601         case SUCCESS_REQ:
602                 wpabuf_free(data->ssl.out_buf);
603                 data->ssl.out_used = 0;
604                 data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
605                                                                1);
606                 break;
607         case FAILURE_REQ:
608                 wpabuf_free(data->ssl.out_buf);
609                 data->ssl.out_used = 0;
610                 data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
611                                                                0);
612                 break;
613         default:
614                 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
615                            __func__, data->state);
616                 return NULL;
617         }
618
619         return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
620                                         data->peap_version, id);
621 }
622
623
624 static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
625                               struct wpabuf *respData)
626 {
627         const u8 *pos;
628         size_t len;
629
630         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
631         if (pos == NULL || len < 1) {
632                 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
633                 return TRUE;
634         }
635
636         return FALSE;
637 }
638
639
640 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
641                                 EapType eap_type)
642 {
643         if (data->phase2_priv && data->phase2_method) {
644                 data->phase2_method->reset(sm, data->phase2_priv);
645                 data->phase2_method = NULL;
646                 data->phase2_priv = NULL;
647         }
648         data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
649                                                         eap_type);
650         if (!data->phase2_method)
651                 return -1;
652
653         sm->init_phase2 = 1;
654         data->phase2_priv = data->phase2_method->init(sm);
655         sm->init_phase2 = 0;
656         return 0;
657 }
658
659
660 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
661                                           struct eap_peap_data *data,
662                                           const u8 *crypto_tlv,
663                                           size_t crypto_tlv_len)
664 {
665         u8 buf[61], mac[SHA1_MAC_LEN];
666         const u8 *pos;
667
668         if (crypto_tlv_len != 4 + 56) {
669                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
670                            "length %d", (int) crypto_tlv_len);
671                 return -1;
672         }
673
674         pos = crypto_tlv;
675         pos += 4; /* TLV header */
676         if (pos[1] != data->peap_version) {
677                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
678                            "mismatch (was %d; expected %d)",
679                            pos[1], data->peap_version);
680                 return -1;
681         }
682
683         if (pos[3] != 1) {
684                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
685                            "SubType %d", pos[3]);
686                 return -1;
687         }
688         pos += 4;
689         pos += 32; /* Nonce */
690
691         /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
692         os_memcpy(buf, crypto_tlv, 60);
693         os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
694         buf[60] = EAP_TYPE_PEAP;
695         hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
696
697         if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
698                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
699                            "cryptobinding TLV");
700                 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);
701                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data",
702                             buf, 61);
703                 return -1;
704         }
705
706         wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
707
708         return 0;
709 }
710
711
712 static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
713                                         struct eap_peap_data *data,
714                                         struct wpabuf *in_data)
715 {
716         const u8 *pos;
717         size_t left;
718         const u8 *result_tlv = NULL, *crypto_tlv = NULL;
719         size_t result_tlv_len = 0, crypto_tlv_len = 0;
720         int tlv_type, mandatory, tlv_len;
721
722         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left);
723         if (pos == NULL) {
724                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header");
725                 return;
726         }
727
728         /* Parse TLVs */
729         wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left);
730         while (left >= 4) {
731                 mandatory = !!(pos[0] & 0x80);
732                 tlv_type = pos[0] & 0x3f;
733                 tlv_type = (tlv_type << 8) | pos[1];
734                 tlv_len = ((int) pos[2] << 8) | pos[3];
735                 pos += 4;
736                 left -= 4;
737                 if ((size_t) tlv_len > left) {
738                         wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
739                                    "(tlv_len=%d left=%lu)", tlv_len,
740                                    (unsigned long) left);
741                         eap_peap_state(data, FAILURE);
742                         return;
743                 }
744                 switch (tlv_type) {
745                 case EAP_TLV_RESULT_TLV:
746                         result_tlv = pos;
747                         result_tlv_len = tlv_len;
748                         break;
749                 case EAP_TLV_CRYPTO_BINDING_TLV:
750                         crypto_tlv = pos;
751                         crypto_tlv_len = tlv_len;
752                         break;
753                 default:
754                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
755                                    "%d%s", tlv_type,
756                                    mandatory ? " (mandatory)" : "");
757                         if (mandatory) {
758                                 eap_peap_state(data, FAILURE);
759                                 return;
760                         }
761                         /* Ignore this TLV, but process other TLVs */
762                         break;
763                 }
764
765                 pos += tlv_len;
766                 left -= tlv_len;
767         }
768         if (left) {
769                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
770                            "Request (left=%lu)", (unsigned long) left);
771                 eap_peap_state(data, FAILURE);
772                 return;
773         }
774
775         /* Process supported TLVs */
776         if (crypto_tlv && data->crypto_binding_sent) {
777                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
778                             crypto_tlv, crypto_tlv_len);
779                 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
780                                                    crypto_tlv_len + 4) < 0) {
781                         eap_peap_state(data, FAILURE);
782                         return;
783                 }
784                 data->crypto_binding_used = 1;
785         } else if (!crypto_tlv && data->crypto_binding_sent &&
786                    data->crypto_binding == REQUIRE_BINDING) {
787                 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
788                 eap_peap_state(data, FAILURE);
789                 return;
790         }
791
792         if (result_tlv) {
793                 int status;
794                 const char *requested;
795
796                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV",
797                             result_tlv, result_tlv_len);
798                 if (result_tlv_len < 2) {
799                         wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV "
800                                    "(len=%lu)",
801                                    (unsigned long) result_tlv_len);
802                         eap_peap_state(data, FAILURE);
803                         return;
804                 }
805                 requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" :
806                         "Failure";
807                 status = WPA_GET_BE16(result_tlv);
808                 if (status == EAP_TLV_RESULT_SUCCESS) {
809                         wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
810                                    "- requested %s", requested);
811                         if (data->tlv_request == TLV_REQ_SUCCESS)
812                                 eap_peap_state(data, SUCCESS);
813                         else
814                                 eap_peap_state(data, FAILURE);
815                         
816                 } else if (status == EAP_TLV_RESULT_FAILURE) {
817                         wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
818                                    "- requested %s", requested);
819                         eap_peap_state(data, FAILURE);
820                 } else {
821                         wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result "
822                                    "Status %d", status);
823                         eap_peap_state(data, FAILURE);
824                 }
825         }
826 }
827
828
829 #ifdef EAP_TNC
830 static void eap_peap_process_phase2_soh(struct eap_sm *sm,
831                                         struct eap_peap_data *data,
832                                         struct wpabuf *in_data)
833 {
834         const u8 *pos, *vpos;
835         size_t left;
836         const u8 *soh_tlv = NULL;
837         size_t soh_tlv_len = 0;
838         int tlv_type, mandatory, tlv_len, vtlv_len;
839         u8 next_type;
840         u32 vendor_id;
841
842         pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
843         if (pos == NULL) {
844                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP "
845                            "Extensions Method header - skip TNC");
846                 goto auth_method;
847         }
848
849         /* Parse TLVs */
850         wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left);
851         while (left >= 4) {
852                 mandatory = !!(pos[0] & 0x80);
853                 tlv_type = pos[0] & 0x3f;
854                 tlv_type = (tlv_type << 8) | pos[1];
855                 tlv_len = ((int) pos[2] << 8) | pos[3];
856                 pos += 4;
857                 left -= 4;
858                 if ((size_t) tlv_len > left) {
859                         wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
860                                    "(tlv_len=%d left=%lu)", tlv_len,
861                                    (unsigned long) left);
862                         eap_peap_state(data, FAILURE);
863                         return;
864                 }
865                 switch (tlv_type) {
866                 case EAP_TLV_VENDOR_SPECIFIC_TLV:
867                         if (tlv_len < 4) {
868                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short "
869                                            "vendor specific TLV (len=%d)",
870                                            (int) tlv_len);
871                                 eap_peap_state(data, FAILURE);
872                                 return;
873                         }
874
875                         vendor_id = WPA_GET_BE32(pos);
876                         if (vendor_id != EAP_VENDOR_MICROSOFT) {
877                                 if (mandatory) {
878                                         eap_peap_state(data, FAILURE);
879                                         return;
880                                 }
881                                 break;
882                         }
883
884                         vpos = pos + 4;
885                         mandatory = !!(vpos[0] & 0x80);
886                         tlv_type = vpos[0] & 0x3f;
887                         tlv_type = (tlv_type << 8) | vpos[1];
888                         vtlv_len = ((int) vpos[2] << 8) | vpos[3];
889                         vpos += 4;
890                         if (vpos + vtlv_len > pos + left) {
891                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV "
892                                            "underrun");
893                                 eap_peap_state(data, FAILURE);
894                                 return;
895                         }
896
897                         if (tlv_type == 1) {
898                                 soh_tlv = vpos;
899                                 soh_tlv_len = vtlv_len;
900                                 break;
901                         }
902
903                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV "
904                                    "Type %d%s", tlv_type,
905                                    mandatory ? " (mandatory)" : "");
906                         if (mandatory) {
907                                 eap_peap_state(data, FAILURE);
908                                 return;
909                         }
910                         /* Ignore this TLV, but process other TLVs */
911                         break;
912                 default:
913                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
914                                    "%d%s", tlv_type,
915                                    mandatory ? " (mandatory)" : "");
916                         if (mandatory) {
917                                 eap_peap_state(data, FAILURE);
918                                 return;
919                         }
920                         /* Ignore this TLV, but process other TLVs */
921                         break;
922                 }
923
924                 pos += tlv_len;
925                 left -= tlv_len;
926         }
927         if (left) {
928                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
929                            "Request (left=%lu)", (unsigned long) left);
930                 eap_peap_state(data, FAILURE);
931                 return;
932         }
933
934         /* Process supported TLVs */
935         if (soh_tlv) {
936                 int failure = 0;
937                 wpabuf_free(data->soh_response);
938                 data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len,
939                                                       &failure);
940                 if (failure) {
941                         eap_peap_state(data, FAILURE);
942                         return;
943                 }
944         } else {
945                 wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received");
946                 eap_peap_state(data, FAILURE);
947                 return;
948         }
949
950 auth_method:
951         eap_peap_state(data, PHASE2_METHOD);
952         next_type = sm->user->methods[0].method;
953         sm->user_eap_method_index = 1;
954         wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
955         eap_peap_phase2_init(sm, data, next_type);
956 }
957 #endif /* EAP_TNC */
958
959
960 static void eap_peap_process_phase2_response(struct eap_sm *sm,
961                                              struct eap_peap_data *data,
962                                              struct wpabuf *in_data)
963 {
964         u8 next_type = EAP_TYPE_NONE;
965         const struct eap_hdr *hdr;
966         const u8 *pos;
967         size_t left;
968
969         if (data->state == PHASE2_TLV) {
970                 eap_peap_process_phase2_tlv(sm, data, in_data);
971                 return;
972         }
973
974 #ifdef EAP_TNC
975         if (data->state == PHASE2_SOH) {
976                 eap_peap_process_phase2_soh(sm, data, in_data);
977                 return;
978         }
979 #endif /* EAP_TNC */
980
981         if (data->phase2_priv == NULL) {
982                 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
983                            "initialized?!", __func__);
984                 return;
985         }
986
987         hdr = wpabuf_head(in_data);
988         pos = (const u8 *) (hdr + 1);
989
990         if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
991                 left = wpabuf_len(in_data) - sizeof(*hdr);
992                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
993                             "allowed types", pos + 1, left - 1);
994                 eap_sm_process_nak(sm, pos + 1, left - 1);
995                 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
996                     sm->user->methods[sm->user_eap_method_index].method !=
997                     EAP_TYPE_NONE) {
998                         next_type = sm->user->methods[
999                                 sm->user_eap_method_index++].method;
1000                         wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
1001                                    next_type);
1002                 } else {
1003                         eap_peap_req_failure(sm, data);
1004                         next_type = EAP_TYPE_NONE;
1005                 }
1006                 eap_peap_phase2_init(sm, data, next_type);
1007                 return;
1008         }
1009
1010         if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
1011                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
1012                            "ignore the packet");
1013                 return;
1014         }
1015
1016         data->phase2_method->process(sm, data->phase2_priv, in_data);
1017
1018         if (sm->method_pending == METHOD_PENDING_WAIT) {
1019                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
1020                            "pending wait state - save decrypted response");
1021                 wpabuf_free(data->pending_phase2_resp);
1022                 data->pending_phase2_resp = wpabuf_dup(in_data);
1023         }
1024
1025         if (!data->phase2_method->isDone(sm, data->phase2_priv))
1026                 return;
1027
1028         if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
1029                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
1030                 eap_peap_req_failure(sm, data);
1031                 next_type = EAP_TYPE_NONE;
1032                 eap_peap_phase2_init(sm, data, next_type);
1033                 return;
1034         }
1035
1036         os_free(data->phase2_key);
1037         if (data->phase2_method->getKey) {
1038                 data->phase2_key = data->phase2_method->getKey(
1039                         sm, data->phase2_priv, &data->phase2_key_len);
1040                 if (data->phase2_key == NULL) {
1041                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
1042                                    "failed");
1043                         eap_peap_req_failure(sm, data);
1044                         eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
1045                         return;
1046                 }
1047
1048                 if (data->phase2_key_len == 32 &&
1049                     data->phase2_method->vendor == EAP_VENDOR_IETF &&
1050                     data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
1051                         /*
1052                          * Microsoft uses reverse order for MS-MPPE keys in
1053                          * EAP-PEAP when compared to EAP-FAST derivation of
1054                          * ISK. Swap the keys here to get the correct ISK for
1055                          * EAP-PEAPv0 cryptobinding.
1056                          */
1057                         u8 tmp[16];
1058                         os_memcpy(tmp, data->phase2_key, 16);
1059                         os_memcpy(data->phase2_key, data->phase2_key + 16, 16);
1060                         os_memcpy(data->phase2_key + 16, tmp, 16);
1061                 }
1062         }
1063
1064         switch (data->state) {
1065         case PHASE1_ID2:
1066         case PHASE2_ID:
1067         case PHASE2_SOH:
1068                 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1069                         wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
1070                                           "Identity not found in the user "
1071                                           "database",
1072                                           sm->identity, sm->identity_len);
1073                         eap_peap_req_failure(sm, data);
1074                         next_type = EAP_TYPE_NONE;
1075                         break;
1076                 }
1077
1078 #ifdef EAP_TNC
1079                 if (data->state != PHASE2_SOH && sm->tnc &&
1080                     data->peap_version == 0) {
1081                         eap_peap_state(data, PHASE2_SOH);
1082                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
1083                                    "TNC (NAP SOH)");
1084                         next_type = EAP_TYPE_NONE;
1085                         break;
1086                 }
1087 #endif /* EAP_TNC */
1088
1089                 eap_peap_state(data, PHASE2_METHOD);
1090                 next_type = sm->user->methods[0].method;
1091                 sm->user_eap_method_index = 1;
1092                 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
1093                 break;
1094         case PHASE2_METHOD:
1095                 eap_peap_req_success(sm, data);
1096                 next_type = EAP_TYPE_NONE;
1097                 break;
1098         case FAILURE:
1099                 break;
1100         default:
1101                 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
1102                            __func__, data->state);
1103                 break;
1104         }
1105
1106         eap_peap_phase2_init(sm, data, next_type);
1107 }
1108
1109
1110 static void eap_peap_process_phase2(struct eap_sm *sm,
1111                                     struct eap_peap_data *data,
1112                                     const struct wpabuf *respData,
1113                                     const u8 *in_data, size_t in_len)
1114 {
1115         struct wpabuf *in_decrypted;
1116         int len_decrypted;
1117         const struct eap_hdr *hdr;
1118         size_t buf_len, len;
1119
1120         wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
1121                    " Phase 2", (unsigned long) in_len);
1122
1123         if (data->pending_phase2_resp) {
1124                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
1125                            "skip decryption and use old data");
1126                 eap_peap_process_phase2_response(sm, data,
1127                                                  data->pending_phase2_resp);
1128                 wpabuf_free(data->pending_phase2_resp);
1129                 data->pending_phase2_resp = NULL;
1130                 return;
1131         }
1132
1133         buf_len = in_len;
1134         /*
1135          * Even though we try to disable TLS compression, it is possible that
1136          * this cannot be done with all TLS libraries. Add extra buffer space
1137          * to handle the possibility of the decrypted data being longer than
1138          * input data.
1139          */
1140         buf_len += 500;
1141         buf_len *= 3;
1142         in_decrypted = wpabuf_alloc(buf_len);
1143         if (in_decrypted == NULL) {
1144                 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
1145                            "for decryption");
1146                 return;
1147         }
1148
1149         len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
1150                                                in_data, in_len,
1151                                                wpabuf_mhead(in_decrypted),
1152                                                buf_len);
1153         if (len_decrypted < 0) {
1154                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1155                            "data");
1156                 wpabuf_free(in_decrypted);
1157                 eap_peap_state(data, FAILURE);
1158                 return;
1159         }
1160         wpabuf_put(in_decrypted, len_decrypted);
1161
1162         wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1163                             in_decrypted);
1164
1165         hdr = wpabuf_head(in_decrypted);
1166
1167         if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1168                 const struct eap_hdr *resp;
1169                 struct eap_hdr *nhdr;
1170                 struct wpabuf *nbuf =
1171                         wpabuf_alloc(sizeof(struct eap_hdr) +
1172                                      wpabuf_len(in_decrypted));
1173                 if (nbuf == NULL) {
1174                         wpabuf_free(in_decrypted);
1175                         return;
1176                 }
1177
1178                 resp = wpabuf_head(respData);
1179                 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1180                 nhdr->code = resp->code;
1181                 nhdr->identifier = resp->identifier;
1182                 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1183                                             wpabuf_len(in_decrypted));
1184                 wpabuf_put_buf(nbuf, in_decrypted);
1185                 wpabuf_free(in_decrypted);
1186
1187                 in_decrypted = nbuf;
1188         } else if (data->peap_version >= 2) {
1189                 struct eap_tlv_hdr *tlv;
1190                 struct wpabuf *nmsg;
1191
1192                 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
1193                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
1194                                    "EAP TLV");
1195                         wpabuf_free(in_decrypted);
1196                         return;
1197                 }
1198                 tlv = wpabuf_mhead(in_decrypted);
1199                 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
1200                     EAP_TLV_EAP_PAYLOAD_TLV) {
1201                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
1202                         wpabuf_free(in_decrypted);
1203                         return;
1204                 }
1205                 if (sizeof(*tlv) + be_to_host16(tlv->length) >
1206                     wpabuf_len(in_decrypted)) {
1207                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
1208                                    "length");
1209                         wpabuf_free(in_decrypted);
1210                         return;
1211                 }
1212                 hdr = (struct eap_hdr *) (tlv + 1);
1213                 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
1214                         wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
1215                                    "EAP packet in EAP TLV");
1216                         wpabuf_free(in_decrypted);
1217                         return;
1218                 }
1219
1220                 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
1221                 if (nmsg == NULL) {
1222                         wpabuf_free(in_decrypted);
1223                         return;
1224                 }
1225
1226                 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
1227                 wpabuf_free(in_decrypted);
1228                 in_decrypted = nmsg;
1229         }
1230
1231         hdr = wpabuf_head(in_decrypted);
1232         if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1233                 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1234                            "EAP frame (len=%lu)",
1235                            (unsigned long) wpabuf_len(in_decrypted));
1236                 wpabuf_free(in_decrypted);
1237                 eap_peap_req_failure(sm, data);
1238                 return;
1239         }
1240         len = be_to_host16(hdr->length);
1241         if (len > wpabuf_len(in_decrypted)) {
1242                 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1243                            "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1244                            (unsigned long) wpabuf_len(in_decrypted),
1245                            (unsigned long) len);
1246                 wpabuf_free(in_decrypted);
1247                 eap_peap_req_failure(sm, data);
1248                 return;
1249         }
1250         wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1251                    "identifier=%d length=%lu", hdr->code, hdr->identifier,
1252                    (unsigned long) len);
1253         switch (hdr->code) {
1254         case EAP_CODE_RESPONSE:
1255                 eap_peap_process_phase2_response(sm, data, in_decrypted);
1256                 break;
1257         case EAP_CODE_SUCCESS:
1258                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1259                 if (data->state == SUCCESS_REQ) {
1260                         eap_peap_state(data, SUCCESS);
1261                 }
1262                 break;
1263         case EAP_CODE_FAILURE:
1264                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1265                 eap_peap_state(data, FAILURE);
1266                 break;
1267         default:
1268                 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1269                            "Phase 2 EAP header", hdr->code);
1270                 break;
1271         }
1272
1273         os_free(in_decrypted);
1274 }
1275
1276
1277 static int eap_peapv2_start_phase2(struct eap_sm *sm,
1278                                    struct eap_peap_data *data)
1279 {
1280         struct wpabuf *buf, *buf2;
1281         int res;
1282
1283         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1284                    "payload in the same message");
1285         eap_peap_state(data, PHASE1_ID2);
1286         if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
1287                 return -1;
1288
1289         /* TODO: which Id to use here? */
1290         buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
1291         if (buf == NULL)
1292                 return -1;
1293
1294         buf2 = eap_peapv2_tlv_eap_payload(buf);
1295         if (buf2 == NULL)
1296                 return -1;
1297
1298         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
1299
1300         buf = wpabuf_alloc(data->ssl.tls_out_limit);
1301         if (buf == NULL) {
1302                 wpabuf_free(buf2);
1303                 return -1;
1304         }
1305
1306         res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
1307                                      wpabuf_head(buf2), wpabuf_len(buf2),
1308                                      wpabuf_put(buf, 0),
1309                                      data->ssl.tls_out_limit);
1310         wpabuf_free(buf2);
1311
1312         if (res < 0) {
1313                 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1314                            "data");
1315                 wpabuf_free(buf);
1316                 return -1;
1317         }
1318
1319         wpabuf_put(buf, res);
1320         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
1321                         buf);
1322
1323         /* Append TLS data into the pending buffer after the Server Finished */
1324         if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {
1325                 wpabuf_free(buf);
1326                 return -1;
1327         }
1328         wpabuf_put_buf(data->ssl.out_buf, buf);
1329         wpabuf_free(buf);
1330
1331         return 0;
1332 }
1333
1334
1335 static void eap_peap_process(struct eap_sm *sm, void *priv,
1336                              struct wpabuf *respData)
1337 {
1338         struct eap_peap_data *data = priv;
1339         const u8 *pos;
1340         u8 flags;
1341         size_t left;
1342         int peer_version;
1343         int ret;
1344
1345         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
1346                                &left);
1347         if (pos == NULL || left < 1)
1348                 return;
1349         flags = *pos++;
1350         left--;
1351         wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
1352                    "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
1353                    flags);
1354         data->recv_version = peer_version = flags & EAP_TLS_VERSION_MASK;
1355         if (data->force_version >= 0 && peer_version != data->force_version) {
1356                 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1357                            " version (forced=%d peer=%d) - reject",
1358                            data->force_version, peer_version);
1359                 eap_peap_state(data, FAILURE);
1360                 return;
1361         }
1362         if (peer_version < data->peap_version) {
1363                 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1364                            "use version %d",
1365                            peer_version, data->peap_version, peer_version);
1366                 data->peap_version = peer_version;
1367         }
1368
1369         ret = eap_server_tls_reassemble(&data->ssl, flags, &pos, &left);
1370         if (ret < 0) {
1371                 eap_peap_state(data, FAILURE);
1372                 return;
1373         } else if (ret == 1)
1374                 return;
1375
1376         switch (data->state) {
1377         case PHASE1:
1378                 if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1379                         eap_peap_state(data, FAILURE);
1380                         break;
1381                 }
1382
1383                 if (data->peap_version >= 2 &&
1384                     tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1385                         if (eap_peapv2_start_phase2(sm, data)) {
1386                                 eap_peap_state(data, FAILURE);
1387                                 break;
1388                         }
1389                 }
1390                 break;
1391         case PHASE2_START:
1392                 eap_peap_state(data, PHASE2_ID);
1393                 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
1394                 break;
1395         case PHASE1_ID2:
1396         case PHASE2_ID:
1397         case PHASE2_METHOD:
1398         case PHASE2_SOH:
1399         case PHASE2_TLV:
1400                 eap_peap_process_phase2(sm, data, respData, pos, left);
1401                 break;
1402         case SUCCESS_REQ:
1403                 eap_peap_state(data, SUCCESS);
1404                 break;
1405         case FAILURE_REQ:
1406                 eap_peap_state(data, FAILURE);
1407                 break;
1408         default:
1409                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1410                            data->state, __func__);
1411                 break;
1412         }
1413
1414         if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
1415                 wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
1416                            "in TLS processing");
1417                 eap_peap_state(data, FAILURE);
1418         }
1419
1420         eap_server_tls_free_in_buf(&data->ssl);
1421 }
1422
1423
1424 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
1425 {
1426         struct eap_peap_data *data = priv;
1427         return data->state == SUCCESS || data->state == FAILURE;
1428 }
1429
1430
1431 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1432 {
1433         struct eap_peap_data *data = priv;
1434         u8 *eapKeyData;
1435
1436         if (data->state != SUCCESS)
1437                 return NULL;
1438
1439         if (data->crypto_binding_used) {
1440                 u8 csk[128];
1441                 /*
1442                  * Note: It looks like Microsoft implementation requires null
1443                  * termination for this label while the one used for deriving
1444                  * IPMK|CMK did not use null termination.
1445                  */
1446                 peap_prfplus(data->peap_version, data->ipmk, 40,
1447                              "Session Key Generating Function",
1448                              (u8 *) "\00", 1, csk, sizeof(csk));
1449                 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1450                 eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1451                 if (eapKeyData) {
1452                         os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1453                         *len = EAP_TLS_KEY_LEN;
1454                         wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1455                                     eapKeyData, EAP_TLS_KEY_LEN);
1456                 } else {
1457                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1458                                    "key");
1459                 }
1460
1461                 return eapKeyData;
1462         }
1463
1464         /* TODO: PEAPv1 - different label in some cases */
1465         eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1466                                                "client EAP encryption",
1467                                                EAP_TLS_KEY_LEN);
1468         if (eapKeyData) {
1469                 *len = EAP_TLS_KEY_LEN;
1470                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1471                             eapKeyData, EAP_TLS_KEY_LEN);
1472         } else {
1473                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1474         }
1475
1476         return eapKeyData;
1477 }
1478
1479
1480 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1481 {
1482         struct eap_peap_data *data = priv;
1483         return data->state == SUCCESS;
1484 }
1485
1486
1487 int eap_server_peap_register(void)
1488 {
1489         struct eap_method *eap;
1490         int ret;
1491
1492         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1493                                       EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1494         if (eap == NULL)
1495                 return -1;
1496
1497         eap->init = eap_peap_init;
1498         eap->reset = eap_peap_reset;
1499         eap->buildReq = eap_peap_buildReq;
1500         eap->check = eap_peap_check;
1501         eap->process = eap_peap_process;
1502         eap->isDone = eap_peap_isDone;
1503         eap->getKey = eap_peap_getKey;
1504         eap->isSuccess = eap_peap_isSuccess;
1505
1506         ret = eap_server_method_register(eap);
1507         if (ret)
1508                 eap_server_method_free(eap);
1509         return ret;
1510 }