eap_ikev2_common.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-IKEv2 common routines 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ikev2_common.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_ikev2_common.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys, 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *i_nonce, size_t i_nonce_len, 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *r_nonce, size_t r_nonce_len, 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *keymat) 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *nonces; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t nlen; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KEYMAT = prf+(SK_d, Ni | Nr) */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlen = i_nonce_len + r_nonce_len; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonces = os_malloc(nlen); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonces == NULL) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nonces, i_nonce, i_nonce_len); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen, 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) { 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(nonces); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(nonces); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT", 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keymat, EAP_MSK_LEN + EAP_EMSK_LEN); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for fragment ack"); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 0); /* Flags */ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CCNS_PL */ 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for fragment ack"); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack"); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys, 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int initiator, const struct wpabuf *msg, 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t icv_len; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 icv[IKEV2_MAX_HASH_LEN]; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ = ikev2_get_integ(integ_alg); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (integ == NULL) { 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "transform / cannot validate ICV"); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icv_len = integ->hash_len; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) icv_len) { 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the " 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message for Integrity Checksum Data"); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (SK_a == NULL) { 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation"); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len, 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(msg), 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(msg) - icv_len, icv) < 0) { 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV"); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(icv, end - icv_len, icv_len) != 0) { 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV"); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV", 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icv, icv_len); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV", 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end - icv_len, icv_len); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in " 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the received message"); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return icv_len; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 133