1143351Sharti/*
2143351Sharti * EAP-IKEv2 common routines
3143351Sharti * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
4143351Sharti *
5143351Sharti * This software may be distributed under the terms of the BSD license.
6143351Sharti * See README for more details.
7143351Sharti */
8143351Sharti
9208291Suqs#include "includes.h"
10143351Sharti
11143351Sharti#include "common.h"
12143351Sharti#include "eap_defs.h"
13143351Sharti#include "eap_common.h"
14143351Sharti#include "ikev2_common.h"
15143351Sharti#include "eap_ikev2_common.h"
16143351Sharti
17143351Sharti
18143351Shartiint eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
19143351Sharti			    const u8 *i_nonce, size_t i_nonce_len,
20143351Sharti			    const u8 *r_nonce, size_t r_nonce_len,
21143351Sharti			    u8 *keymat)
22143351Sharti{
23143351Sharti	u8 *nonces;
24143351Sharti	size_t nlen;
25143351Sharti
26143351Sharti	/* KEYMAT = prf+(SK_d, Ni | Nr) */
27143351Sharti	if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
28143351Sharti		return -1;
29143351Sharti
30143351Sharti	nlen = i_nonce_len + r_nonce_len;
31143351Sharti	nonces = os_malloc(nlen);
32143351Sharti	if (nonces == NULL)
33143351Sharti		return -1;
34143351Sharti	os_memcpy(nonces, i_nonce, i_nonce_len);
35147432Sru	os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
36147432Sru
37143351Sharti	if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
38143351Sharti			   keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
39147432Sru		os_free(nonces);
40143351Sharti		return -1;
41147432Sru	}
42147432Sru	os_free(nonces);
43147432Sru
44147432Sru	wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
45147432Sru			keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
46147432Sru
47147432Sru	return 0;
48147432Sru}
49147432Sru
50148066Shrs
51143351Shartistruct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code)
52143351Sharti{
53143351Sharti	struct wpabuf *msg;
54147432Sru
55147432Sru	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
56143351Sharti	if (msg == NULL) {
57143351Sharti		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
58147432Sru			   "for fragment ack");
59143351Sharti		return NULL;
60143351Sharti	}
61143351Sharti
62143351Sharti	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
63143351Sharti
64143351Sharti	return msg;
65147432Sru}
66143351Sharti
67147432Sru
68143351Shartiint eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
69147432Sru			   int initiator, const struct wpabuf *msg,
70143351Sharti			   const u8 *pos, const u8 *end)
71143351Sharti{
72143351Sharti	const struct ikev2_integ_alg *integ;
73147432Sru	size_t icv_len;
74143351Sharti	u8 icv[IKEV2_MAX_HASH_LEN];
75143351Sharti	const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
76147432Sru
77147432Sru	integ = ikev2_get_integ(integ_alg);
78147432Sru	if (integ == NULL) {
79147432Sru		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
80143351Sharti			   "transform / cannot validate ICV");
81143351Sharti		return -1;
82143351Sharti	}
83143351Sharti	icv_len = integ->hash_len;
84143351Sharti
85143351Sharti	if (end - pos < (int) icv_len) {
86143351Sharti		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
87143351Sharti			   "message for Integrity Checksum Data");
88143351Sharti		return -1;
89147432Sru	}
90143351Sharti
91143351Sharti	if (SK_a == NULL) {
92147432Sru		wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
93143351Sharti		return -1;
94143351Sharti	}
95143351Sharti
96147432Sru	if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
97143351Sharti			     wpabuf_head(msg),
98147432Sru			     wpabuf_len(msg) - icv_len, icv) < 0) {
99147432Sru		wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
100143351Sharti		return -1;
101143351Sharti	}
102143351Sharti
103147432Sru	if (os_memcmp_const(icv, end - icv_len, icv_len) != 0) {
104143351Sharti		wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
105143351Sharti		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
106143351Sharti			    icv, icv_len);
107147432Sru		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
108147432Sru			    end - icv_len, icv_len);
109147432Sru		return -1;
110143351Sharti	}
111143351Sharti
112143351Sharti	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
113231564Sed		   "the received message");
114143351Sharti
115143351Sharti	return icv_len;
116143351Sharti}
117143351Sharti