1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP peer method: EAP-PSK (RFC 4764) 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Note: EAP-PSK is an EAP authentication method and as such, completely 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * different from WPA-PSK. This file is not needed for WPA-PSK functionality. 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_peer/eap_i.h" 22b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/aes_wrap.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_common/eap_psk_common.h" 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_psk_data { 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 rand_p[EAP_PSK_RAND_LEN]; 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *id_s, *id_p; 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t id_s_len, id_p_len; 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 msk[EAP_MSK_LEN]; 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_psk_init(struct eap_sm *sm) 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_data *data; 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *identity, *password; 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t identity_len, password_len; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password = eap_get_config_password(sm, &password_len); 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!password || password_len != 16) { 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not " 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "configured"); 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_psk_key_setup(password, data->ak, data->kdk)) { 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = PSK_INIT; 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (identity) { 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->id_p = os_malloc(identity_len); 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->id_p) 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->id_p, identity, identity_len); 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->id_p_len = identity_len; 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->id_p == NULL) { 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_psk_deinit(struct eap_sm *sm, void *priv) 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_data *data = priv; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->id_s); 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->id_p); 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *reqData) 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_psk_hdr_1 *hdr1; 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_hdr_2 *hdr2; 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *buf, *pos; 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buflen, len; 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *cpos; 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr1 = (const struct eap_psk_hdr_1 *) cpos; 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cpos == NULL || len < sizeof(*hdr1)) { 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "length (%lu; expected %lu or more)", 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len, 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) sizeof(*hdr1)); 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) { 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_PSK_FLAGS_GET_T(hdr1->flags)); 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s, 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_PSK_RAND_LEN); 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->id_s); 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->id_s_len = len - sizeof(*hdr1); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->id_s = os_malloc(data->id_s_len); 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->id_s == NULL) { 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "ID_S (len=%lu)", (unsigned long) data->id_s_len); 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->id_s, data->id_s_len); 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(data->rand_p, EAP_PSK_RAND_LEN)) { 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(*hdr2) + data->id_p_len, EAP_CODE_RESPONSE, 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_get_id(reqData)); 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr2 = wpabuf_put(resp, sizeof(*hdr2)); 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */ 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(resp, data->id_p, data->id_p_len); 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(buflen); 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(resp); 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf, data->id_p, data->id_p_len); 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf + data->id_p_len; 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data->id_s, data->id_s_len); 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += data->id_s_len; 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += EAP_PSK_RAND_LEN; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) { 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(resp); 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_PSK_RAND_LEN); 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->id_p, data->id_p_len); 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = PSK_MAC_SENT; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *reqData) 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_psk_hdr_3 *hdr3; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_hdr_4 *hdr4; 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *buf, *rpchannel, nonce[16], *decrypted; 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pchannel, *tag, *msg; 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 mac[EAP_PSK_MAC_LEN]; 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buflen, left, data_len, len, plen; 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int failed = 0; 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reqData, &len); 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr3 = (const struct eap_psk_hdr_3 *) pos; 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < sizeof(*hdr3)) { 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "length (%lu; expected %lu or more)", 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len, 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) sizeof(*hdr3)); 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left = len - sizeof(*hdr3); 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pchannel = (const u8 *) (hdr3 + 1); 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) { 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_PSK_FLAGS_GET_T(hdr3->flags)); 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_PSK_RAND_LEN); 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left < 4 + 16 + 1) { 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "third message (len=%lu, expected 21)", 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) left); 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buflen = data->id_s_len + EAP_PSK_RAND_LEN; 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(buflen); 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf, data->id_s, data->id_s_len); 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (omac1_aes_128(data->ak, buf, buflen, mac)) { 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "message"); 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->msk, data->emsk)) { 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(nonce, 0, 12); 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(nonce + 12, pchannel, 4); 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pchannel += 4; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= 4; 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tag = pchannel; 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pchannel += 16; 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left -= 16; 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = pchannel; 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nonce, sizeof(nonce)); 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_head(reqData), 5); 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted = os_malloc(left); 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (decrypted == NULL) { 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(decrypted, msg, left); 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_head(reqData), 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct eap_hdr) + 1 + 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(*hdr3) - EAP_PSK_MAC_LEN, decrypted, 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left, tag)) { 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt decrypted, left); 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Verify R flag */ 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (decrypted[0] >> 6) { 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case EAP_PSK_R_FLAG_CONT: 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case EAP_PSK_R_FLAG_DONE_SUCCESS: 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case EAP_PSK_R_FLAG_DONE_FAILURE: 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "authentication"); 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data_len = 1; 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((decrypted[0] & EAP_PSK_E_FLAG) && left > 1) 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data_len++; 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = sizeof(*hdr4) + 4 + 16 + data_len; 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, plen, 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) { 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr4 = wpabuf_put(resp, sizeof(*hdr4)); 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel = wpabuf_put(resp, 4 + 16 + data_len); 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* nonce++ */ 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inc_byte_array(nonce, sizeof(nonce)); 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(rpchannel, nonce + 12, 4); 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (decrypted[0] & EAP_PSK_E_FLAG) { 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag"); 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed = 1; 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) | 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_PSK_E_FLAG; 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (left > 1) { 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Add empty EXT_Payload with same EXT_Type */ 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel[4 + 16 + 1] = decrypted[1]; 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (failed) 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6; 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel + 4 + 16, data_len); 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_head(resp), 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct eap_hdr) + 1 + sizeof(*hdr4), 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel + 4 + 16, data_len, rpchannel + 4)) { 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(resp); 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rpchannel, 4 + 16 + data_len); 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt failed ? "un" : ""); 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = PSK_DONE; 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(decrypted); 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *reqData) 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_data *data = priv; 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp = NULL; 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL) { 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = FALSE; 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_MAY_CONT; 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = TRUE; 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PSK_INIT: 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_psk_process_1(data, ret, reqData); 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PSK_MAC_SENT: 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_psk_process_3(data, ret, reqData); 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PSK_DONE: 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "unexpected message"); 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret->methodState == METHOD_DONE) { 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = FALSE; 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_data *data = priv; 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == PSK_DONE; 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_data *data = priv; 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *key; 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != PSK_DONE) 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key = os_malloc(EAP_MSK_LEN); 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key == NULL) 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = EAP_MSK_LEN; 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(key, data->msk, EAP_MSK_LEN); 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return key; 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_psk_data *data = priv; 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *key; 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != PSK_DONE) 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key == NULL) 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = EAP_EMSK_LEN; 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return key; 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_peer_psk_register(void) 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_psk_init; 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->deinit = eap_psk_deinit; 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_psk_process; 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isKeyAvailable = eap_psk_isKeyAvailable; 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->getKey = eap_psk_getKey; 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->get_emsk = eap_psk_get_emsk; 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_peer_method_register(eap); 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_peer_method_free(eap); 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 483