da73e02a6cfc6613c1bd966a3c6d417eeab3d5ba
[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                                     struct wpabuf *in_buf)
1114 {
1115         struct wpabuf *in_decrypted;
1116         int len_decrypted;
1117         const struct eap_hdr *hdr;
1118         size_t buf_len, len;
1119         u8 *in_data;
1120         size_t in_len;
1121
1122         in_data = wpabuf_mhead(in_buf);
1123         in_len = wpabuf_len(in_buf);
1124
1125         wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
1126                    " Phase 2", (unsigned long) in_len);
1127
1128         if (data->pending_phase2_resp) {
1129                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
1130                            "skip decryption and use old data");
1131                 eap_peap_process_phase2_response(sm, data,
1132                                                  data->pending_phase2_resp);
1133                 wpabuf_free(data->pending_phase2_resp);
1134                 data->pending_phase2_resp = NULL;
1135                 return;
1136         }
1137
1138         buf_len = in_len;
1139         /*
1140          * Even though we try to disable TLS compression, it is possible that
1141          * this cannot be done with all TLS libraries. Add extra buffer space
1142          * to handle the possibility of the decrypted data being longer than
1143          * input data.
1144          */
1145         buf_len += 500;
1146         buf_len *= 3;
1147         in_decrypted = wpabuf_alloc(buf_len);
1148         if (in_decrypted == NULL) {
1149                 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
1150                            "for decryption");
1151                 return;
1152         }
1153
1154         len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
1155                                                in_data, in_len,
1156                                                wpabuf_mhead(in_decrypted),
1157                                                buf_len);
1158         if (len_decrypted < 0) {
1159                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1160                            "data");
1161                 wpabuf_free(in_decrypted);
1162                 eap_peap_state(data, FAILURE);
1163                 return;
1164         }
1165         wpabuf_put(in_decrypted, len_decrypted);
1166
1167         wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1168                             in_decrypted);
1169
1170         hdr = wpabuf_head(in_decrypted);
1171
1172         if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1173                 const struct eap_hdr *resp;
1174                 struct eap_hdr *nhdr;
1175                 struct wpabuf *nbuf =
1176                         wpabuf_alloc(sizeof(struct eap_hdr) +
1177                                      wpabuf_len(in_decrypted));
1178                 if (nbuf == NULL) {
1179                         wpabuf_free(in_decrypted);
1180                         return;
1181                 }
1182
1183                 resp = wpabuf_head(respData);
1184                 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1185                 nhdr->code = resp->code;
1186                 nhdr->identifier = resp->identifier;
1187                 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1188                                             wpabuf_len(in_decrypted));
1189                 wpabuf_put_buf(nbuf, in_decrypted);
1190                 wpabuf_free(in_decrypted);
1191
1192                 in_decrypted = nbuf;
1193         } else if (data->peap_version >= 2) {
1194                 struct eap_tlv_hdr *tlv;
1195                 struct wpabuf *nmsg;
1196
1197                 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
1198                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
1199                                    "EAP TLV");
1200                         wpabuf_free(in_decrypted);
1201                         return;
1202                 }
1203                 tlv = wpabuf_mhead(in_decrypted);
1204                 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
1205                     EAP_TLV_EAP_PAYLOAD_TLV) {
1206                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
1207                         wpabuf_free(in_decrypted);
1208                         return;
1209                 }
1210                 if (sizeof(*tlv) + be_to_host16(tlv->length) >
1211                     wpabuf_len(in_decrypted)) {
1212                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
1213                                    "length");
1214                         wpabuf_free(in_decrypted);
1215                         return;
1216                 }
1217                 hdr = (struct eap_hdr *) (tlv + 1);
1218                 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
1219                         wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
1220                                    "EAP packet in EAP TLV");
1221                         wpabuf_free(in_decrypted);
1222                         return;
1223                 }
1224
1225                 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
1226                 if (nmsg == NULL) {
1227                         wpabuf_free(in_decrypted);
1228                         return;
1229                 }
1230
1231                 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
1232                 wpabuf_free(in_decrypted);
1233                 in_decrypted = nmsg;
1234         }
1235
1236         hdr = wpabuf_head(in_decrypted);
1237         if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1238                 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1239                            "EAP frame (len=%lu)",
1240                            (unsigned long) wpabuf_len(in_decrypted));
1241                 wpabuf_free(in_decrypted);
1242                 eap_peap_req_failure(sm, data);
1243                 return;
1244         }
1245         len = be_to_host16(hdr->length);
1246         if (len > wpabuf_len(in_decrypted)) {
1247                 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1248                            "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1249                            (unsigned long) wpabuf_len(in_decrypted),
1250                            (unsigned long) len);
1251                 wpabuf_free(in_decrypted);
1252                 eap_peap_req_failure(sm, data);
1253                 return;
1254         }
1255         wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1256                    "identifier=%d length=%lu", hdr->code, hdr->identifier,
1257                    (unsigned long) len);
1258         switch (hdr->code) {
1259         case EAP_CODE_RESPONSE:
1260                 eap_peap_process_phase2_response(sm, data, in_decrypted);
1261                 break;
1262         case EAP_CODE_SUCCESS:
1263                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1264                 if (data->state == SUCCESS_REQ) {
1265                         eap_peap_state(data, SUCCESS);
1266                 }
1267                 break;
1268         case EAP_CODE_FAILURE:
1269                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1270                 eap_peap_state(data, FAILURE);
1271                 break;
1272         default:
1273                 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1274                            "Phase 2 EAP header", hdr->code);
1275                 break;
1276         }
1277
1278         os_free(in_decrypted);
1279 }
1280
1281
1282 static int eap_peapv2_start_phase2(struct eap_sm *sm,
1283                                    struct eap_peap_data *data)
1284 {
1285         struct wpabuf *buf, *buf2;
1286         int res;
1287
1288         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1289                    "payload in the same message");
1290         eap_peap_state(data, PHASE1_ID2);
1291         if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
1292                 return -1;
1293
1294         /* TODO: which Id to use here? */
1295         buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
1296         if (buf == NULL)
1297                 return -1;
1298
1299         buf2 = eap_peapv2_tlv_eap_payload(buf);
1300         if (buf2 == NULL)
1301                 return -1;
1302
1303         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
1304
1305         buf = wpabuf_alloc(data->ssl.tls_out_limit);
1306         if (buf == NULL) {
1307                 wpabuf_free(buf2);
1308                 return -1;
1309         }
1310
1311         res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
1312                                      wpabuf_head(buf2), wpabuf_len(buf2),
1313                                      wpabuf_put(buf, 0),
1314                                      data->ssl.tls_out_limit);
1315         wpabuf_free(buf2);
1316
1317         if (res < 0) {
1318                 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1319                            "data");
1320                 wpabuf_free(buf);
1321                 return -1;
1322         }
1323
1324         wpabuf_put(buf, res);
1325         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
1326                         buf);
1327
1328         /* Append TLS data into the pending buffer after the Server Finished */
1329         if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {
1330                 wpabuf_free(buf);
1331                 return -1;
1332         }
1333         wpabuf_put_buf(data->ssl.out_buf, buf);
1334         wpabuf_free(buf);
1335
1336         return 0;
1337 }
1338
1339
1340 static int eap_peap_process_version(struct eap_sm *sm, void *priv,
1341                                     int peer_version)
1342 {
1343         struct eap_peap_data *data = priv;
1344
1345         data->recv_version = peer_version;
1346         if (data->force_version >= 0 && peer_version != data->force_version) {
1347                 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1348                            " version (forced=%d peer=%d) - reject",
1349                            data->force_version, peer_version);
1350                 return -1;
1351         }
1352         if (peer_version < data->peap_version) {
1353                 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1354                            "use version %d",
1355                            peer_version, data->peap_version, peer_version);
1356                 data->peap_version = peer_version;
1357         }
1358
1359         return 0;
1360 }
1361
1362
1363 static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
1364                                  const struct wpabuf *respData)
1365 {
1366         struct eap_peap_data *data = priv;
1367
1368         switch (data->state) {
1369         case PHASE1:
1370                 if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1371                         eap_peap_state(data, FAILURE);
1372                         break;
1373                 }
1374
1375                 if (data->peap_version >= 2 &&
1376                     tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1377                         if (eap_peapv2_start_phase2(sm, data)) {
1378                                 eap_peap_state(data, FAILURE);
1379                                 break;
1380                         }
1381                 }
1382                 break;
1383         case PHASE2_START:
1384                 eap_peap_state(data, PHASE2_ID);
1385                 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
1386                 break;
1387         case PHASE1_ID2:
1388         case PHASE2_ID:
1389         case PHASE2_METHOD:
1390         case PHASE2_SOH:
1391         case PHASE2_TLV:
1392                 eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf);
1393                 break;
1394         case SUCCESS_REQ:
1395                 eap_peap_state(data, SUCCESS);
1396                 break;
1397         case FAILURE_REQ:
1398                 eap_peap_state(data, FAILURE);
1399                 break;
1400         default:
1401                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1402                            data->state, __func__);
1403                 break;
1404         }
1405 }
1406
1407
1408 static void eap_peap_process(struct eap_sm *sm, void *priv,
1409                              struct wpabuf *respData)
1410 {
1411         struct eap_peap_data *data = priv;
1412         if (eap_server_tls_process(sm, &data->ssl, respData, data,
1413                                    EAP_TYPE_PEAP, eap_peap_process_version,
1414                                    eap_peap_process_msg) < 0)
1415                 eap_peap_state(data, FAILURE);
1416 }
1417
1418
1419 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
1420 {
1421         struct eap_peap_data *data = priv;
1422         return data->state == SUCCESS || data->state == FAILURE;
1423 }
1424
1425
1426 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1427 {
1428         struct eap_peap_data *data = priv;
1429         u8 *eapKeyData;
1430
1431         if (data->state != SUCCESS)
1432                 return NULL;
1433
1434         if (data->crypto_binding_used) {
1435                 u8 csk[128];
1436                 /*
1437                  * Note: It looks like Microsoft implementation requires null
1438                  * termination for this label while the one used for deriving
1439                  * IPMK|CMK did not use null termination.
1440                  */
1441                 peap_prfplus(data->peap_version, data->ipmk, 40,
1442                              "Session Key Generating Function",
1443                              (u8 *) "\00", 1, csk, sizeof(csk));
1444                 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1445                 eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1446                 if (eapKeyData) {
1447                         os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1448                         *len = EAP_TLS_KEY_LEN;
1449                         wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1450                                     eapKeyData, EAP_TLS_KEY_LEN);
1451                 } else {
1452                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1453                                    "key");
1454                 }
1455
1456                 return eapKeyData;
1457         }
1458
1459         /* TODO: PEAPv1 - different label in some cases */
1460         eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1461                                                "client EAP encryption",
1462                                                EAP_TLS_KEY_LEN);
1463         if (eapKeyData) {
1464                 *len = EAP_TLS_KEY_LEN;
1465                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1466                             eapKeyData, EAP_TLS_KEY_LEN);
1467         } else {
1468                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1469         }
1470
1471         return eapKeyData;
1472 }
1473
1474
1475 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1476 {
1477         struct eap_peap_data *data = priv;
1478         return data->state == SUCCESS;
1479 }
1480
1481
1482 int eap_server_peap_register(void)
1483 {
1484         struct eap_method *eap;
1485         int ret;
1486
1487         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1488                                       EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1489         if (eap == NULL)
1490                 return -1;
1491
1492         eap->init = eap_peap_init;
1493         eap->reset = eap_peap_reset;
1494         eap->buildReq = eap_peap_buildReq;
1495         eap->check = eap_peap_check;
1496         eap->process = eap_peap_process;
1497         eap->isDone = eap_peap_isDone;
1498         eap->getKey = eap_peap_getKey;
1499         eap->isSuccess = eap_peap_isSuccess;
1500
1501         ret = eap_server_method_register(eap);
1502         if (ret)
1503                 eap_server_method_free(eap);
1504         return ret;
1505 }