static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, struct eap_peap_data *data, const u8 *crypto_tlv, size_t crypto_tlv_len) { u8 buf[61], mac[SHA1_MAC_LEN]; const u8 *pos; if (eap_peap_derive_cmk(sm, data) < 0) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK"); return -1; } if (crypto_tlv_len != 4 + 56) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " "length %d", (int) crypto_tlv_len); return -1; } pos = crypto_tlv; pos += 4; /* TLV header */ if (pos[1] != data->peap_version) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " "mismatch (was %d; expected %d)", pos[1], data->peap_version); return -1; } if (pos[3] != 0) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " "SubType %d", pos[3]); return -1; } pos += 4; os_memcpy(data->binding_nonce, pos, 32); pos += 32; /* Nonce */ /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ os_memcpy(buf, crypto_tlv, 60); os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ buf[60] = EAP_TYPE_PEAP; wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data", buf, sizeof(buf)); hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " "cryptobinding TLV"); wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC", pos, SHA1_MAC_LEN); wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC", mac, SHA1_MAC_LEN); return -1; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); return 0; }
static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, struct eap_peap_data *data, u8 id) { struct wpabuf *buf, *encr_req; size_t mlen; mlen = 6; /* Result TLV */ if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && data->crypto_binding != NO_BINDING) { mlen += 60; /* Cryptobinding TLV */ #ifdef EAP_SERVER_TNC if (data->soh_response) mlen += wpabuf_len(data->soh_response); #endif /* EAP_SERVER_TNC */ } buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen, EAP_CODE_REQUEST, id); if (buf == NULL) return NULL; wpabuf_put_u8(buf, 0x80); /* Mandatory */ wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); /* Length */ wpabuf_put_be16(buf, 2); /* Status */ wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && data->crypto_binding != NO_BINDING) { u8 *mac; u8 eap_type = EAP_TYPE_PEAP; const u8 *addr[2]; size_t len[2]; u16 tlv_type; #ifdef EAP_SERVER_TNC if (data->soh_response) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " "Response TLV"); wpabuf_put_buf(buf, data->soh_response); wpabuf_free(data->soh_response); data->soh_response = NULL; } #endif /* EAP_SERVER_TNC */ if (eap_peap_derive_cmk(sm, data) < 0 || random_get_bytes(data->binding_nonce, 32)) { wpabuf_free(buf); return NULL; } /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ addr[0] = wpabuf_put(buf, 0); len[0] = 60; addr[1] = &eap_type; len[1] = 1; tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; wpabuf_put_be16(buf, tlv_type); wpabuf_put_be16(buf, 56); wpabuf_put_u8(buf, 0); /* Reserved */ wpabuf_put_u8(buf, data->peap_version); /* Version */ wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ mac = wpabuf_put(buf, 20); /* Compound_MAC */ wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20); wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", addr[0], len[0]); wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", addr[1], len[1]); hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); data->crypto_binding_sent = 1; } wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", buf); encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); wpabuf_free(buf); return encr_req; }