134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt/* 234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * hostapd / EAP-EKE (RFC 6124) server 334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * Copyright (c) 2013, Jouni Malinen <j@w1.fi> 434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * 534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * See README for more details. 734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "includes.h" 1034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 1134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "common.h" 1234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "crypto/random.h" 1334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "eap_server/eap_i.h" 1434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "eap_common/eap_eke_common.h" 1534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 1634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 1734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstruct eap_eke_data { 1834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt enum { 1934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt IDENTITY, COMMIT, CONFIRM, FAILURE_REPORT, SUCCESS, FAILURE 2034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } state; 2134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 msk[EAP_MSK_LEN]; 2234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 2334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *peerid; 2434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t peerid_len; 2534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 peerid_type; 2634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 serverid_type; 2734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 dh_priv[EAP_EKE_MAX_DH_LEN]; 2834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 key[EAP_EKE_MAX_KEY_LEN]; 2934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_session sess; 3034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonce_p[EAP_EKE_MAX_NONCE_LEN]; 3134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonce_s[EAP_EKE_MAX_NONCE_LEN]; 3234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msgs; 3334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt int phase2; 3434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u32 failure_code; 3534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}; 3634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 3734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 3834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic const char * eap_eke_state_txt(int state) 3934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 4034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt switch (state) { 4134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case IDENTITY: 4234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "IDENTITY"; 4334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case COMMIT: 4434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "COMMIT"; 4534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case CONFIRM: 4634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "CONFIRM"; 4734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case FAILURE_REPORT: 4834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "FAILURE_REPORT"; 4934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case SUCCESS: 5034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "SUCCESS"; 5134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case FAILURE: 5234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "FAILURE"; 5334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt default: 5434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "?"; 5534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 5634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 5734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_state(struct eap_eke_data *data, int state) 6034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 6134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s", 6234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state_txt(data->state), 6334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state_txt(state)); 6434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->state = state; 6534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 6634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 6734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 6834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_fail(struct eap_eke_data *data, u32 code) 6934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 7034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Failure - code 0x%x", code); 7134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->failure_code = code; 7234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, FAILURE_REPORT); 7334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 7434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void * eap_eke_init(struct eap_sm *sm) 7734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 7834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data; 7934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t i; 8034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 8134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data = os_zalloc(sizeof(*data)); 8234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data == NULL) 8334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 8434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, IDENTITY); 8534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 8634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid_type = EAP_EKE_ID_OPAQUE; 8734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt for (i = 0; i < sm->server_id_len; i++) { 8834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (sm->server_id[i] == '.' && 8934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid_type == EAP_EKE_ID_OPAQUE) 9034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid_type = EAP_EKE_ID_FQDN; 9134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (sm->server_id[i] == '@') 9234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid_type = EAP_EKE_ID_NAI; 9334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 9434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 9534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->phase2 = sm->init_phase2; 9634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 9734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data; 9834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 9934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 10034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 10134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_reset(struct eap_sm *sm, void *priv) 10234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 10334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 10434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 10534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->peerid); 10634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(data->msgs); 107c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 10834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 10934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 11034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 11134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data, 11234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 id, size_t length, u8 eke_exch) 11334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 11434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 11534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t plen; 11634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 11734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plen = 1 + length; 11834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 11934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen, 12034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_CODE_REQUEST, id); 12134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) { 12234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory"); 12334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 12434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 12534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 12634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, eke_exch); 12734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 12834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 12934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 13034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 13134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 13234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int supported_proposal(const u8 *pos) 13334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 13434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos[0] == EAP_EKE_DHGROUP_EKE_16 && 13534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[1] == EAP_EKE_ENCR_AES128_CBC && 13634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 && 13734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[3] == EAP_EKE_MAC_HMAC_SHA2_256) 13834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return 1; 13934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 14034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos[0] == EAP_EKE_DHGROUP_EKE_15 && 14134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[1] == EAP_EKE_ENCR_AES128_CBC && 14234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 && 14334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[3] == EAP_EKE_MAC_HMAC_SHA2_256) 14434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return 1; 14534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 14634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos[0] == EAP_EKE_DHGROUP_EKE_14 && 14734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[1] == EAP_EKE_ENCR_AES128_CBC && 14834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[2] == EAP_EKE_PRF_HMAC_SHA2_256 && 14934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[3] == EAP_EKE_MAC_HMAC_SHA2_256) 15034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return 1; 15134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos[0] == EAP_EKE_DHGROUP_EKE_14 && 15334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[1] == EAP_EKE_ENCR_AES128_CBC && 15434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[2] == EAP_EKE_PRF_HMAC_SHA1 && 15534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[3] == EAP_EKE_MAC_HMAC_SHA1) 15634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return 1; 15734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return 0; 15934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 16034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_failure(struct eap_eke_data *data, u8 id) 16334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 16434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 16534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Failure: Failure-Code=0x%x", 16734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->failure_code); 16834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE); 17034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) { 17134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, FAILURE); 17234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 17334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 17434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_be32(msg, data->failure_code); 17534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 17734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 17834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_identity(struct eap_sm *sm, 18134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 18234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 id) 18334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 18434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 18534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t plen; 18634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity"); 18834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plen = 2 + 4 * 4 + 1 + sm->server_id_len; 19034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID); 19134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) 19234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 19334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, 4); /* NumProposals */ 19534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, 0); /* Reserved */ 19634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Proposal - DH Group 16 with AES128-CBC and SHA256 */ 19834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_16); /* Group Description */ 19934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 20034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ 20134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ 20234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 20334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Proposal - DH Group 15 with AES128-CBC and SHA256 */ 20434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_15); /* Group Description */ 20534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 20634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ 20734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ 20834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 20934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Proposal - DH Group 14 with AES128-CBC and SHA256 */ 21034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */ 21134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 21234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA2_256); /* PRF */ 21334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA2_256); /* MAC */ 21434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 21634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * Proposal - DH Group 14 with AES128-CBC and SHA1 21734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * (mandatory to implement algorithms) 21834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 21934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_DHGROUP_EKE_14); /* Group Description */ 22034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_ENCR_AES128_CBC); /* Encryption */ 22134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_PRF_HMAC_SHA1); /* PRF */ 22234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, EAP_EKE_MAC_HMAC_SHA1); /* MAC */ 22334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 22434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* Server IDType + Identity */ 22534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, data->serverid_type); 22634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_data(msg, sm->server_id, sm->server_id_len); 22734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 22834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(data->msgs); 22934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->msgs = wpabuf_dup(msg); 23034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->msgs == NULL) { 23134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 23234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 23334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 23434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 23634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 23734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_commit(struct eap_sm *sm, 24034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, u8 id) 24134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 24234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 24334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 pub[EAP_EKE_MAX_DH_LEN]; 24434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Commit"); 24634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (sm->user == NULL || sm->user->password == NULL) { 24834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Password with not configured"); 24934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 25034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 25134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 25234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 25334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_key(&data->sess, sm->user->password, 25434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sm->user->password_len, 25534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sm->server_id, sm->server_id_len, 25634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, data->key) < 0) { 25734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key"); 25834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 25934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 26034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 26134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 26234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_eke_build_msg(data, id, data->sess.dhcomp_len, 26334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_COMMIT); 26434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) { 26534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 26634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 26734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 26834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 26934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 27034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * y_s = g ^ x_s (mod p) 27134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * x_s = random number 2 .. p-1 27234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * temp = prf(0+, password) 27334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * key = prf+(temp, ID_S | ID_P) 27434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * DHComponent_S = Encr(key, y_s) 27534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 27634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 27734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) { 27834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH"); 27934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 28034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 28134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 28234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 28334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_dhcomp(&data->sess, data->key, pub, 28434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(msg, data->sess.dhcomp_len)) 28534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt < 0) { 28634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_S"); 28734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 28834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 28934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 29034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 29134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 29234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (wpabuf_resize(&data->msgs, wpabuf_len(msg)) < 0) { 29334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 29434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 29534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 29634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 29734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, msg); 29834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 29934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 30034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 30134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_confirm(struct eap_sm *sm, 30434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, u8 id) 30534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 30634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 30734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t plen, prot_len; 30834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN]; 30934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *auth; 31034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 31134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Confirm"); 31234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 31334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plen = data->sess.pnonce_ps_len + data->sess.prf_len; 31434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_eke_build_msg(data, id, plen, EAP_EKE_CONFIRM); 31534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) { 31634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 31734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 31834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 31934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 32034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (random_get_bytes(data->nonce_s, data->sess.nonce_len)) { 32134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 32234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 32334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 32434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 32534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S", 32634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_s, data->sess.nonce_len); 32734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 32834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(nonces, data->nonce_p, data->sess.nonce_len); 32934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(nonces + data->sess.nonce_len, data->nonce_s, 33034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.nonce_len); 33134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prot_len = wpabuf_tailroom(msg); 33234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_prot(&data->sess, nonces, 2 * data->sess.nonce_len, 33334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(msg, 0), &prot_len) < 0) { 33434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 33534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 33634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 33734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 33834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(msg, prot_len); 33934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 34034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_ka(&data->sess, 34134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sm->server_id, sm->server_id_len, 34234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, 34334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_p, data->nonce_s) < 0) { 34434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 34534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 34634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 34734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 34834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 34934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt auth = wpabuf_put(msg, data->sess.prf_len); 35034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth) < 0) { 35134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(msg); 35234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 35334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 35434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 35534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth, data->sess.prf_len); 35634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 35734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 35834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 35934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 36034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 36134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id) 36234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 36334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 36434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 36534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt switch (data->state) { 36634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case IDENTITY: 36734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_identity(sm, data, id); 36834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case COMMIT: 36934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_commit(sm, data, id); 37034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case CONFIRM: 37134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_confirm(sm, data, id); 37234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case FAILURE_REPORT: 37334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_failure(data, id); 37434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt default: 37534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Unknown state %d in buildReq", 37634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->state); 37734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 37834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 37934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 38034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 38134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 38234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 38334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_check(struct eap_sm *sm, void *priv, 38434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *respData) 38534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 38634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 38734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t len; 38834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos; 38934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 eke_exch; 39034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 39134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); 39234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos == NULL || len < 1) { 39334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame"); 39434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return TRUE; 39534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 39634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 39734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eke_exch = *pos; 39834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch); 39934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 40034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state == IDENTITY && eke_exch == EAP_EKE_ID) 40134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return FALSE; 40234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 40334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT) 40434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return FALSE; 40534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 40634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM) 40734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return FALSE; 40834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 40934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eke_exch == EAP_EKE_FAILURE) 41034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return FALSE; 41134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 41234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d", 41334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eke_exch, data->state); 41434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 41534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return TRUE; 41634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 41734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 41834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 41934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_identity(struct eap_sm *sm, 42034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 42134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *respData, 42234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, size_t payloadlen) 42334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 42434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 42534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt int i; 42634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 42734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity"); 42834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 42934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != IDENTITY) { 43034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 43134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 43234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 43334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 43434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 43534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payloadlen; 43634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 43734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + 2 + 4 + 1 > end) { 43834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload"); 43934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 44034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 44134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 44234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 44334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (*pos != 1) { 44434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)", 44534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *pos); 44634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 44734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 44834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 44934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 45034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += 2; 45134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 45234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (!supported_proposal(pos)) { 45334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)", 45434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[0], pos[1], pos[2], pos[3]); 45534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 45634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 45734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 45834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 45934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)", 46034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos[0], pos[1], pos[2], pos[3]); 46134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) < 46234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 0) { 46334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 46434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 46534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 46634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += 4; 46734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 46834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid_type = *pos++; 46934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->peerid); 47034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid = os_malloc(end - pos); 47134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->peerid == NULL) { 47234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid"); 47334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 47434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 47534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 47634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(data->peerid, pos, end - pos); 47734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid_len = end - pos; 47834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type); 47934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity", 48034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len); 48134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 48234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) { 48334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database"); 48434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 48534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 48634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 48734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 48834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt for (i = 0; i < EAP_MAX_METHODS; i++) { 48934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 49034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sm->user->methods[i].method == EAP_TYPE_EKE) 49134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 49234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 49334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (i == EAP_MAX_METHODS) { 49434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE"); 49534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 49634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 49734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 49834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 49934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (sm->user->password == NULL || sm->user->password_len == 0) { 50034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer"); 50134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND); 50234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 50334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 50434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 50534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { 50634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 50734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 50834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 50934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, respData); 51034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 51134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, COMMIT); 51234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 51334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 51434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 51534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_commit(struct eap_sm *sm, 51634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 51734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *respData, 51834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, size_t payloadlen) 51934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 52034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end, *dhcomp, *pnonce; 52134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t decrypt_len; 52234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Commit"); 52434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != COMMIT) { 52634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 52734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 52834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 52934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 53034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 53134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payloadlen; 53234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 53334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + data->sess.dhcomp_len + data->sess.pnonce_len > end) { 53434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); 53534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 53634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 53734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 53834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 53934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P", 54034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, data->sess.dhcomp_len); 54134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhcomp = pos; 54234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += data->sess.dhcomp_len; 54334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", pos, data->sess.pnonce_len); 54434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pnonce = pos; 54534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += data->sess.pnonce_len; 54634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos); 54734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 54834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_shared_secret(&data->sess, data->key, data->dh_priv, dhcomp) 54934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt < 0) { 55034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret"); 55134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 55234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 55334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 55434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 55534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_ke_ki(&data->sess, 55634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sm->server_id, sm->server_id_len, 55734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len) < 0) { 55834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki"); 55934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 56034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 56134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 56234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 56334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt decrypt_len = sizeof(data->nonce_p); 56434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_decrypt_prot(&data->sess, pnonce, data->sess.pnonce_len, 56534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_p, &decrypt_len) < 0) { 56634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_P"); 56734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 56834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 56934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 57034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (decrypt_len < (size_t) data->sess.nonce_len) { 57134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: PNonce_P protected data too short to include Nonce_P"); 57234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 57334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 57434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 57534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P", 57634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_p, data->sess.nonce_len); 57734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 57834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) { 57934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 58034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 58134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 58234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, respData); 58334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, CONFIRM); 58534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 58634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_confirm(struct eap_sm *sm, 58934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 59034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *respData, 59134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, size_t payloadlen) 59234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 59334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t decrypt_len; 59434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonce[EAP_EKE_MAX_NONCE_LEN]; 59534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 auth_p[EAP_EKE_MAX_HASH_LEN]; 59634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 59734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm"); 59834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 59934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != CONFIRM) { 60034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 60134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 60234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 60334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 60434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Confirm"); 60534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 60634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (payloadlen < (size_t) data->sess.pnonce_len + data->sess.prf_len) { 60734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); 60834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR); 60934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 61034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 61134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 61234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt decrypt_len = sizeof(nonce); 61334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_decrypt_prot(&data->sess, payload, data->sess.pnonce_len, 61434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nonce, &decrypt_len) < 0) { 61534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_S"); 61634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 61734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 61834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 61934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (decrypt_len < (size_t) data->sess.nonce_len) { 62034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: PNonce_S protected data too short to include Nonce_S"); 62134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 62234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 62334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 62434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_S", 62534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nonce, data->sess.nonce_len); 62634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (os_memcmp(nonce, data->nonce_s, data->sess.nonce_len) != 0) { 62734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_S does not match previously sent Nonce_S"); 62834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 62934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 63034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 63134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 63234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth_p) < 0) { 63334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Could not derive Auth_P"); 63434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 63534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 63634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 63734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth_p, data->sess.prf_len); 638c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(auth_p, payload + data->sess.pnonce_len, 639c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt data->sess.prf_len) != 0) { 64034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Auth_P does not match"); 64134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_AUTHENTICATION_FAIL); 64234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 64334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 64434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 64534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_len, 64634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, 64734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_s, data->nonce_p, 64834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->msk, data->emsk) < 0) { 64934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK"); 65034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 65134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 65234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 65334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 65534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(data->key, 0, sizeof(data->key)); 65634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 65734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, SUCCESS); 65934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 66034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process_failure(struct eap_sm *sm, 66334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 66434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *respData, 66534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, size_t payloadlen) 66634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 66734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u32 code; 66834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Failure"); 67034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 67134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (payloadlen < 4) { 67234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure"); 67334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, FAILURE); 67434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 67534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 67634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 67734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt code = WPA_GET_BE32(payload); 67834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Peer reported failure code 0x%x", code); 67934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 68034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, FAILURE); 68134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 68234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 68334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 68434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_process(struct eap_sm *sm, void *priv, 68534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *respData) 68634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 68734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 68834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 eke_exch; 68934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t len; 69034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 69134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 69234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); 69334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos == NULL || len < 1) 69434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return; 69534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 69634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eke_exch = *pos; 69734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = pos + len; 69834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos++; 69934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received payload", pos, end - pos); 70134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt switch (eke_exch) { 70334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_ID: 70434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_process_identity(sm, data, respData, pos, end - pos); 70534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 70634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_COMMIT: 70734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_process_commit(sm, data, respData, pos, end - pos); 70834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 70934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_CONFIRM: 71034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_process_confirm(sm, data, respData, pos, end - pos); 71134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 71234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_FAILURE: 71334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_process_failure(sm, data, respData, pos, end - pos); 71434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 71534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 71634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 71734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 71834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 71934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_isDone(struct eap_sm *sm, void *priv) 72034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 72134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 72234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 72334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 72434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len) 72734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 72834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 72934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *key; 73034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 73134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != SUCCESS) 73234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 73334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 73434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 73534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (key == NULL) 73634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 73734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 73834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *len = EAP_MSK_LEN; 73934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return key; 74134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 74234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 74534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 74634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 74734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *key; 74834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != SUCCESS) 75034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 75134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 75234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 75334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (key == NULL) 75434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 75534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 75634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *len = EAP_EMSK_LEN; 75734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 75834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return key; 75934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 76034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 76134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 76234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv) 76334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 76434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 76534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data->state == SUCCESS; 76634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 76734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 76834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 76934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtint eap_server_eke_register(void) 77034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 77134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method *eap; 77234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt int ret; 77334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 77434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 77534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); 77634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap == NULL) 77734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return -1; 77834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 77934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->init = eap_eke_init; 78034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->reset = eap_eke_reset; 78134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->buildReq = eap_eke_buildReq; 78234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->check = eap_eke_check; 78334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->process = eap_eke_process; 78434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->isDone = eap_eke_isDone; 78534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->getKey = eap_eke_getKey; 78634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->isSuccess = eap_eke_isSuccess; 78734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->get_emsk = eap_eke_get_emsk; 78834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 78934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret = eap_server_method_register(eap); 79034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (ret) 79134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_server_method_free(eap); 79234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return ret; 79334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 794