134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt/* 234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * EAP peer method: EAP-EKE (RFC 6124) 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_peer/eap_i.h" 1434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#include "eap_common/eap_eke_common.h" 1534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 1634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstruct eap_eke_data { 1734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt enum { 1834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt IDENTITY, COMMIT, CONFIRM, SUCCESS, FAILURE 1934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } state; 2034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 msk[EAP_MSK_LEN]; 2134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 2234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *peerid; 2334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t peerid_len; 2434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *serverid; 2534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t serverid_len; 2634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 dh_priv[EAP_EKE_MAX_DH_LEN]; 2734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_session sess; 2834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonce_p[EAP_EKE_MAX_NONCE_LEN]; 2934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonce_s[EAP_EKE_MAX_NONCE_LEN]; 3034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msgs; 31fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u8 dhgroup; /* forced DH group or 0 to allow all supported */ 32fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u8 encr; /* forced encryption algorithm or 0 to allow all supported */ 33fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u8 prf; /* forced PRF or 0 to allow all supported */ 34fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u8 mac; /* forced MAC or 0 to allow all supported */ 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 SUCCESS: 4834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "SUCCESS"; 4934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case FAILURE: 5034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "FAILURE"; 5134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt default: 5234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "?"; 5334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 5434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 5534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_state(struct eap_eke_data *data, int state) 5834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 5934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s", 6034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state_txt(data->state), eap_eke_state_txt(state)); 6134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->state = state; 6234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 6334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 6434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 6534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_deinit(struct eap_sm *sm, void *priv); 6634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 6734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 6834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void * eap_eke_init(struct eap_sm *sm) 6934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 7034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data; 7134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *identity, *password; 7234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t identity_len, password_len; 73fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt const char *phase1; 7434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 7634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (!password) { 7734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: No password configured"); 7834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 7934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 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 identity = eap_get_config_identity(sm, &identity_len); 8734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (identity) { 8834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid = os_malloc(identity_len); 8934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->peerid == NULL) { 9034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_deinit(sm, data); 9134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 9234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 9334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(data->peerid, identity, identity_len); 9434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid_len = identity_len; 9534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 9634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 97fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt phase1 = eap_get_config_phase1(sm); 98fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (phase1) { 99fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt const char *pos; 100fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 101fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "dhgroup="); 102fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 103fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->dhgroup = atoi(pos + 8); 104fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced dhgroup %u", 105fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->dhgroup); 106fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 107fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 108fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "encr="); 109fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 110fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->encr = atoi(pos + 5); 111fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced encr %u", 112fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->encr); 113fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 114fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 115fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "prf="); 116fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 117fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->prf = atoi(pos + 4); 118fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced prf %u", 119fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->prf); 120fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 121fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 122fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "mac="); 123fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 124fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->mac = atoi(pos + 4); 125fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced mac %u", 126fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->mac); 127fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 128fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 129fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 13034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data; 13134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 13234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 13334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 13434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_deinit(struct eap_sm *sm, void *priv) 13534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 13634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 13734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 13834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->serverid); 13934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->peerid); 14034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(data->msgs); 141c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 14234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 14334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 14434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 14534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data, int id, 14634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t length, u8 eke_exch) 14734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 14834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 14934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t plen; 15034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plen = 1 + length; 15234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen, 15434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_CODE_RESPONSE, id); 15534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) { 15634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory"); 15734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 15834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 15934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, eke_exch); 16134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 16334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 16434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_dhgroup(u8 dhgroup) 16734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 16834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return dhgroup == EAP_EKE_DHGROUP_EKE_2 || 16934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_5 || 17034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_14 || 17134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_15 || 17234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_16; 17334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 17434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_encr(u8 encr) 17734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 17834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return encr == EAP_EKE_ENCR_AES128_CBC; 17934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 18034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_prf(u8 prf) 18334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 18434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return prf == EAP_EKE_PRF_HMAC_SHA1 || 18534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prf == EAP_EKE_PRF_HMAC_SHA2_256; 18634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 18734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_mac(u8 mac) 19034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 19134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return mac == EAP_EKE_MAC_HMAC_SHA1 || 19234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt mac == EAP_EKE_MAC_HMAC_SHA2_256; 19334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 19434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data, 19734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 19834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 19934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u32 failure_code) 20034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 20134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 20234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 20334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x", 20434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt failure_code); 20534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 20634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_build_msg(data, eap_get_id(reqData), 4, EAP_EKE_FAILURE); 20734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp) 20834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_be32(resp, failure_code); 20934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 21134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 21234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, FAILURE); 21434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->methodState = METHOD_DONE; 21534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->decision = DECISION_FAIL; 21634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = FALSE; 21734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 21934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 22034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 22134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 22234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, 22334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 22434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 22534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 22634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 22734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 22834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 22934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt unsigned num_prop, i; 23034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 23134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *prop = NULL; 23234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 idtype; 23334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != IDENTITY) { 23534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 23634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 23734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 23834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-ID/Request"); 24034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (payload_len < 2 + 4) { 24234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data"); 24334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 24434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 24534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 24634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 24834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payload_len; 24934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 25034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt num_prop = *pos++; 25134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos++; /* Ignore Reserved field */ 25234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 25334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + num_prop * 4 > end) { 25434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)", 25534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt num_prop); 25634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 25734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 25834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 25934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 26034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt for (i = 0; i < num_prop; i++) { 26134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *tmp = pos; 26234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 26334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u", 26434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt i, pos[0], pos[1], pos[2], pos[3]); 26534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += 4; 26634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 267fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->dhgroup && data->dhgroup != *tmp) || 268fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_dhgroup(*tmp)) 26934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 27034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt tmp++; 271fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->encr && data->encr != *tmp) || 272fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_encr(*tmp)) 27334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 27434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt tmp++; 275fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->prf && data->prf != *tmp) || 276fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_prf(*tmp)) 27734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 27834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt tmp++; 279fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->mac && data->mac != *tmp) || 280fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_mac(*tmp)) 28134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 28234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 28334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prop = tmp - 3; 28434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_session_init(&data->sess, prop[0], prop[1], prop[2], 28534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prop[3]) < 0) { 28634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prop = NULL; 28734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 28834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 28934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 29034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Selected proposal"); 29134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 29234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 29334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 29434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (prop == NULL) { 29534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found"); 29634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 29734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN); 29834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 29934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += (num_prop - i - 1) * 4; 30134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos == end) { 30334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity"); 30434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 30534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 30634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 30734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt idtype = *pos++; 30934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Server IDType %u", idtype); 31034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Server Identity", 31134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 31234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->serverid); 31334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid = os_malloc(end - pos); 31434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->serverid == NULL) { 31534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 31634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 31734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 31834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(data->serverid, pos, end - pos); 31934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid_len = end - pos; 32034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 32134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response"); 32234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 32334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_build_msg(data, eap_get_id(reqData), 32434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 2 + 4 + 1 + data->peerid_len, 32534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_ID); 32634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp == NULL) { 32734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 32834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 32934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 33034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 33134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(resp, 1); /* NumProposals */ 33234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(resp, 0); /* Reserved */ 33334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_data(resp, prop, 4); /* Selected Proposal */ 33434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(resp, EAP_EKE_ID_NAI); 33534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->peerid) 33634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_data(resp, data->peerid, data->peerid_len); 33734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 33834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(data->msgs); 33934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp)); 34034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->msgs == NULL) { 34134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 34234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 34334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 34434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 34534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, reqData); 34634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, resp); 34734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 34834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, COMMIT); 34934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 35034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 35134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 35234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 35334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 35434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, 35534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 35634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 35734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 35834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 35934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 36034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 36134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 36234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end, *dhcomp; 36334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t prot_len; 36434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *rpos; 36534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 key[EAP_EKE_MAX_KEY_LEN]; 36634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 pub[EAP_EKE_MAX_DH_LEN]; 36734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *password; 36834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t password_len; 36934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 37034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != COMMIT) { 37134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Commit/Request received in unexpected state (%d)", data->state); 37234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 37334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 37434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 37534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 37634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Commit/Request"); 37734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 37834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 37934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (password == NULL) { 38034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: No password configured!"); 38134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 38234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PASSWD_NOT_FOUND); 38334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 38434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 38534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 38634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payload_len; 38734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 38834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + data->sess.dhcomp_len > end) { 38934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); 39034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 39134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 39234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 39334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 39434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_S", 39534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, data->sess.dhcomp_len); 39634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhcomp = pos; 39734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += data->sess.dhcomp_len; 39834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos); 39934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 40034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 40134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * temp = prf(0+, password) 40234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * key = prf+(temp, ID_S | ID_P) 40334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 40434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_key(&data->sess, password, password_len, 40534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid, data->serverid_len, 40634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, key) < 0) { 40734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key"); 40834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 40934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 41034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 41134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 41234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 41334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * y_p = g ^ x_p (mod p) 41434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * x_p = random number 2 .. p-1 41534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 41634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) { 41734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH"); 41834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 41934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 42034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 42134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 42234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 42334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_shared_secret(&data->sess, key, data->dh_priv, dhcomp) < 0) 42434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt { 42534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret"); 42634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 42734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 42834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 42934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 43034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 43134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_ke_ki(&data->sess, 43234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid, data->serverid_len, 43334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len) < 0) { 43434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki"); 43534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 43634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 43734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 43834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 43934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 44034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Commit/Response"); 44134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 44234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_build_msg(data, eap_get_id(reqData), 44334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.dhcomp_len + data->sess.pnonce_len, 44434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_COMMIT); 44534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp == NULL) { 44634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 44734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 44834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 44934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 45034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 45134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* DHComponent_P = Encr(key, y_p) */ 45234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt rpos = wpabuf_put(resp, data->sess.dhcomp_len); 45334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) { 45443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P"); 45534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 45634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 45734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 45834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 45934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 46034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 46134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P", 46234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt rpos, data->sess.dhcomp_len); 46334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 46434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (random_get_bytes(data->nonce_p, data->sess.nonce_len)) { 46534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 46634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 46734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 46834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 46934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P", 47034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_p, data->sess.nonce_len); 47134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prot_len = wpabuf_tailroom(resp); 47234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_prot(&data->sess, data->nonce_p, data->sess.nonce_len, 47334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, 0), &prot_len) < 0) { 47434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 47534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 47634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 47734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 47834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P", 47934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, 0), prot_len); 48034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, prot_len); 48134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 48234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* TODO: CBValue */ 48334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 48434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (wpabuf_resize(&data->msgs, wpabuf_len(reqData) + wpabuf_len(resp)) 48534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt < 0) { 48634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 48734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 48834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 48934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 49034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, reqData); 49134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, resp); 49234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 49334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, CONFIRM); 49434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 49534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 49634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 49734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 49834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 49934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, 50034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 50134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 50234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 50334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 50434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 50534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 50634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 50734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t prot_len; 50834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN]; 50934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 auth_s[EAP_EKE_MAX_HASH_LEN]; 51034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t decrypt_len; 51134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *auth; 51234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 51334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != CONFIRM) { 51434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)", 51534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->state); 51634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 51734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 51834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 51934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Confirm/Request"); 52134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 52334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payload_len; 52434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) { 52643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); 52734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 52834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 52934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 53034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 53134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt decrypt_len = sizeof(nonces); 53234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_decrypt_prot(&data->sess, pos, data->sess.pnonce_ps_len, 53334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nonces, &decrypt_len) < 0) { 53434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_PS"); 53534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 53634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 53734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 53834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (decrypt_len != (size_t) 2 * data->sess.nonce_len) { 53934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S"); 54034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 54134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 54234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 54334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S", 54434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nonces, 2 * data->sess.nonce_len); 54534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) { 54643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P"); 54734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 54834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 54934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 55034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 55134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(data->nonce_s, nonces + data->sess.nonce_len, 55234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.nonce_len); 55334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S", 55434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_s, data->sess.nonce_len); 55534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 55634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_ka(&data->sess, data->serverid, data->serverid_len, 55734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, 55834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_p, data->nonce_s) < 0) { 55934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 56034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 56134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 56234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 56334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth_s) < 0) 56434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt { 56534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 56634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 56734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 56834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len); 569c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(auth_s, pos + data->sess.pnonce_ps_len, 570c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt data->sess.prf_len) != 0) { 57134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match"); 57234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 57334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 57434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 57534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 57634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Confirm/Response"); 57734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 57834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_build_msg(data, eap_get_id(reqData), 57934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.pnonce_len + data->sess.prf_len, 58034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_CONFIRM); 58134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp == NULL) { 58234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 58334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 58434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 58534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prot_len = wpabuf_tailroom(resp); 58734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_prot(&data->sess, data->nonce_s, data->sess.nonce_len, 58834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, 0), &prot_len) < 0) { 58934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 59034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 59134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 59234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 59334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, prot_len); 59434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 59534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt auth = wpabuf_put(resp, data->sess.prf_len); 59634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth) < 0) { 59734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 59834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 59934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 60034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 60134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth, data->sess.prf_len); 60234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 60334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_msk(&data->sess, data->serverid, data->serverid_len, 60434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, 60534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_s, data->nonce_p, 60634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->msk, data->emsk) < 0) { 60734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK"); 60834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 60934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, 61034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 61134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 61234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 61334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 61434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 61534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 61634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, SUCCESS); 61734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 61834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 61934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = FALSE; 62034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 62134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 62234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 62334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 62434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 62534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_failure(struct eap_eke_data *data, 62634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 62734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 62834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 62934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 63034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 63134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Failure/Request"); 63234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 63334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (payload_len < 4) { 63434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure"); 63534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } else { 63634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u32 code; 63734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt code = WPA_GET_BE32(payload); 63834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failure-Code 0x%x", code); 63934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 64034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 64134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return eap_eke_build_fail(data, ret, reqData, EAP_EKE_FAIL_NO_ERROR); 64234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 64334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 64434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 64534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, 64634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 64734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData) 64834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 64934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 65034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 65134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 65234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t len; 65334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 eke_exch; 65434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, reqData, &len); 65634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos == NULL || len < 1) { 65734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->ignore = TRUE; 65834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 65934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 66034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = pos + len; 66234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eke_exch = *pos++; 66334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: exch %d", eke_exch); 66534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received Data", pos, end - pos); 66634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->ignore = FALSE; 66834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 66934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->decision = DECISION_FAIL; 67034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = TRUE; 67134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 67234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt switch (eke_exch) { 67334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_ID: 67434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_id(data, ret, reqData, pos, end - pos); 67534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 67634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_COMMIT: 67734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_commit(sm, data, ret, reqData, 67834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 67934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 68034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_CONFIRM: 68134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_confirm(data, ret, reqData, 68234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 68334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 68434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_FAILURE: 68534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_failure(data, ret, reqData, 68634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 68734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 68834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt default: 68934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch); 69034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->ignore = TRUE; 69134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 69234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 69334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 69434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (ret->methodState == METHOD_DONE) 69534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = FALSE; 69634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 69734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 69834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 69934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv) 70234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 70334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 70434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data->state == SUCCESS; 70534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 70634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len) 70934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 71034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 71134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *key; 71234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 71334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != SUCCESS) 71434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 71534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 71634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 71734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (key == NULL) 71834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 71934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 72034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *len = EAP_MSK_LEN; 72134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return key; 72334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 72434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_get_emsk(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_EMSK_LEN); 73534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (key == NULL) 73634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 73734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 73834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *len = EAP_EMSK_LEN; 73934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return key; 74134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 74234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtint eap_peer_eke_register(void) 74534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 74634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method *eap; 74734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt int ret; 74834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 75034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); 75134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap == NULL) 75234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return -1; 75334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 75434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->init = eap_eke_init; 75534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->deinit = eap_eke_deinit; 75634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->process = eap_eke_process; 75734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->isKeyAvailable = eap_eke_isKeyAvailable; 75834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->getKey = eap_eke_getKey; 75934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->get_emsk = eap_eke_get_emsk; 76034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 76134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret = eap_peer_method_register(eap); 76234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (ret) 76334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_peer_method_free(eap); 76434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return ret; 76534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 766