00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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);
00069 #else
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
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 }