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) { 88d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt data->peerid = os_memdup(identity, identity_len); 8934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->peerid == NULL) { 9034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_deinit(sm, data); 9134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 9234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 9334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid_len = identity_len; 9434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 9534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 96fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt phase1 = eap_get_config_phase1(sm); 97fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (phase1) { 98fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt const char *pos; 99fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 100fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "dhgroup="); 101fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 102fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->dhgroup = atoi(pos + 8); 103fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced dhgroup %u", 104fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->dhgroup); 105fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 106fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 107fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "encr="); 108fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 109fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->encr = atoi(pos + 5); 110fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced encr %u", 111fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->encr); 112fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 113fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 114fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "prf="); 115fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 116fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->prf = atoi(pos + 4); 117fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced prf %u", 118fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->prf); 119fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 120fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 121fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = os_strstr(phase1, "mac="); 122fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (pos) { 123fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->mac = atoi(pos + 4); 124fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Forced mac %u", 125fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt data->mac); 126fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 127fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 128fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 12934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data; 13034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 13134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 13234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 13334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void eap_eke_deinit(struct eap_sm *sm, void *priv) 13434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 13534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 13634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 13734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->serverid); 13834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->peerid); 13934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(data->msgs); 140c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 14134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 14234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 14334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 14434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data, int id, 14534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t length, u8 eke_exch) 14634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 14734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *msg; 14834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t plen; 14934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt plen = 1 + length; 15134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen, 15334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_CODE_RESPONSE, id); 15434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (msg == NULL) { 15534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory"); 15634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 15734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 15834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 15934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(msg, eke_exch); 16034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return msg; 16234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 16334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 16534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_dhgroup(u8 dhgroup) 16634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 16734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return dhgroup == EAP_EKE_DHGROUP_EKE_2 || 16834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_5 || 16934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_14 || 17034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_15 || 17134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhgroup == EAP_EKE_DHGROUP_EKE_16; 17234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 17334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_encr(u8 encr) 17634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 17734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return encr == EAP_EKE_ENCR_AES128_CBC; 17834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 17934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_prf(u8 prf) 18234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 18334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return prf == EAP_EKE_PRF_HMAC_SHA1 || 18434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prf == EAP_EKE_PRF_HMAC_SHA2_256; 18534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 18634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 18834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int eap_eke_supp_mac(u8 mac) 18934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 19034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return mac == EAP_EKE_MAC_HMAC_SHA1 || 19134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt mac == EAP_EKE_MAC_HMAC_SHA2_256; 19234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 19334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data, 19634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 197cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt u8 id, u32 failure_code) 19834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 19934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 20034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 20134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x", 20234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt failure_code); 20334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 204cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt resp = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE); 20534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp) 20634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_be32(resp, failure_code); 20734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 20834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 20934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 21034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, FAILURE); 21234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->methodState = METHOD_DONE; 21334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->decision = DECISION_FAIL; 21434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = FALSE; 21534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 21734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 21834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 21934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 22034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_id(struct eap_eke_data *data, 22134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 22234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 22334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 22434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 22534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 22634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 22734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt unsigned num_prop, i; 22834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 22934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *prop = NULL; 23034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 idtype; 231cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt u8 id = eap_get_id(reqData); 23234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != IDENTITY) { 234cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 23534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 23634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 23734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 23834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-ID/Request"); 23934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (payload_len < 2 + 4) { 24134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data"); 242cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 24334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 24434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 24534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 24734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payload_len; 24834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt num_prop = *pos++; 25034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos++; /* Ignore Reserved field */ 25134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 25234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + num_prop * 4 > end) { 25334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)", 25434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt num_prop); 255cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 25634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 25734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 25834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 25934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt for (i = 0; i < num_prop; i++) { 26034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *tmp = pos; 26134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 26234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u", 26334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt i, pos[0], pos[1], pos[2], pos[3]); 26434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += 4; 26534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 266fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->dhgroup && data->dhgroup != *tmp) || 267fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_dhgroup(*tmp)) 26834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 26934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt tmp++; 270fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->encr && data->encr != *tmp) || 271fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_encr(*tmp)) 27234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 27334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt tmp++; 274fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->prf && data->prf != *tmp) || 275fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_prf(*tmp)) 27634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 27734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt tmp++; 278fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((data->mac && data->mac != *tmp) || 279fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !eap_eke_supp_mac(*tmp)) 28034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 28134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 28234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prop = tmp - 3; 28334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_session_init(&data->sess, prop[0], prop[1], prop[2], 28434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prop[3]) < 0) { 28534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prop = NULL; 28634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt continue; 28734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 28834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 28934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Selected proposal"); 29034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 29134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 29234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 29334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (prop == NULL) { 29434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found"); 295cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 29634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN); 29734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 29834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 29934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += (num_prop - i - 1) * 4; 30034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos == end) { 30234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity"); 303cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 30434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 30534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 30634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 30734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt idtype = *pos++; 30834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Server IDType %u", idtype); 30934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Server Identity", 31034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 31134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_free(data->serverid); 312d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt data->serverid = os_memdup(pos, end - pos); 31334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->serverid == NULL) { 314cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 31534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 31634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 31734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid_len = end - pos; 31834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 31934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response"); 32034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 321cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt resp = eap_eke_build_msg(data, id, 32234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 2 + 4 + 1 + data->peerid_len, 32334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_ID); 32434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp == NULL) { 325cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 32634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 32734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 32834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 32934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(resp, 1); /* NumProposals */ 33034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(resp, 0); /* Reserved */ 33134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_data(resp, prop, 4); /* Selected Proposal */ 33234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_u8(resp, EAP_EKE_ID_NAI); 33334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->peerid) 33434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_data(resp, data->peerid, data->peerid_len); 33534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 33634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(data->msgs); 33734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp)); 33834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->msgs == NULL) { 33934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 340cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 34134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 34234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 34334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, reqData); 34434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put_buf(data->msgs, resp); 34534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 34634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, COMMIT); 34734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 34834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 34934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 35034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 35134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 35234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, 35334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data, 35434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 35534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 35634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 35734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 35834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 35934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 36034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end, *dhcomp; 36134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t prot_len; 36234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *rpos; 36334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 key[EAP_EKE_MAX_KEY_LEN]; 36434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 pub[EAP_EKE_MAX_DH_LEN]; 36534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *password; 36634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t password_len; 367cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt u8 id = eap_get_id(reqData); 36834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 36934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != COMMIT) { 37034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Commit/Request received in unexpected state (%d)", data->state); 371cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 37234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 37334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 37434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 37534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Commit/Request"); 37634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 37734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 37834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (password == NULL) { 37934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: No password configured!"); 380cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 38134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PASSWD_NOT_FOUND); 38234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 38334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 38434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 38534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payload_len; 38634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 38734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + data->sess.dhcomp_len > end) { 38834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit"); 389cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 39034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 39134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 39234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 39334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_S", 39434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, data->sess.dhcomp_len); 39534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt dhcomp = pos; 39634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos += data->sess.dhcomp_len; 39734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos); 39834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 39934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 40034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * temp = prf(0+, password) 40134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * key = prf+(temp, ID_S | ID_P) 40234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 40334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_key(&data->sess, password, password_len, 40434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid, data->serverid_len, 40534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, key) < 0) { 40634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key"); 407cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 40834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 40934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 41034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 41134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* 41234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * y_p = g ^ x_p (mod p) 41334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * x_p = random number 2 .. p-1 41434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt */ 41534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) { 41634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH"); 41734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 418cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 41934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 42034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 42134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 42234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_shared_secret(&data->sess, key, data->dh_priv, dhcomp) < 0) 42334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt { 42434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret"); 42534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 426cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 42734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 42834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 42934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 43034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_ke_ki(&data->sess, 43134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->serverid, data->serverid_len, 43234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len) < 0) { 43334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki"); 43434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 435cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 43634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 43734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 43834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 43934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Commit/Response"); 44034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 441cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt resp = eap_eke_build_msg(data, id, 44234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.dhcomp_len + data->sess.pnonce_len, 44334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_COMMIT); 44434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp == NULL) { 44534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 446cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 44734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 44834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 44934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 45034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt /* DHComponent_P = Encr(key, y_p) */ 45134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt rpos = wpabuf_put(resp, data->sess.dhcomp_len); 45234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) { 453d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpabuf_free(resp); 45443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P"); 45534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(key, 0, sizeof(key)); 456cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 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); 466cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 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); 475cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 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); 487cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 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; 512cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt u8 id = eap_get_id(reqData); 51334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 51434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != CONFIRM) { 51534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)", 51634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->state); 517cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 51834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 51934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 52034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Confirm/Request"); 52234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = payload; 52434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = payload + payload_len; 52534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) { 52743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm"); 528cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 52934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PROTO_ERROR); 53034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 53134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 53234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt decrypt_len = sizeof(nonces); 53334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_decrypt_prot(&data->sess, pos, data->sess.pnonce_ps_len, 53434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nonces, &decrypt_len) < 0) { 53534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_PS"); 536cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 53734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 53834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 53934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (decrypt_len != (size_t) 2 * data->sess.nonce_len) { 54034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S"); 541cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 54234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 54334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 54434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S", 54534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nonces, 2 * data->sess.nonce_len); 54634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) { 54743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P"); 548cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 54934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 55034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 55134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 55234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(data->nonce_s, nonces + data->sess.nonce_len, 55334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.nonce_len); 55434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S", 55534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_s, data->sess.nonce_len); 55634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 55734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_ka(&data->sess, data->serverid, data->serverid_len, 55834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, 55934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_p, data->nonce_s) < 0) { 560cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 56134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 56234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 56334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 56434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth_s) < 0) 56534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt { 566cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 56734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 56834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 56934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len); 570c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(auth_s, pos + data->sess.pnonce_ps_len, 571c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt data->sess.prf_len) != 0) { 57234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match"); 573cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 57434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_AUTHENTICATION_FAIL); 57534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 57634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 57734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Confirm/Response"); 57834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 579cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt resp = eap_eke_build_msg(data, id, 58034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->sess.pnonce_len + data->sess.prf_len, 58134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_CONFIRM); 58234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (resp == NULL) { 583cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 58434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 58534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 58634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt prot_len = wpabuf_tailroom(resp); 58834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_prot(&data->sess, data->nonce_s, data->sess.nonce_len, 58934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, 0), &prot_len) < 0) { 59034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 591cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 59234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 59334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 59434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_put(resp, prot_len); 59534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 59634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt auth = wpabuf_put(resp, data->sess.prf_len); 59734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth) < 0) { 59834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 599cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 60034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 60134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 60234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth, data->sess.prf_len); 60334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 60434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap_eke_derive_msk(&data->sess, data->serverid, data->serverid_len, 60534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->peerid, data->peerid_len, 60634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->nonce_s, data->nonce_p, 60734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt data->msk, data->emsk) < 0) { 60834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK"); 60934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpabuf_free(resp); 610cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, id, 61134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR); 61234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 61334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 61434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); 61534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_session_clean(&data->sess); 61634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 61734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap_eke_state(data, SUCCESS); 61834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 61934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 62034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = FALSE; 62134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 62234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 62334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 62434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 62534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 62634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process_failure(struct eap_eke_data *data, 62734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 62834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData, 62934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *payload, 63034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t payload_len) 63134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 63234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Failure/Request"); 63334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 63434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (payload_len < 4) { 63534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure"); 63634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } else { 63734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u32 code; 63834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt code = WPA_GET_BE32(payload); 63934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-EKE: Failure-Code 0x%x", code); 64034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 64134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 642cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt return eap_eke_build_fail(data, ret, eap_get_id(reqData), 643cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt EAP_EKE_FAIL_NO_ERROR); 64434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 64534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 64634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 64734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, 64834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method_ret *ret, 64934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const struct wpabuf *reqData) 65034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 65134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 65234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpabuf *resp; 65334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *pos, *end; 65434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt size_t len; 65534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 eke_exch; 65634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, reqData, &len); 65834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (pos == NULL || len < 1) { 65934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->ignore = TRUE; 66034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 66134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 66234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt end = pos + len; 66434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eke_exch = *pos++; 66534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: exch %d", eke_exch); 66734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received Data", pos, end - pos); 66834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 66934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->ignore = FALSE; 67034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 67134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->decision = DECISION_FAIL; 67234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = TRUE; 67334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 67434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt switch (eke_exch) { 67534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_ID: 67634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_id(data, ret, reqData, pos, end - pos); 67734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 67834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_COMMIT: 67934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_commit(sm, data, ret, reqData, 68034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 68134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 68234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_CONFIRM: 68334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_confirm(data, ret, reqData, 68434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 68534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 68634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case EAP_EKE_FAILURE: 68734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt resp = eap_eke_process_failure(data, ret, reqData, 68834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt pos, end - pos); 68934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt break; 69034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt default: 69134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch); 69234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->ignore = TRUE; 69334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 69434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 69534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 69634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (ret->methodState == METHOD_DONE) 69734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret->allowNotifications = FALSE; 69834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 69934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return resp; 70034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 70134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic Boolean eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv) 70434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 70534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 70634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data->state == SUCCESS; 70734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 70834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 70934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 71034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len) 71134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 71234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 71334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *key; 71434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 71534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != SUCCESS) 71634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 71734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 718d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt key = os_memdup(data->msk, EAP_MSK_LEN); 71934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (key == NULL) 72034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 72134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *len = EAP_MSK_LEN; 72234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return key; 72434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 72534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 72734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 72834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 72934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_eke_data *data = priv; 73034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *key; 73134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 73234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (data->state != SUCCESS) 73334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 73434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 735d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt key = os_memdup(data->emsk, EAP_EMSK_LEN); 73634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (key == NULL) 73734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NULL; 73834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt *len = EAP_EMSK_LEN; 73934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return key; 74134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 74234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 74334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7448bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidtstatic u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 7458bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt{ 7468bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt struct eap_eke_data *data = priv; 7478bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt u8 *sid; 7488bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt size_t sid_len; 7498bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt 7508bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt if (data->state != SUCCESS) 7518bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt return NULL; 7528bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt 7538bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt sid_len = 1 + 2 * data->sess.nonce_len; 7548bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt sid = os_malloc(sid_len); 7558bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt if (sid == NULL) 7568bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt return NULL; 7578bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt sid[0] = EAP_TYPE_EKE; 7588bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len); 7598bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s, 7608bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt data->sess.nonce_len); 7618bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt *len = sid_len; 7628bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt 7638bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt return sid; 7648bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt} 7658bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt 7668bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt 76734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtint eap_peer_eke_register(void) 76834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 76934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct eap_method *eap; 77034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 77134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 77234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); 77334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (eap == NULL) 77434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return -1; 77534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 77634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->init = eap_eke_init; 77734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->deinit = eap_eke_deinit; 77834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->process = eap_eke_process; 77934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->isKeyAvailable = eap_eke_isKeyAvailable; 78034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->getKey = eap_eke_getKey; 78134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt eap->get_emsk = eap_eke_get_emsk; 7828bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt eap->getSessionId = eap_eke_get_session_id; 78334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7841d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return eap_peer_method_register(eap); 78534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 786