$search
00001 /* 00002 * EAP-IKEv2 common routines 00003 * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eap_defs.h" 00019 #include "eap_common.h" 00020 #include "ikev2_common.h" 00021 #include "eap_ikev2_common.h" 00022 00023 00024 int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys, 00025 const u8 *i_nonce, size_t i_nonce_len, 00026 const u8 *r_nonce, size_t r_nonce_len, 00027 u8 *keymat) 00028 { 00029 u8 *nonces; 00030 size_t nlen; 00031 00032 /* KEYMAT = prf+(SK_d, Ni | Nr) */ 00033 if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL) 00034 return -1; 00035 00036 nlen = i_nonce_len + r_nonce_len; 00037 nonces = os_malloc(nlen); 00038 if (nonces == NULL) 00039 return -1; 00040 os_memcpy(nonces, i_nonce, i_nonce_len); 00041 os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len); 00042 00043 if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen, 00044 keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) { 00045 os_free(nonces); 00046 return -1; 00047 } 00048 os_free(nonces); 00049 00050 wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT", 00051 keymat, EAP_MSK_LEN + EAP_EMSK_LEN); 00052 00053 return 0; 00054 } 00055 00056 00057 struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code) 00058 { 00059 struct wpabuf *msg; 00060 00061 #ifdef CCNS_PL 00062 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id); 00063 if (msg == NULL) { 00064 wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " 00065 "for fragment ack"); 00066 return NULL; 00067 } 00068 wpabuf_put_u8(msg, 0); /* Flags */ 00069 #else /* CCNS_PL */ 00070 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id); 00071 if (msg == NULL) { 00072 wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " 00073 "for fragment ack"); 00074 return NULL; 00075 } 00076 #endif /* CCNS_PL */ 00077 00078 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack"); 00079 00080 return msg; 00081 } 00082 00083 00084 int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys, 00085 int initiator, const struct wpabuf *msg, 00086 const u8 *pos, const u8 *end) 00087 { 00088 const struct ikev2_integ_alg *integ; 00089 size_t icv_len; 00090 u8 icv[IKEV2_MAX_HASH_LEN]; 00091 const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; 00092 00093 integ = ikev2_get_integ(integ_alg); 00094 if (integ == NULL) { 00095 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " 00096 "transform / cannot validate ICV"); 00097 return -1; 00098 } 00099 icv_len = integ->hash_len; 00100 00101 if (end - pos < (int) icv_len) { 00102 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the " 00103 "message for Integrity Checksum Data"); 00104 return -1; 00105 } 00106 00107 if (SK_a == NULL) { 00108 wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation"); 00109 return -1; 00110 } 00111 00112 if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len, 00113 wpabuf_head(msg), 00114 wpabuf_len(msg) - icv_len, icv) < 0) { 00115 wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV"); 00116 return -1; 00117 } 00118 00119 if (os_memcmp(icv, end - icv_len, icv_len) != 0) { 00120 wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV"); 00121 wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV", 00122 icv, icv_len); 00123 wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV", 00124 end - icv_len, icv_len); 00125 return -1; 00126 } 00127 00128 wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in " 00129 "the received message"); 00130 00131 return icv_len; 00132 }