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