static struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm,
					     struct eap_eke_data *data, u8 id)
{
	struct wpabuf *msg;
	size_t plen, prot_len;
	u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
	u8 *auth;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm");

	plen = data->sess.pnonce_ps_len + data->sess.prf_len;
	msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM);
	if (msg == NULL) {
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
			data->nonce_s, data->sess.nonce_len);

	os_memcpy(nonces, data->nonce_p, data->sess.nonce_len);
	os_memcpy(nonces + data->sess.nonce_len, data->nonce_s,
		  data->sess.nonce_len);
	prot_len = wpabuf_tailroom(msg);
	if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len,
			 wpabuf_put(msg, 0), &prot_len) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpabuf_put(msg, prot_len);

	if (eap_eke_derive_ka(&data->sess,
			      sm->server_id, sm->server_id_len,
			      data->peerid, data->peerid_len,
			      data->nonce_p, data->nonce_s) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}

	auth = wpabuf_put(msg, data->sess.prf_len);
	if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) {
		wpabuf_free(msg);
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return eap_eke_build_failure(data, id);
	}
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len);

	return msg;
}
Beispiel #2
0
static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data,
					       struct eap_method_ret *ret,
					       const struct wpabuf *reqData,
					       const u8 *payload,
					       size_t payload_len)
{
	struct wpabuf *resp;
	const u8 *pos, *end;
	size_t prot_len;
	u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
	u8 auth_s[EAP_EKE_MAX_HASH_LEN];
	size_t decrypt_len;
	u8 *auth;
	u8 id = eap_get_id(reqData);

	if (data->state != CONFIRM) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)",
			   data->state);
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PROTO_ERROR);
	}

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Confirm/Request");

	pos = payload;
	end = payload + payload_len;

	if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PROTO_ERROR);
	}

	decrypt_len = sizeof(nonces);
	if (eap_eke_decrypt_prot(&data->sess, pos, data->sess.pnonce_ps_len,
				 nonces, &decrypt_len) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_PS");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_AUTHENTICATION_FAIL);
	}
	if (decrypt_len != (size_t) 2 * data->sess.nonce_len) {
		wpa_printf(MSG_INFO, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_AUTHENTICATION_FAIL);
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S",
			nonces, 2 * data->sess.nonce_len);
	if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_AUTHENTICATION_FAIL);
	}

	os_memcpy(data->nonce_s, nonces + data->sess.nonce_len,
		  data->sess.nonce_len);
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
			data->nonce_s, data->sess.nonce_len);

	if (eap_eke_derive_ka(&data->sess, data->serverid, data->serverid_len,
			      data->peerid, data->peerid_len,
			      data->nonce_p, data->nonce_s) < 0) {
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}

	if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth_s) < 0)
	{
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len);
	if (os_memcmp_const(auth_s, pos + data->sess.pnonce_ps_len,
			    data->sess.prf_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_AUTHENTICATION_FAIL);
	}

	wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Confirm/Response");

	resp = eap_eke_build_msg(data, id,
				 data->sess.pnonce_len + data->sess.prf_len,
				 EAP_EKE_CONFIRM);
	if (resp == NULL) {
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}

	prot_len = wpabuf_tailroom(resp);
	if (eap_eke_prot(&data->sess, data->nonce_s, data->sess.nonce_len,
			 wpabuf_put(resp, 0), &prot_len) < 0) {
		wpabuf_free(resp);
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}
	wpabuf_put(resp, prot_len);

	auth = wpabuf_put(resp, data->sess.prf_len);
	if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth) < 0) {
		wpabuf_free(resp);
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth, data->sess.prf_len);

	if (eap_eke_derive_msk(&data->sess, data->serverid, data->serverid_len,
			       data->peerid, data->peerid_len,
			       data->nonce_s, data->nonce_p,
			       data->msk, data->emsk) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK");
		wpabuf_free(resp);
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}

	os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
	eap_eke_session_clean(&data->sess);

	eap_eke_state(data, SUCCESS);
	ret->methodState = METHOD_MAY_CONT;
	ret->decision = DECISION_COND_SUCC;
	ret->allowNotifications = FALSE;

	return resp;
}