/*
 * EAP-IKEv2 common routines
 * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"

#include "common.h"
#include "eap_defs.h"
#include "eap_common.h"
#include "ikev2_common.h"
#include "eap_ikev2_common.h"


int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
			    const u8 *i_nonce, size_t i_nonce_len,
			    const u8 *r_nonce, size_t r_nonce_len,
			    u8 *keymat)
{
	u8 *nonces;
	size_t nlen;

	/* KEYMAT = prf+(SK_d, Ni | Nr) */
	if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
		return -1;

	nlen = i_nonce_len + r_nonce_len;
	nonces = os_malloc(nlen);
	if (nonces == NULL)
		return -1;
	os_memcpy(nonces, i_nonce, i_nonce_len);
	os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);

	if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
			   keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
		os_free(nonces);
		return -1;
	}
	os_free(nonces);

	wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
			keymat, EAP_MSK_LEN + EAP_EMSK_LEN);

	return 0;
}


struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code)
{
	struct wpabuf *msg;

#ifdef CCNS_PL
	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id);
	if (msg == NULL) {
		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
			   "for fragment ack");
		return NULL;
	}
	wpabuf_put_u8(msg, 0); /* Flags */
#else /* CCNS_PL */
	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
	if (msg == NULL) {
		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
			   "for fragment ack");
		return NULL;
	}
#endif /* CCNS_PL */

	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");

	return msg;
}


int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
			   int initiator, const struct wpabuf *msg,
			   const u8 *pos, const u8 *end)
{
	const struct ikev2_integ_alg *integ;
	size_t icv_len;
	u8 icv[IKEV2_MAX_HASH_LEN];
	const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;

	integ = ikev2_get_integ(integ_alg);
	if (integ == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
			   "transform / cannot validate ICV");
		return -1;
	}
	icv_len = integ->hash_len;

	if (end - pos < (int) icv_len) {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
			   "message for Integrity Checksum Data");
		return -1;
	}

	if (SK_a == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
		return -1;
	}

	if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
			     wpabuf_head(msg),
			     wpabuf_len(msg) - icv_len, icv) < 0) {
		wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
		return -1;
	}

	if (os_memcmp(icv, end - icv_len, icv_len) != 0) {
		wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
			    icv, icv_len);
		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
			    end - icv_len, icv_len);
		return -1;
	}

	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
		   "the received message");

	return icv_len;
}
