Пример #1
0
static void eap_eke_reset(struct eap_sm *sm, void *priv)
{
	struct eap_eke_data *data = priv;
	eap_eke_session_clean(&data->sess);
	os_free(data->peerid);
	wpabuf_free(data->msgs);
	bin_clear_free(data, sizeof(*data));
}
Пример #2
0
static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data,
					  struct eap_method_ret *ret,
					  u8 id, u32 failure_code)
{
	struct wpabuf *resp;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x",
		   failure_code);

	resp = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE);
	if (resp)
		wpabuf_put_be32(resp, failure_code);

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

	eap_eke_state(data, FAILURE);
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_FAIL;
	ret->allowNotifications = FALSE;

	return resp;
}
Пример #3
0
static void eap_eke_process_confirm(struct eap_sm *sm,
				    struct eap_eke_data *data,
				    const struct wpabuf *respData,
				    const u8 *payload, size_t payloadlen)
{
	size_t decrypt_len;
	u8 nonce[EAP_EKE_MAX_NONCE_LEN];
	u8 auth_p[EAP_EKE_MAX_HASH_LEN];

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

	if (data->state != CONFIRM) {
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

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

	if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	decrypt_len = sizeof(nonce);
	if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len,
				 nonce, &decrypt_len) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}
	if (decrypt_len < (size_t) data->sess.nonce_len) {
		wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S",
			nonce, data->sess.nonce_len);
	if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}

	if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len);
	if (os_memcmp_const(auth_p, payload + data->sess.pnonce_len,
			    data->sess.prf_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match");
		eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL);
		return;
	}

	if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_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");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}

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

	eap_eke_state(data, SUCCESS);
}
Пример #4
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;
}