c9e6db5d2752ead8daa4d4d85b31b8a8ce7b2edb
[libeap.git] / src / eap_peer / eap_peap.c
1 /*
2  * EAP peer method: 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 "crypto/sha1.h"
19 #include "eap_i.h"
20 #include "eap_tls_common.h"
21 #include "eap_config.h"
22 #include "tls.h"
23 #include "eap_common/eap_tlv_common.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_deinit(struct eap_sm *sm, void *priv);
35
36
37 struct eap_peap_data {
38         struct eap_ssl_data ssl;
39
40         int peap_version, force_peap_version, force_new_label;
41
42         const struct eap_method *phase2_method;
43         void *phase2_priv;
44         int phase2_success;
45         int phase2_eap_success;
46         int phase2_eap_started;
47
48         struct eap_method_type phase2_type;
49         struct eap_method_type *phase2_types;
50         size_t num_phase2_types;
51
52         int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner
53                                  * EAP-Success
54                                  * 1 = reply with tunneled EAP-Success to inner
55                                  * EAP-Success and expect AS to send outer
56                                  * (unencrypted) EAP-Success after this
57                                  * 2 = reply with PEAP/TLS ACK to inner
58                                  * EAP-Success and expect AS to send outer
59                                  * (unencrypted) EAP-Success after this */
60         int resuming; /* starting a resumed session */
61         u8 *key_data;
62
63         struct wpabuf *pending_phase2_req;
64         enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
65         int crypto_binding_used;
66         u8 ipmk[40];
67         u8 cmk[20];
68 };
69
70
71 static int eap_peap_parse_phase1(struct eap_peap_data *data,
72                                  const char *phase1)
73 {
74         const char *pos;
75
76         pos = os_strstr(phase1, "peapver=");
77         if (pos) {
78                 data->force_peap_version = atoi(pos + 8);
79                 data->peap_version = data->force_peap_version;
80                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d",
81                            data->force_peap_version);
82         }
83
84         if (os_strstr(phase1, "peaplabel=1")) {
85                 data->force_new_label = 1;
86                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key "
87                            "derivation");
88         }
89
90         if (os_strstr(phase1, "peap_outer_success=0")) {
91                 data->peap_outer_success = 0;
92                 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on "
93                            "tunneled EAP-Success");
94         } else if (os_strstr(phase1, "peap_outer_success=1")) {
95                 data->peap_outer_success = 1;
96                 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success "
97                            "after receiving tunneled EAP-Success");
98         } else if (os_strstr(phase1, "peap_outer_success=2")) {
99                 data->peap_outer_success = 2;
100                 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after "
101                            "receiving tunneled EAP-Success");
102         }
103
104         if (os_strstr(phase1, "crypto_binding=0")) {
105                 data->crypto_binding = NO_BINDING;
106                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding");
107         } else if (os_strstr(phase1, "crypto_binding=1")) {
108                 data->crypto_binding = OPTIONAL_BINDING;
109                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding");
110         } else if (os_strstr(phase1, "crypto_binding=2")) {
111                 data->crypto_binding = REQUIRE_BINDING;
112                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
113         }
114
115         return 0;
116 }
117
118
119 static void * eap_peap_init(struct eap_sm *sm)
120 {
121         struct eap_peap_data *data;
122         struct eap_peer_config *config = eap_get_config(sm);
123
124         data = os_zalloc(sizeof(*data));
125         if (data == NULL)
126                 return NULL;
127         sm->peap_done = FALSE;
128         data->peap_version = EAP_PEAP_VERSION;
129         data->force_peap_version = -1;
130         data->peap_outer_success = 2;
131         data->crypto_binding = OPTIONAL_BINDING;
132
133         if (config && config->phase1 &&
134             eap_peap_parse_phase1(data, config->phase1) < 0) {
135                 eap_peap_deinit(sm, data);
136                 return NULL;
137         }
138
139         if (eap_peer_select_phase2_methods(config, "auth=",
140                                            &data->phase2_types,
141                                            &data->num_phase2_types) < 0) {
142                 eap_peap_deinit(sm, data);
143                 return NULL;
144         }
145
146         data->phase2_type.vendor = EAP_VENDOR_IETF;
147         data->phase2_type.method = EAP_TYPE_NONE;
148
149         if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
150                 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
151                 eap_peap_deinit(sm, data);
152                 return NULL;
153         }
154
155         return data;
156 }
157
158
159 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
160 {
161         struct eap_peap_data *data = priv;
162         if (data == NULL)
163                 return;
164         if (data->phase2_priv && data->phase2_method)
165                 data->phase2_method->deinit(sm, data->phase2_priv);
166         os_free(data->phase2_types);
167         eap_peer_tls_ssl_deinit(sm, &data->ssl);
168         os_free(data->key_data);
169         wpabuf_free(data->pending_phase2_req);
170         os_free(data);
171 }
172
173
174 /**
175  * eap_tlv_build_nak - Build EAP-TLV NAK message
176  * @id: EAP identifier for the header
177  * @nak_type: TLV type (EAP_TLV_*)
178  * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
179  *
180  * This funtion builds an EAP-TLV NAK message. The caller is responsible for
181  * freeing the returned buffer.
182  */
183 static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
184 {
185         struct wpabuf *msg;
186
187         msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
188                             EAP_CODE_RESPONSE, id);
189         if (msg == NULL)
190                 return NULL;
191
192         wpabuf_put_u8(msg, 0x80); /* Mandatory */
193         wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
194         wpabuf_put_be16(msg, 6); /* Length */
195         wpabuf_put_be32(msg, 0); /* Vendor-Id */
196         wpabuf_put_be16(msg, nak_type); /* NAK-Type */
197
198         return msg;
199 }
200
201
202 static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
203                             u8 *isk, size_t isk_len)
204 {
205         u8 *key;
206         size_t key_len;
207
208         os_memset(isk, 0, isk_len);
209         if (data->phase2_method == NULL || data->phase2_priv == NULL ||
210             data->phase2_method->isKeyAvailable == NULL ||
211             data->phase2_method->getKey == NULL)
212                 return 0;
213
214         if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) ||
215             (key = data->phase2_method->getKey(sm, data->phase2_priv,
216                                                &key_len)) == NULL) {
217                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material "
218                            "from Phase 2");
219                 return -1;
220         }
221
222         if (key_len == 32 &&
223             data->phase2_method->vendor == EAP_VENDOR_IETF &&
224             data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
225                 /*
226                  * Microsoft uses reverse order for MS-MPPE keys in
227                  * EAP-PEAP when compared to EAP-FAST derivation of
228                  * ISK. Swap the keys here to get the correct ISK for
229                  * EAP-PEAPv0 cryptobinding.
230                  */
231                 u8 tmp[16];
232                 os_memcpy(tmp, key, 16);
233                 os_memcpy(key, key + 16, 16);
234                 os_memcpy(key + 16, tmp, 16);
235         }
236
237         if (key_len > isk_len)
238                 key_len = isk_len;
239         os_memcpy(isk, key, key_len);
240         os_free(key);
241
242         return 0;
243 }
244
245
246 void peap_prfplus(int version, const u8 *key, size_t key_len,
247                   const char *label, const u8 *seed, size_t seed_len,
248                   u8 *buf, size_t buf_len)
249 {
250         unsigned char counter = 0;
251         size_t pos, plen;
252         u8 hash[SHA1_MAC_LEN];
253         size_t label_len = os_strlen(label);
254         u8 extra[2];
255         const unsigned char *addr[5];
256         size_t len[5];
257
258         addr[0] = hash;
259         len[0] = 0;
260         addr[1] = (unsigned char *) label;
261         len[1] = label_len;
262         addr[2] = seed;
263         len[2] = seed_len;
264
265         if (version == 0) {
266                 /*
267                  * PRF+(K, S, LEN) = T1 | T2 | ... | Tn
268                  * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00)
269                  * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00)
270                  * ...
271                  * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00)
272                  */
273
274                 extra[0] = 0;
275                 extra[1] = 0;
276
277                 addr[3] = &counter;
278                 len[3] = 1;
279                 addr[4] = extra;
280                 len[4] = 2;
281         } else {
282                 /*
283                  * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where:
284                  * T1 = HMAC-SHA1(K, S | LEN | 0x01)
285                  * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02)
286                  * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03)
287                  * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04)
288                  *   ...
289                  */
290
291                 extra[0] = buf_len & 0xff;
292
293                 addr[3] = extra;
294                 len[3] = 1;
295                 addr[4] = &counter;
296                 len[4] = 1;
297         }
298
299         pos = 0;
300         while (pos < buf_len) {
301                 counter++;
302                 plen = buf_len - pos;
303                 hmac_sha1_vector(key, key_len, 5, addr, len, hash);
304                 if (plen >= SHA1_MAC_LEN) {
305                         os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
306                         pos += SHA1_MAC_LEN;
307                 } else {
308                         os_memcpy(&buf[pos], hash, plen);
309                         break;
310                 }
311                 len[0] = SHA1_MAC_LEN;
312         }
313 }
314
315
316 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
317 {
318         u8 *tk;
319         u8 isk[32], imck[60];
320
321         /*
322          * Tunnel key (TK) is the first 60 octets of the key generated by
323          * phase 1 of PEAP (based on TLS).
324          */
325         tk = data->key_data;
326         if (tk == NULL)
327                 return -1;
328         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
329
330         if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0)
331                 return -1;
332         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
333
334         /*
335          * IPMK Seed = "Inner Methods Compound Keys" | ISK
336          * TempKey = First 40 octets of TK
337          * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
338          * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
339          * in the end of the label just before ISK; is that just a typo?)
340          */
341         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
342         peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
343                      isk, sizeof(isk), imck, sizeof(imck));
344         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
345                         imck, sizeof(imck));
346
347         /* TODO: fast-connect: IPMK|CMK = TK */
348         os_memcpy(data->ipmk, imck, 40);
349         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
350         os_memcpy(data->cmk, imck + 40, 20);
351         wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
352
353         return 0;
354 }
355
356
357 static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
358                                      struct eap_peap_data *data,
359                                      struct wpabuf *buf)
360 {
361         u8 *mac;
362         u8 eap_type = EAP_TYPE_PEAP;
363         const u8 *addr[2];
364         size_t len[2];
365         u16 tlv_type;
366         u8 binding_nonce[32];
367
368         /* FIX: should binding_nonce be copied from request? */
369         if (os_get_random(binding_nonce, 32))
370                 return -1;
371
372         /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
373         addr[0] = wpabuf_put(buf, 0);
374         len[0] = 60;
375         addr[1] = &eap_type;
376         len[1] = 1;
377
378         tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
379         if (data->peap_version >= 2)
380                 tlv_type |= EAP_TLV_TYPE_MANDATORY;
381         wpabuf_put_be16(buf, tlv_type);
382         wpabuf_put_be16(buf, 56);
383
384         wpabuf_put_u8(buf, 0); /* Reserved */
385         wpabuf_put_u8(buf, data->peap_version); /* Version */
386         wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */
387         wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */
388         wpabuf_put_data(buf, binding_nonce, 32); /* Nonce */
389         mac = wpabuf_put(buf, 20); /* Compound_MAC */
390         wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
391         wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
392                     addr[0], len[0]);
393         wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
394                     addr[1], len[1]);
395         hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
396         wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
397         data->crypto_binding_used = 1;
398
399         return 0;
400 }
401
402
403 /**
404  * eap_tlv_build_result - Build EAP-TLV Result message
405  * @id: EAP identifier for the header
406  * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
407  * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
408  *
409  * This funtion builds an EAP-TLV Result message. The caller is responsible for
410  * freeing the returned buffer.
411  */
412 static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
413                                             struct eap_peap_data *data,
414                                             int crypto_tlv_used,
415                                             int id, u16 status)
416 {
417         struct wpabuf *msg;
418         size_t len;
419
420         if (data->crypto_binding == NO_BINDING)
421                 crypto_tlv_used = 0;
422
423         len = 6;
424         if (crypto_tlv_used)
425                 len += 60; /* Cryptobinding TLV */
426         msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
427                             EAP_CODE_RESPONSE, id);
428         if (msg == NULL)
429                 return NULL;
430
431         wpabuf_put_u8(msg, 0x80); /* Mandatory */
432         wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV);
433         wpabuf_put_be16(msg, 2); /* Length */
434         wpabuf_put_be16(msg, status); /* Status */
435
436         if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
437                 wpabuf_free(msg);
438                 return NULL;
439         }
440
441         return msg;
442 }
443
444
445 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
446                                           struct eap_peap_data *data,
447                                           const u8 *crypto_tlv,
448                                           size_t crypto_tlv_len)
449 {
450         u8 buf[61], mac[SHA1_MAC_LEN];
451         const u8 *pos;
452
453         if (eap_peap_derive_cmk(sm, data) < 0) {
454                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK");
455                 return -1;
456         }
457
458         if (crypto_tlv_len != 4 + 56) {
459                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
460                            "length %d", (int) crypto_tlv_len);
461                 return -1;
462         }
463
464         pos = crypto_tlv;
465         pos += 4; /* TLV header */
466         if (pos[1] != data->peap_version) {
467                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
468                            "mismatch (was %d; expected %d)",
469                            pos[1], data->peap_version);
470                 return -1;
471         }
472
473         if (pos[3] != 0) {
474                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
475                            "SubType %d", pos[3]);
476                 return -1;
477         }
478         pos += 4;
479         pos += 32; /* Nonce */
480
481         /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
482         os_memcpy(buf, crypto_tlv, 60);
483         os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
484         buf[60] = EAP_TYPE_PEAP;
485         hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
486
487         if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
488                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
489                            "cryptobinding TLV");
490                 return -1;
491         }
492
493         wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
494
495         return 0;
496 }
497
498
499 /**
500  * eap_tlv_process - Process a received EAP-TLV message and generate a response
501  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
502  * @ret: Return values from EAP request validation and processing
503  * @req: EAP-TLV request to be processed. The caller must have validated that
504  * the buffer is large enough to contain full request (hdr->length bytes) and
505  * that the EAP type is EAP_TYPE_TLV.
506  * @resp: Buffer to return a pointer to the allocated response message. This
507  * field should be initialized to %NULL before the call. The value will be
508  * updated if a response message is generated. The caller is responsible for
509  * freeing the allocated message.
510  * @force_failure: Force negotiation to fail
511  * Returns: 0 on success, -1 on failure
512  */
513 static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
514                            struct eap_method_ret *ret,
515                            const struct wpabuf *req, struct wpabuf **resp,
516                            int force_failure)
517 {
518         size_t left, tlv_len;
519         const u8 *pos;
520         const u8 *result_tlv = NULL, *crypto_tlv = NULL;
521         size_t result_tlv_len = 0, crypto_tlv_len = 0;
522         int tlv_type, mandatory;
523
524         /* Parse TLVs */
525         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left);
526         if (pos == NULL)
527                 return -1;
528         wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
529         while (left >= 4) {
530                 mandatory = !!(pos[0] & 0x80);
531                 tlv_type = WPA_GET_BE16(pos) & 0x3fff;
532                 pos += 2;
533                 tlv_len = WPA_GET_BE16(pos);
534                 pos += 2;
535                 left -= 4;
536                 if (tlv_len > left) {
537                         wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
538                                    "(tlv_len=%lu left=%lu)",
539                                    (unsigned long) tlv_len,
540                                    (unsigned long) left);
541                         return -1;
542                 }
543                 switch (tlv_type) {
544                 case EAP_TLV_RESULT_TLV:
545                         result_tlv = pos;
546                         result_tlv_len = tlv_len;
547                         break;
548                 case EAP_TLV_CRYPTO_BINDING_TLV:
549                         crypto_tlv = pos;
550                         crypto_tlv_len = tlv_len;
551                         break;
552                 default:
553                         wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
554                                    "%d%s", tlv_type,
555                                    mandatory ? " (mandatory)" : "");
556                         if (mandatory) {
557                                 /* NAK TLV and ignore all TLVs in this packet.
558                                  */
559                                 *resp = eap_tlv_build_nak(eap_get_id(req),
560                                                           tlv_type);
561                                 return *resp == NULL ? -1 : 0;
562                         }
563                         /* Ignore this TLV, but process other TLVs */
564                         break;
565                 }
566
567                 pos += tlv_len;
568                 left -= tlv_len;
569         }
570         if (left) {
571                 wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
572                            "Request (left=%lu)", (unsigned long) left);
573                 return -1;
574         }
575
576         /* Process supported TLVs */
577         if (crypto_tlv && data->crypto_binding != NO_BINDING) {
578                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
579                             crypto_tlv, crypto_tlv_len);
580                 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
581                                                    crypto_tlv_len + 4) < 0) {
582                         if (result_tlv == NULL)
583                                 return -1;
584                         force_failure = 1;
585                 }
586         } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) {
587                 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
588                 return -1;
589         }
590
591         if (result_tlv) {
592                 int status, resp_status;
593                 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
594                             result_tlv, result_tlv_len);
595                 if (result_tlv_len < 2) {
596                         wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
597                                    "(len=%lu)",
598                                    (unsigned long) result_tlv_len);
599                         return -1;
600                 }
601                 status = WPA_GET_BE16(result_tlv);
602                 if (status == EAP_TLV_RESULT_SUCCESS) {
603                         wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
604                                    "- EAP-TLV/Phase2 Completed");
605                         if (force_failure) {
606                                 wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
607                                            " - force failed Phase 2");
608                                 resp_status = EAP_TLV_RESULT_FAILURE;
609                                 ret->decision = DECISION_FAIL;
610                         } else {
611                                 resp_status = EAP_TLV_RESULT_SUCCESS;
612                                 ret->decision = DECISION_UNCOND_SUCC;
613                         }
614                 } else if (status == EAP_TLV_RESULT_FAILURE) {
615                         wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
616                         resp_status = EAP_TLV_RESULT_FAILURE;
617                         ret->decision = DECISION_FAIL;
618                 } else {
619                         wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
620                                    "Status %d", status);
621                         resp_status = EAP_TLV_RESULT_FAILURE;
622                         ret->decision = DECISION_FAIL;
623                 }
624                 ret->methodState = METHOD_DONE;
625
626                 *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL,
627                                              eap_get_id(req), resp_status);
628         }
629
630         return 0;
631 }
632
633
634 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
635 {
636         struct wpabuf *e;
637         struct eap_tlv_hdr *tlv;
638
639         if (buf == NULL)
640                 return NULL;
641
642         /* Encapsulate EAP packet in EAP-Payload TLV */
643         wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
644         e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
645         if (e == NULL) {
646                 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
647                            "for TLV encapsulation");
648                 wpabuf_free(buf);
649                 return NULL;
650         }
651         tlv = wpabuf_put(e, sizeof(*tlv));
652         tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
653                                      EAP_TLV_EAP_PAYLOAD_TLV);
654         tlv->length = host_to_be16(wpabuf_len(buf));
655         wpabuf_put_buf(e, buf);
656         wpabuf_free(buf);
657         return e;
658 }
659
660
661 static int eap_peap_phase2_request(struct eap_sm *sm,
662                                    struct eap_peap_data *data,
663                                    struct eap_method_ret *ret,
664                                    struct wpabuf *req,
665                                    struct wpabuf **resp)
666 {
667         struct eap_hdr *hdr = wpabuf_mhead(req);
668         size_t len = be_to_host16(hdr->length);
669         u8 *pos;
670         struct eap_method_ret iret;
671         struct eap_peer_config *config = eap_get_config(sm);
672
673         if (len <= sizeof(struct eap_hdr)) {
674                 wpa_printf(MSG_INFO, "EAP-PEAP: too short "
675                            "Phase 2 request (len=%lu)", (unsigned long) len);
676                 return -1;
677         }
678         pos = (u8 *) (hdr + 1);
679         wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
680         switch (*pos) {
681         case EAP_TYPE_IDENTITY:
682                 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
683                 break;
684         case EAP_TYPE_TLV:
685                 os_memset(&iret, 0, sizeof(iret));
686                 if (eap_tlv_process(sm, data, &iret, req, resp,
687                                     data->phase2_eap_started &&
688                                     !data->phase2_eap_success)) {
689                         ret->methodState = METHOD_DONE;
690                         ret->decision = DECISION_FAIL;
691                         return -1;
692                 }
693                 if (iret.methodState == METHOD_DONE ||
694                     iret.methodState == METHOD_MAY_CONT) {
695                         ret->methodState = iret.methodState;
696                         ret->decision = iret.decision;
697                         data->phase2_success = 1;
698                 }
699                 break;
700         default:
701                 if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
702                     data->phase2_type.method == EAP_TYPE_NONE) {
703                         size_t i;
704                         for (i = 0; i < data->num_phase2_types; i++) {
705                                 if (data->phase2_types[i].vendor !=
706                                     EAP_VENDOR_IETF ||
707                                     data->phase2_types[i].method != *pos)
708                                         continue;
709
710                                 data->phase2_type.vendor =
711                                         data->phase2_types[i].vendor;
712                                 data->phase2_type.method =
713                                         data->phase2_types[i].method;
714                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
715                                            "Phase 2 EAP vendor %d method %d",
716                                            data->phase2_type.vendor,
717                                            data->phase2_type.method);
718                                 break;
719                         }
720                 }
721                 if (*pos != data->phase2_type.method ||
722                     *pos == EAP_TYPE_NONE) {
723                         if (eap_peer_tls_phase2_nak(data->phase2_types,
724                                                     data->num_phase2_types,
725                                                     hdr, resp))
726                                 return -1;
727                         return 0;
728                 }
729
730                 if (data->phase2_priv == NULL) {
731                         data->phase2_method = eap_peer_get_eap_method(
732                                 data->phase2_type.vendor,
733                                 data->phase2_type.method);
734                         if (data->phase2_method) {
735                                 sm->init_phase2 = 1;
736                                 sm->mschapv2_full_key = 1;
737                                 data->phase2_priv =
738                                         data->phase2_method->init(sm);
739                                 sm->init_phase2 = 0;
740                                 sm->mschapv2_full_key = 0;
741                         }
742                 }
743                 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
744                         wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize "
745                                    "Phase 2 EAP method %d", *pos);
746                         ret->methodState = METHOD_DONE;
747                         ret->decision = DECISION_FAIL;
748                         return -1;
749                 }
750                 data->phase2_eap_started = 1;
751                 os_memset(&iret, 0, sizeof(iret));
752                 *resp = data->phase2_method->process(sm, data->phase2_priv,
753                                                      &iret, req);
754                 if ((iret.methodState == METHOD_DONE ||
755                      iret.methodState == METHOD_MAY_CONT) &&
756                     (iret.decision == DECISION_UNCOND_SUCC ||
757                      iret.decision == DECISION_COND_SUCC)) {
758                         data->phase2_eap_success = 1;
759                         data->phase2_success = 1;
760                 }
761                 break;
762         }
763
764         if (*resp == NULL &&
765             (config->pending_req_identity || config->pending_req_password ||
766              config->pending_req_otp || config->pending_req_new_password)) {
767                 wpabuf_free(data->pending_phase2_req);
768                 data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
769         }
770
771         return 0;
772 }
773
774
775 static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
776                             struct eap_method_ret *ret,
777                             const struct eap_hdr *req,
778                             const struct wpabuf *in_data,
779                             struct wpabuf **out_data)
780 {
781         struct wpabuf *in_decrypted = NULL;
782         int res, skip_change = 0;
783         struct eap_hdr *hdr, *rhdr;
784         struct wpabuf *resp = NULL;
785         size_t len;
786
787         wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
788                    " Phase 2", (unsigned long) wpabuf_len(in_data));
789
790         if (data->pending_phase2_req) {
791                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
792                            "skip decryption and use old data");
793                 /* Clear TLS reassembly state. */
794                 eap_peer_tls_reset_input(&data->ssl);
795                 in_decrypted = data->pending_phase2_req;
796                 data->pending_phase2_req = NULL;
797                 skip_change = 1;
798                 goto continue_req;
799         }
800
801         if (wpabuf_len(in_data) == 0 && sm->workaround &&
802             data->phase2_success) {
803                 /*
804                  * Cisco ACS seems to be using TLS ACK to terminate
805                  * EAP-PEAPv0/GTC. Try to reply with TLS ACK.
806                  */
807                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
808                            "expected data - acknowledge with TLS ACK since "
809                            "Phase 2 has been completed");
810                 ret->decision = DECISION_COND_SUCC;
811                 ret->methodState = METHOD_DONE;
812                 return 1;
813         } else if (wpabuf_len(in_data) == 0) {
814                 /* Received TLS ACK - requesting more fragments */
815                 return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
816                                             data->peap_version,
817                                             req->identifier, NULL, out_data);
818         }
819
820         res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
821         if (res)
822                 return res;
823
824 continue_req:
825         wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
826                         in_decrypted);
827
828         hdr = wpabuf_mhead(in_decrypted);
829         if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST &&
830             be_to_host16(hdr->length) == 5 &&
831             eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) {
832                 /* At least FreeRADIUS seems to send full EAP header with
833                  * EAP Request Identity */
834                 skip_change = 1;
835         }
836         if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST &&
837             eap_get_type(in_decrypted) == EAP_TYPE_TLV) {
838                 skip_change = 1;
839         }
840
841         if (data->peap_version == 0 && !skip_change) {
842                 struct eap_hdr *nhdr;
843                 struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
844                                                    wpabuf_len(in_decrypted));
845                 if (nmsg == NULL) {
846                         wpabuf_free(in_decrypted);
847                         return 0;
848                 }
849                 nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
850                 wpabuf_put_buf(nmsg, in_decrypted);
851                 nhdr->code = req->code;
852                 nhdr->identifier = req->identifier;
853                 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
854                                             wpabuf_len(in_decrypted));
855
856                 wpabuf_free(in_decrypted);
857                 in_decrypted = nmsg;
858         }
859
860         if (data->peap_version >= 2) {
861                 struct eap_tlv_hdr *tlv;
862                 struct wpabuf *nmsg;
863
864                 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
865                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
866                                    "EAP TLV");
867                         wpabuf_free(in_decrypted);
868                         return 0;
869                 }
870                 tlv = wpabuf_mhead(in_decrypted);
871                 if ((be_to_host16(tlv->tlv_type) & 0x3fff) !=
872                     EAP_TLV_EAP_PAYLOAD_TLV) {
873                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
874                         wpabuf_free(in_decrypted);
875                         return 0;
876                 }
877                 if (sizeof(*tlv) + be_to_host16(tlv->length) >
878                     wpabuf_len(in_decrypted)) {
879                         wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
880                                    "length");
881                         wpabuf_free(in_decrypted);
882                         return 0;
883                 }
884                 hdr = (struct eap_hdr *) (tlv + 1);
885                 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
886                         wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
887                                    "EAP packet in EAP TLV");
888                         wpabuf_free(in_decrypted);
889                         return 0;
890                 }
891
892                 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
893                 if (nmsg == NULL) {
894                         wpabuf_free(in_decrypted);
895                         return 0;
896                 }
897
898                 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
899                 wpabuf_free(in_decrypted);
900                 in_decrypted = nmsg;
901         }
902
903         hdr = wpabuf_mhead(in_decrypted);
904         if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {
905                 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
906                            "EAP frame (len=%lu)",
907                            (unsigned long) wpabuf_len(in_decrypted));
908                 wpabuf_free(in_decrypted);
909                 return 0;
910         }
911         len = be_to_host16(hdr->length);
912         if (len > wpabuf_len(in_decrypted)) {
913                 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
914                            "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
915                            (unsigned long) wpabuf_len(in_decrypted),
916                            (unsigned long) len);
917                 wpabuf_free(in_decrypted);
918                 return 0;
919         }
920         if (len < wpabuf_len(in_decrypted)) {
921                 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
922                            "shorter length than full decrypted data "
923                            "(%lu < %lu)",
924                            (unsigned long) len,
925                            (unsigned long) wpabuf_len(in_decrypted));
926         }
927         wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
928                    "identifier=%d length=%lu", hdr->code, hdr->identifier,
929                    (unsigned long) len);
930         switch (hdr->code) {
931         case EAP_CODE_REQUEST:
932                 if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
933                                             &resp)) {
934                         wpabuf_free(in_decrypted);
935                         wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
936                                    "processing failed");
937                         return 0;
938                 }
939                 break;
940         case EAP_CODE_SUCCESS:
941                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
942                 if (data->peap_version == 1) {
943                         /* EAP-Success within TLS tunnel is used to indicate
944                          * shutdown of the TLS channel. The authentication has
945                          * been completed. */
946                         if (data->phase2_eap_started &&
947                             !data->phase2_eap_success) {
948                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
949                                            "Success used to indicate success, "
950                                            "but Phase 2 EAP was not yet "
951                                            "completed successfully");
952                                 ret->methodState = METHOD_DONE;
953                                 ret->decision = DECISION_FAIL;
954                                 wpabuf_free(in_decrypted);
955                                 return 0;
956                         }
957                         wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
958                                    "EAP-Success within TLS tunnel - "
959                                    "authentication completed");
960                         ret->decision = DECISION_UNCOND_SUCC;
961                         ret->methodState = METHOD_DONE;
962                         data->phase2_success = 1;
963                         if (data->peap_outer_success == 2) {
964                                 wpabuf_free(in_decrypted);
965                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
966                                            "to finish authentication");
967                                 return 1;
968                         } else if (data->peap_outer_success == 1) {
969                                 /* Reply with EAP-Success within the TLS
970                                  * channel to complete the authentication. */
971                                 resp = wpabuf_alloc(sizeof(struct eap_hdr));
972                                 if (resp) {
973                                         rhdr = wpabuf_put(resp, sizeof(*rhdr));
974                                         rhdr->code = EAP_CODE_SUCCESS;
975                                         rhdr->identifier = hdr->identifier;
976                                         rhdr->length =
977                                                 host_to_be16(sizeof(*rhdr));
978                                 }
979                         } else {
980                                 /* No EAP-Success expected for Phase 1 (outer,
981                                  * unencrypted auth), so force EAP state
982                                  * machine to SUCCESS state. */
983                                 sm->peap_done = TRUE;
984                         }
985                 } else {
986                         /* FIX: ? */
987                 }
988                 break;
989         case EAP_CODE_FAILURE:
990                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
991                 ret->decision = DECISION_FAIL;
992                 ret->methodState = METHOD_MAY_CONT;
993                 ret->allowNotifications = FALSE;
994                 /* Reply with EAP-Failure within the TLS channel to complete
995                  * failure reporting. */
996                 resp = wpabuf_alloc(sizeof(struct eap_hdr));
997                 if (resp) {
998                         rhdr = wpabuf_put(resp, sizeof(*rhdr));
999                         rhdr->code = EAP_CODE_FAILURE;
1000                         rhdr->identifier = hdr->identifier;
1001                         rhdr->length = host_to_be16(sizeof(*rhdr));
1002                 }
1003                 break;
1004         default:
1005                 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1006                            "Phase 2 EAP header", hdr->code);
1007                 break;
1008         }
1009
1010         wpabuf_free(in_decrypted);
1011
1012         if (resp) {
1013                 int skip_change2 = 0;
1014                 struct wpabuf *rmsg, buf;
1015
1016                 wpa_hexdump_buf_key(MSG_DEBUG,
1017                                     "EAP-PEAP: Encrypting Phase 2 data", resp);
1018                 /* PEAP version changes */
1019                 if (data->peap_version >= 2) {
1020                         resp = eap_peapv2_tlv_eap_payload(resp);
1021                         if (resp == NULL)
1022                                 return -1;
1023                 }
1024                 if (wpabuf_len(resp) >= 5 &&
1025                     wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&
1026                     eap_get_type(resp) == EAP_TYPE_TLV)
1027                         skip_change2 = 1;
1028                 rmsg = resp;
1029                 if (data->peap_version == 0 && !skip_change2) {
1030                         wpabuf_set(&buf, wpabuf_head_u8(resp) +
1031                                    sizeof(struct eap_hdr),
1032                                    wpabuf_len(resp) - sizeof(struct eap_hdr));
1033                         rmsg = &buf;
1034                 }
1035
1036                 if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
1037                                          data->peap_version, req->identifier,
1038                                          rmsg, out_data)) {
1039                         wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
1040                                    "a Phase 2 frame");
1041                 }
1042                 wpabuf_free(resp);
1043         }
1044
1045         return 0;
1046 }
1047
1048
1049 static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
1050                                         struct eap_method_ret *ret,
1051                                         const struct wpabuf *reqData)
1052 {
1053         const struct eap_hdr *req;
1054         size_t left;
1055         int res;
1056         u8 flags, id;
1057         struct wpabuf *resp;
1058         const u8 *pos;
1059         struct eap_peap_data *data = priv;
1060
1061         pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
1062                                         reqData, &left, &flags);
1063         if (pos == NULL)
1064                 return NULL;
1065         req = wpabuf_head(reqData);
1066         id = req->identifier;
1067
1068         if (flags & EAP_TLS_FLAGS_START) {
1069                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
1070                            "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
1071                         data->peap_version);
1072                 if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)
1073                         data->peap_version = flags & EAP_PEAP_VERSION_MASK;
1074                 if (data->force_peap_version >= 0 &&
1075                     data->force_peap_version != data->peap_version) {
1076                         wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
1077                                    "forced PEAP version %d",
1078                                    data->force_peap_version);
1079                         ret->methodState = METHOD_DONE;
1080                         ret->decision = DECISION_FAIL;
1081                         ret->allowNotifications = FALSE;
1082                         return NULL;
1083                 }
1084                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
1085                            data->peap_version);
1086                 left = 0; /* make sure that this frame is empty, even though it
1087                            * should always be, anyway */
1088         }
1089
1090         resp = NULL;
1091         if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1092             !data->resuming) {
1093                 struct wpabuf msg;
1094                 wpabuf_set(&msg, pos, left);
1095                 res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
1096         } else {
1097                 res = eap_peer_tls_process_helper(sm, &data->ssl,
1098                                                   EAP_TYPE_PEAP,
1099                                                   data->peap_version, id, pos,
1100                                                   left, &resp);
1101
1102                 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1103                         char *label;
1104                         wpa_printf(MSG_DEBUG,
1105                                    "EAP-PEAP: TLS done, proceed to Phase 2");
1106                         os_free(data->key_data);
1107                         /* draft-josefsson-ppext-eap-tls-eap-05.txt
1108                          * specifies that PEAPv1 would use "client PEAP
1109                          * encryption" as the label. However, most existing
1110                          * PEAPv1 implementations seem to be using the old
1111                          * label, "client EAP encryption", instead. Use the old
1112                          * label by default, but allow it to be configured with
1113                          * phase1 parameter peaplabel=1. */
1114                         if (data->peap_version > 1 || data->force_new_label)
1115                                 label = "client PEAP encryption";
1116                         else
1117                                 label = "client EAP encryption";
1118                         wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
1119                                    "key derivation", label);
1120                         data->key_data =
1121                                 eap_peer_tls_derive_key(sm, &data->ssl, label,
1122                                                         EAP_TLS_KEY_LEN);
1123                         if (data->key_data) {
1124                                 wpa_hexdump_key(MSG_DEBUG, 
1125                                                 "EAP-PEAP: Derived key",
1126                                                 data->key_data,
1127                                                 EAP_TLS_KEY_LEN);
1128                         } else {
1129                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
1130                                            "derive key");
1131                         }
1132
1133                         if (sm->workaround && data->resuming) {
1134                                 /*
1135                                  * At least few RADIUS servers (Aegis v1.1.6;
1136                                  * but not v1.1.4; and Cisco ACS) seem to be
1137                                  * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco
1138                                  * ACS) session resumption with outer
1139                                  * EAP-Success. This does not seem to follow
1140                                  * draft-josefsson-pppext-eap-tls-eap-05.txt
1141                                  * section 4.2, so only allow this if EAP
1142                                  * workarounds are enabled.
1143                                  */
1144                                 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
1145                                            "allow outer EAP-Success to "
1146                                            "terminate PEAP resumption");
1147                                 ret->decision = DECISION_COND_SUCC;
1148                                 data->phase2_success = 1;
1149                         }
1150
1151                         data->resuming = 0;
1152                 }
1153
1154                 if (res == 2) {
1155                         struct wpabuf msg;
1156                         /*
1157                          * Application data included in the handshake message.
1158                          */
1159                         wpabuf_free(data->pending_phase2_req);
1160                         data->pending_phase2_req = resp;
1161                         resp = NULL;
1162                         wpabuf_set(&msg, pos, left);
1163                         res = eap_peap_decrypt(sm, data, ret, req, &msg,
1164                                                &resp);
1165                 }
1166         }
1167
1168         if (ret->methodState == METHOD_DONE) {
1169                 ret->allowNotifications = FALSE;
1170         }
1171
1172         if (res == 1) {
1173                 wpabuf_free(resp);
1174                 return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
1175                                               data->peap_version);
1176         }
1177
1178         return resp;
1179 }
1180
1181
1182 static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
1183 {
1184         struct eap_peap_data *data = priv;
1185         return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1186                 data->phase2_success;
1187 }
1188
1189
1190 static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
1191 {
1192         struct eap_peap_data *data = priv;
1193         wpabuf_free(data->pending_phase2_req);
1194         data->pending_phase2_req = NULL;
1195         data->crypto_binding_used = 0;
1196 }
1197
1198
1199 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
1200 {
1201         struct eap_peap_data *data = priv;
1202         os_free(data->key_data);
1203         data->key_data = NULL;
1204         if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1205                 os_free(data);
1206                 return NULL;
1207         }
1208         if (data->phase2_priv && data->phase2_method &&
1209             data->phase2_method->init_for_reauth)
1210                 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1211         data->phase2_success = 0;
1212         data->phase2_eap_success = 0;
1213         data->phase2_eap_started = 0;
1214         data->resuming = 1;
1215         sm->peap_done = FALSE;
1216         return priv;
1217 }
1218
1219
1220 static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
1221                                size_t buflen, int verbose)
1222 {
1223         struct eap_peap_data *data = priv;
1224         int len, ret;
1225
1226         len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1227         if (data->phase2_method) {
1228                 ret = os_snprintf(buf + len, buflen - len,
1229                                   "EAP-PEAPv%d Phase2 method=%s\n",
1230                                   data->peap_version,
1231                                   data->phase2_method->name);
1232                 if (ret < 0 || (size_t) ret >= buflen - len)
1233                         return len;
1234                 len += ret;
1235         }
1236         return len;
1237 }
1238
1239
1240 static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
1241 {
1242         struct eap_peap_data *data = priv;
1243         return data->key_data != NULL && data->phase2_success;
1244 }
1245
1246
1247 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1248 {
1249         struct eap_peap_data *data = priv;
1250         u8 *key;
1251
1252         if (data->key_data == NULL || !data->phase2_success)
1253                 return NULL;
1254
1255         key = os_malloc(EAP_TLS_KEY_LEN);
1256         if (key == NULL)
1257                 return NULL;
1258
1259         *len = EAP_TLS_KEY_LEN;
1260
1261         if (data->crypto_binding_used) {
1262                 u8 csk[128];
1263                 /*
1264                  * Note: It looks like Microsoft implementation requires null
1265                  * termination for this label while the one used for deriving
1266                  * IPMK|CMK did not use null termination.
1267                  */
1268                 peap_prfplus(data->peap_version, data->ipmk, 40,
1269                              "Session Key Generating Function",
1270                              (u8 *) "\00", 1, csk, sizeof(csk));
1271                 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1272                 os_memcpy(key, csk, EAP_TLS_KEY_LEN);
1273                 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1274                             key, EAP_TLS_KEY_LEN);
1275         } else
1276                 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
1277
1278         return key;
1279 }
1280
1281
1282 int eap_peer_peap_register(void)
1283 {
1284         struct eap_method *eap;
1285         int ret;
1286
1287         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1288                                     EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1289         if (eap == NULL)
1290                 return -1;
1291
1292         eap->init = eap_peap_init;
1293         eap->deinit = eap_peap_deinit;
1294         eap->process = eap_peap_process;
1295         eap->isKeyAvailable = eap_peap_isKeyAvailable;
1296         eap->getKey = eap_peap_getKey;
1297         eap->get_status = eap_peap_get_status;
1298         eap->has_reauth_data = eap_peap_has_reauth_data;
1299         eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
1300         eap->init_for_reauth = eap_peap_init_for_reauth;
1301
1302         ret = eap_peer_method_register(eap);
1303         if (ret)
1304                 eap_peer_method_free(eap);
1305         return ret;
1306 }