static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, struct eap_method_ret *ret) { wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; eap_tls_free_key(data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, "client EAP encryption", EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", data->key_data, EAP_TLS_KEY_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); } else { wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); } os_free(data->session_id); data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_TLS, &data->id_len); if (data->session_id) { wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", data->session_id, data->id_len); } else { wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); } }
static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { const struct eap_hdr *req; size_t left; int res; u8 flags, id; struct wpabuf *resp; const u8 *pos; struct eap_peap_data *data = priv; struct wpabuf msg; pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, reqData, &left, &flags); if (pos == NULL) return NULL; req = wpabuf_head(reqData); id = req->identifier; if (flags & EAP_TLS_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " "ver=%d)", flags & EAP_TLS_VERSION_MASK, data->peap_version); if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version) data->peap_version = flags & EAP_TLS_VERSION_MASK; if (data->force_peap_version >= 0 && data->force_peap_version != data->peap_version) { wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " "forced PEAP version %d", data->force_peap_version); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", data->peap_version); left = 0; /* make sure that this frame is empty, even though it * should always be, anyway */ } wpabuf_set(&msg, pos, left); resp = NULL; if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && !data->resuming) { res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } else { if (sm->waiting_ext_cert_check && data->pending_resp) { struct eap_peer_config *config = eap_get_config(sm); if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) { wpa_printf(MSG_DEBUG, "EAP-PEAP: External certificate check succeeded - continue handshake"); resp = data->pending_resp; data->pending_resp = NULL; sm->waiting_ext_cert_check = 0; return resp; } if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { wpa_printf(MSG_DEBUG, "EAP-PEAP: External certificate check failed - force authentication failure"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; sm->waiting_ext_cert_check = 0; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Continuing to wait external server certificate validation"); return NULL; } res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, data->peap_version, id, &msg, &resp); if (res < 0) { wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS processing failed"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return resp; } if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Waiting external server certificate validation"); wpabuf_free(data->pending_resp); data->pending_resp = resp; return NULL; } if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { char *label; wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2"); eap_peap_free_key(data); /* draft-josefsson-ppext-eap-tls-eap-05.txt * specifies that PEAPv1 would use "client PEAP * encryption" as the label. However, most existing * PEAPv1 implementations seem to be using the old * label, "client EAP encryption", instead. Use the old * label by default, but allow it to be configured with * phase1 parameter peaplabel=1. */ if (data->force_new_label) label = "client PEAP encryption"; else label = "client EAP encryption"; wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " "key derivation", label); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, EAP_TLS_KEY_LEN); if (data->key_data) { wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Derived key", data->key_data, EAP_TLS_KEY_LEN); } else { wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " "derive key"); } os_free(data->session_id); data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP, &data->id_len); if (data->session_id) { wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived Session-Id", data->session_id, data->id_len); } else { wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to " "derive Session-Id"); } if (sm->workaround && data->resuming) { /* * At least few RADIUS servers (Aegis v1.1.6; * but not v1.1.4; and Cisco ACS) seem to be * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco * ACS) session resumption with outer * EAP-Success. This does not seem to follow * draft-josefsson-pppext-eap-tls-eap-05.txt * section 4.2, so only allow this if EAP * workarounds are enabled. */ wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " "allow outer EAP-Success to " "terminate PEAP resumption"); ret->decision = DECISION_COND_SUCC; data->phase2_success = 1; } data->resuming = 0; } if (res == 2) { /* * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } } if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } if (res == 1) { wpabuf_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, data->peap_version); } return resp; }
static struct wpabuf * eap_fast_process_crypto_binding( struct eap_sm *sm, struct eap_fast_data *data, struct eap_method_ret *ret, struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len) { struct wpabuf *resp; u8 *pos; u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN]; int res; size_t len; if (eap_fast_validate_crypto_binding(_bind) < 0) return NULL; if (eap_fast_get_cmk(sm, data, cmk) < 0) return NULL; /* Validate received Compound MAC */ os_memcpy(cmac, _bind->compound_mac, sizeof(cmac)); os_memset(_bind->compound_mac, 0, sizeof(cmac)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound " "MAC calculation", (u8 *) _bind, bind_len); hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) _bind, bind_len, _bind->compound_mac); res = os_memcmp_const(cmac, _bind->compound_mac, sizeof(cmac)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC", cmac, sizeof(cmac)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC", _bind->compound_mac, sizeof(cmac)); if (res != 0) { wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match"); os_memcpy(_bind->compound_mac, cmac, sizeof(cmac)); return NULL; } /* * Compound MAC was valid, so authentication succeeded. Reply with * crypto binding to allow server to complete authentication. */ len = sizeof(struct eap_tlv_crypto_binding_tlv); resp = wpabuf_alloc(len); if (resp == NULL) return NULL; if (!data->anon_provisioning && data->phase2_success && eap_fast_derive_msk(data) < 0) { wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; data->phase2_success = 0; wpabuf_free(resp); return NULL; } if (!data->anon_provisioning && data->phase2_success) { os_free(data->session_id); data->session_id = eap_peer_tls_derive_session_id( sm, &data->ssl, EAP_TYPE_FAST, &data->id_len); if (data->session_id) { wpa_hexdump(MSG_DEBUG, "EAP-FAST: Derived Session-Id", data->session_id, data->id_len); } else { wpa_printf(MSG_ERROR, "EAP-FAST: Failed to derive " "Session-Id"); wpabuf_free(resp); return NULL; } } pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv)); eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *) pos, _bind, cmk); return resp; }