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