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