xref: /dflybsd-src/contrib/wpa_supplicant/src/eap_common/eap_ikev2_common.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * EAP-IKEv2 common routines
36d49e1aeSJan Lentfer  * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  */
86d49e1aeSJan Lentfer 
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer 
116d49e1aeSJan Lentfer #include "common.h"
126d49e1aeSJan Lentfer #include "eap_defs.h"
136d49e1aeSJan Lentfer #include "eap_common.h"
146d49e1aeSJan Lentfer #include "ikev2_common.h"
156d49e1aeSJan Lentfer #include "eap_ikev2_common.h"
166d49e1aeSJan Lentfer 
176d49e1aeSJan Lentfer 
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)186d49e1aeSJan Lentfer int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys,
196d49e1aeSJan Lentfer 			    const u8 *i_nonce, size_t i_nonce_len,
206d49e1aeSJan Lentfer 			    const u8 *r_nonce, size_t r_nonce_len,
216d49e1aeSJan Lentfer 			    u8 *keymat)
226d49e1aeSJan Lentfer {
236d49e1aeSJan Lentfer 	u8 *nonces;
246d49e1aeSJan Lentfer 	size_t nlen;
256d49e1aeSJan Lentfer 
266d49e1aeSJan Lentfer 	/* KEYMAT = prf+(SK_d, Ni | Nr) */
276d49e1aeSJan Lentfer 	if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL)
286d49e1aeSJan Lentfer 		return -1;
296d49e1aeSJan Lentfer 
306d49e1aeSJan Lentfer 	nlen = i_nonce_len + r_nonce_len;
316d49e1aeSJan Lentfer 	nonces = os_malloc(nlen);
326d49e1aeSJan Lentfer 	if (nonces == NULL)
336d49e1aeSJan Lentfer 		return -1;
346d49e1aeSJan Lentfer 	os_memcpy(nonces, i_nonce, i_nonce_len);
356d49e1aeSJan Lentfer 	os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len);
366d49e1aeSJan Lentfer 
376d49e1aeSJan Lentfer 	if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen,
386d49e1aeSJan Lentfer 			   keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) {
396d49e1aeSJan Lentfer 		os_free(nonces);
406d49e1aeSJan Lentfer 		return -1;
416d49e1aeSJan Lentfer 	}
426d49e1aeSJan Lentfer 	os_free(nonces);
436d49e1aeSJan Lentfer 
446d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT",
456d49e1aeSJan Lentfer 			keymat, EAP_MSK_LEN + EAP_EMSK_LEN);
466d49e1aeSJan Lentfer 
476d49e1aeSJan Lentfer 	return 0;
486d49e1aeSJan Lentfer }
496d49e1aeSJan Lentfer 
506d49e1aeSJan Lentfer 
eap_ikev2_build_frag_ack(u8 id,u8 code)516d49e1aeSJan Lentfer struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code)
526d49e1aeSJan Lentfer {
536d49e1aeSJan Lentfer 	struct wpabuf *msg;
546d49e1aeSJan Lentfer 
556d49e1aeSJan Lentfer 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id);
566d49e1aeSJan Lentfer 	if (msg == NULL) {
576d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory "
586d49e1aeSJan Lentfer 			   "for fragment ack");
596d49e1aeSJan Lentfer 		return NULL;
606d49e1aeSJan Lentfer 	}
616d49e1aeSJan Lentfer 
626d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack");
636d49e1aeSJan Lentfer 
646d49e1aeSJan Lentfer 	return msg;
656d49e1aeSJan Lentfer }
666d49e1aeSJan Lentfer 
676d49e1aeSJan Lentfer 
eap_ikev2_validate_icv(int integ_alg,struct ikev2_keys * keys,int initiator,const struct wpabuf * msg,const u8 * pos,const u8 * end)686d49e1aeSJan Lentfer int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys,
696d49e1aeSJan Lentfer 			   int initiator, const struct wpabuf *msg,
706d49e1aeSJan Lentfer 			   const u8 *pos, const u8 *end)
716d49e1aeSJan Lentfer {
726d49e1aeSJan Lentfer 	const struct ikev2_integ_alg *integ;
736d49e1aeSJan Lentfer 	size_t icv_len;
746d49e1aeSJan Lentfer 	u8 icv[IKEV2_MAX_HASH_LEN];
756d49e1aeSJan Lentfer 	const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar;
766d49e1aeSJan Lentfer 
776d49e1aeSJan Lentfer 	integ = ikev2_get_integ(integ_alg);
786d49e1aeSJan Lentfer 	if (integ == NULL) {
796d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG "
806d49e1aeSJan Lentfer 			   "transform / cannot validate ICV");
816d49e1aeSJan Lentfer 		return -1;
826d49e1aeSJan Lentfer 	}
836d49e1aeSJan Lentfer 	icv_len = integ->hash_len;
846d49e1aeSJan Lentfer 
856d49e1aeSJan Lentfer 	if (end - pos < (int) icv_len) {
866d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the "
876d49e1aeSJan Lentfer 			   "message for Integrity Checksum Data");
886d49e1aeSJan Lentfer 		return -1;
896d49e1aeSJan Lentfer 	}
906d49e1aeSJan Lentfer 
916d49e1aeSJan Lentfer 	if (SK_a == NULL) {
926d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation");
936d49e1aeSJan Lentfer 		return -1;
946d49e1aeSJan Lentfer 	}
956d49e1aeSJan Lentfer 
966d49e1aeSJan Lentfer 	if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len,
976d49e1aeSJan Lentfer 			     wpabuf_head(msg),
986d49e1aeSJan Lentfer 			     wpabuf_len(msg) - icv_len, icv) < 0) {
996d49e1aeSJan Lentfer 		wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV");
1006d49e1aeSJan Lentfer 		return -1;
1016d49e1aeSJan Lentfer 	}
1026d49e1aeSJan Lentfer 
103*a1157835SDaniel Fojt 	if (os_memcmp_const(icv, end - icv_len, icv_len) != 0) {
1046d49e1aeSJan Lentfer 		wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV");
1056d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV",
1066d49e1aeSJan Lentfer 			    icv, icv_len);
1076d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV",
1086d49e1aeSJan Lentfer 			    end - icv_len, icv_len);
1096d49e1aeSJan Lentfer 		return -1;
1106d49e1aeSJan Lentfer 	}
1116d49e1aeSJan Lentfer 
1126d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in "
1136d49e1aeSJan Lentfer 		   "the received message");
1146d49e1aeSJan Lentfer 
1156d49e1aeSJan Lentfer 	return icv_len;
1166d49e1aeSJan Lentfer }
117