20e1953c5baa5dead4249629da4a4bd94072a3cb
[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         in_decrypted = wpabuf_alloc(buf_len);
1165         if (in_decrypted == NULL) {
1166                 os_free(data->ssl.tls_in);
1167                 data->ssl.tls_in = NULL;
1168                 data->ssl.tls_in_len = 0;
1169                 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
1170                            "for decryption");
1171                 return;
1172         }
1173
1174         len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
1175                                                in_data, in_len,
1176                                                wpabuf_mhead(in_decrypted),
1177                                                buf_len);
1178         os_free(data->ssl.tls_in);
1179         data->ssl.tls_in = NULL;
1180         data->ssl.tls_in_len = 0;
1181         if (len_decrypted < 0) {
1182                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1183                            "data");
1184                 wpabuf_free(in_decrypted);
1185                 eap_peap_state(data, FAILURE);
1186                 return;
1187         }
1188         wpabuf_put(in_decrypted, len_decrypted);
1189
1190         wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1191                             in_decrypted);
1192
1193         hdr = wpabuf_head(in_decrypted);
1194
1195         if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1196                 const struct eap_hdr *resp;
1197                 struct eap_hdr *nhdr;
1198                 struct wpabuf *nbuf =
1199                         wpabuf_alloc(sizeof(struct eap_hdr) +
1200                                      wpabuf_len(in_decrypted));
1201                 if (nbuf == NULL) {
1202                         wpabuf_free(in_decrypted);
1203                         return;
1204                 }
1205
1206                 resp = wpabuf_head(respData);
1207                 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1208                 nhdr->code = resp->code;
1209                 nhdr->identifier = resp->identifier;
1210                 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1211                                             wpabuf_len(in_decrypted));
1212                 wpabuf_put_buf(nbuf, in_decrypted);
1213                 wpabuf_free(in_decrypted);
1214
1215                 in_decrypted = nbuf;
1216         } else if (data->peap_version >= 2) {
1217                 struct eap_tlv_hdr *tlv;
1218                 struct wpabuf *nmsg;
1219
1220                 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
1221                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
1222                                    "EAP TLV");
1223                         wpabuf_free(in_decrypted);
1224                         return;
1225                 }
1226                 tlv = wpabuf_mhead(in_decrypted);
1227                 if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
1228                     EAP_TLV_EAP_PAYLOAD_TLV) {
1229                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
1230                         wpabuf_free(in_decrypted);
1231                         return;
1232                 }
1233                 if (sizeof(*tlv) + be_to_host16(tlv->length) >
1234                     wpabuf_len(in_decrypted)) {
1235                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
1236                                    "length");
1237                         wpabuf_free(in_decrypted);
1238                         return;
1239                 }
1240                 hdr = (struct eap_hdr *) (tlv + 1);
1241                 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
1242                         wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
1243                                    "EAP packet in EAP TLV");
1244                         wpabuf_free(in_decrypted);
1245                         return;
1246                 }
1247
1248                 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
1249                 if (nmsg == NULL) {
1250                         wpabuf_free(in_decrypted);
1251                         return;
1252                 }
1253
1254                 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
1255                 wpabuf_free(in_decrypted);
1256                 in_decrypted = nmsg;
1257         }
1258
1259         hdr = wpabuf_head(in_decrypted);
1260         if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1261                 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1262                            "EAP frame (len=%lu)",
1263                            (unsigned long) wpabuf_len(in_decrypted));
1264                 wpabuf_free(in_decrypted);
1265                 eap_peap_req_failure(sm, data);
1266                 return;
1267         }
1268         len = be_to_host16(hdr->length);
1269         if (len > wpabuf_len(in_decrypted)) {
1270                 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1271                            "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1272                            (unsigned long) wpabuf_len(in_decrypted),
1273                            (unsigned long) len);
1274                 wpabuf_free(in_decrypted);
1275                 eap_peap_req_failure(sm, data);
1276                 return;
1277         }
1278         wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1279                    "identifier=%d length=%lu", hdr->code, hdr->identifier,
1280                    (unsigned long) len);
1281         switch (hdr->code) {
1282         case EAP_CODE_RESPONSE:
1283                 eap_peap_process_phase2_response(sm, data, in_decrypted);
1284                 break;
1285         case EAP_CODE_SUCCESS:
1286                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1287                 if (data->state == SUCCESS_REQ) {
1288                         eap_peap_state(data, SUCCESS);
1289                 }
1290                 break;
1291         case EAP_CODE_FAILURE:
1292                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1293                 eap_peap_state(data, FAILURE);
1294                 break;
1295         default:
1296                 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1297                            "Phase 2 EAP header", hdr->code);
1298                 break;
1299         }
1300
1301         os_free(in_decrypted);
1302 }
1303
1304
1305 static int eap_peapv2_start_phase2(struct eap_sm *sm,
1306                                    struct eap_peap_data *data)
1307 {
1308         struct wpabuf *buf, *buf2;
1309         int res;
1310         u8 *tls_out;
1311
1312         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
1313                    "payload in the same message");
1314         eap_peap_state(data, PHASE1_ID2);
1315         if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
1316                 return -1;
1317
1318         /* TODO: which Id to use here? */
1319         buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
1320         if (buf == NULL)
1321                 return -1;
1322
1323         buf2 = eap_peapv2_tlv_eap_payload(buf);
1324         if (buf2 == NULL)
1325                 return -1;
1326
1327         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
1328
1329         buf = wpabuf_alloc(data->ssl.tls_out_limit);
1330         if (buf == NULL) {
1331                 wpabuf_free(buf2);
1332                 return -1;
1333         }
1334
1335         res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
1336                                      wpabuf_head(buf2), wpabuf_len(buf2),
1337                                      wpabuf_put(buf, 0),
1338                                      data->ssl.tls_out_limit);
1339         wpabuf_free(buf2);
1340
1341         if (res < 0) {
1342                 wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
1343                            "data");
1344                 wpabuf_free(buf);
1345                 return -1;
1346         }
1347
1348         wpabuf_put(buf, res);
1349         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
1350                         buf);
1351
1352         /* Append TLS data into the pending buffer after the Server Finished */
1353         tls_out = os_realloc(data->ssl.tls_out,
1354                              data->ssl.tls_out_len + wpabuf_len(buf));
1355         if (tls_out == NULL) {
1356                 wpabuf_free(buf);
1357                 return -1;
1358         }
1359
1360         os_memcpy(tls_out + data->ssl.tls_out_len, wpabuf_head(buf),
1361                   wpabuf_len(buf));
1362         data->ssl.tls_out = tls_out;
1363         data->ssl.tls_out_len += wpabuf_len(buf);
1364
1365         wpabuf_free(buf);
1366
1367         return 0;
1368 }
1369
1370
1371 static void eap_peap_process(struct eap_sm *sm, void *priv,
1372                              struct wpabuf *respData)
1373 {
1374         struct eap_peap_data *data = priv;
1375         const u8 *pos;
1376         u8 flags;
1377         size_t left;
1378         unsigned int tls_msg_len;
1379         int peer_version;
1380
1381         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
1382                                &left);
1383         if (pos == NULL || left < 1)
1384                 return;
1385         flags = *pos++;
1386         left--;
1387         wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
1388                    "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
1389                    flags);
1390         data->recv_version = peer_version = flags & EAP_PEAP_VERSION_MASK;
1391         if (data->force_version >= 0 && peer_version != data->force_version) {
1392                 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1393                            " version (forced=%d peer=%d) - reject",
1394                            data->force_version, peer_version);
1395                 eap_peap_state(data, FAILURE);
1396                 return;
1397         }
1398         if (peer_version < data->peap_version) {
1399                 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1400                            "use version %d",
1401                            peer_version, data->peap_version, peer_version);
1402                 data->peap_version = peer_version;
1403         }
1404         if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
1405                 if (left < 4) {
1406                         wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS "
1407                                    "length");
1408                         eap_peap_state(data, FAILURE);
1409                         return;
1410                 }
1411                 tls_msg_len = WPA_GET_BE32(pos);
1412                 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d",
1413                            tls_msg_len);
1414                 if (data->ssl.tls_in_left == 0) {
1415                         data->ssl.tls_in_total = tls_msg_len;
1416                         data->ssl.tls_in_left = tls_msg_len;
1417                         os_free(data->ssl.tls_in);
1418                         data->ssl.tls_in = NULL;
1419                         data->ssl.tls_in_len = 0;
1420                 }
1421                 pos += 4;
1422                 left -= 4;
1423         }
1424
1425         switch (data->state) {
1426         case PHASE1:
1427                 if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
1428                     0) {
1429                         wpa_printf(MSG_INFO, "EAP-PEAP: TLS processing "
1430                                    "failed");
1431                         eap_peap_state(data, FAILURE);
1432                         break;
1433                 }
1434
1435                 if (data->peap_version >= 2 &&
1436                     tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1437                         if (eap_peapv2_start_phase2(sm, data)) {
1438                                 eap_peap_state(data, FAILURE);
1439                                 break;
1440                         }
1441                 }
1442                 break;
1443         case PHASE2_START:
1444                 eap_peap_state(data, PHASE2_ID);
1445                 eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
1446                 break;
1447         case PHASE1_ID2:
1448         case PHASE2_ID:
1449         case PHASE2_METHOD:
1450         case PHASE2_SOH:
1451         case PHASE2_TLV:
1452                 eap_peap_process_phase2(sm, data, respData, pos, left);
1453                 break;
1454         case SUCCESS_REQ:
1455                 eap_peap_state(data, SUCCESS);
1456                 break;
1457         case FAILURE_REQ:
1458                 eap_peap_state(data, FAILURE);
1459                 break;
1460         default:
1461                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1462                            data->state, __func__);
1463                 break;
1464         }
1465
1466         if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
1467                 wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
1468                            "in TLS processing");
1469                 eap_peap_state(data, FAILURE);
1470         }
1471 }
1472
1473
1474 static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
1475 {
1476         struct eap_peap_data *data = priv;
1477         return data->state == SUCCESS || data->state == FAILURE;
1478 }
1479
1480
1481 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1482 {
1483         struct eap_peap_data *data = priv;
1484         u8 *eapKeyData;
1485
1486         if (data->state != SUCCESS)
1487                 return NULL;
1488
1489         if (data->crypto_binding_used) {
1490                 u8 csk[128];
1491                 /*
1492                  * Note: It looks like Microsoft implementation requires null
1493                  * termination for this label while the one used for deriving
1494                  * IPMK|CMK did not use null termination.
1495                  */
1496                 peap_prfplus(data->peap_version, data->ipmk, 40,
1497                              "Session Key Generating Function",
1498                              (u8 *) "\00", 1, csk, sizeof(csk));
1499                 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1500                 eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1501                 if (eapKeyData) {
1502                         os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1503                         *len = EAP_TLS_KEY_LEN;
1504                         wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1505                                     eapKeyData, EAP_TLS_KEY_LEN);
1506                 } else {
1507                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1508                                    "key");
1509                 }
1510
1511                 return eapKeyData;
1512         }
1513
1514         /* TODO: PEAPv1 - different label in some cases */
1515         eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1516                                                "client EAP encryption",
1517                                                EAP_TLS_KEY_LEN);
1518         if (eapKeyData) {
1519                 *len = EAP_TLS_KEY_LEN;
1520                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1521                             eapKeyData, EAP_TLS_KEY_LEN);
1522         } else {
1523                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1524         }
1525
1526         return eapKeyData;
1527 }
1528
1529
1530 static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1531 {
1532         struct eap_peap_data *data = priv;
1533         return data->state == SUCCESS;
1534 }
1535
1536
1537 int eap_server_peap_register(void)
1538 {
1539         struct eap_method *eap;
1540         int ret;
1541
1542         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1543                                       EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1544         if (eap == NULL)
1545                 return -1;
1546
1547         eap->init = eap_peap_init;
1548         eap->reset = eap_peap_reset;
1549         eap->buildReq = eap_peap_buildReq;
1550         eap->check = eap_peap_check;
1551         eap->process = eap_peap_process;
1552         eap->isDone = eap_peap_isDone;
1553         eap->getKey = eap_peap_getKey;
1554         eap->isSuccess = eap_peap_isSuccess;
1555
1556         ret = eap_server_method_register(eap);
1557         if (ret)
1558                 eap_server_method_free(eap);
1559         return ret;
1560 }