static void * eap_psk_init(struct eap_sm *sm) { struct eap_psk_data *data; const u8 *identity, *password; size_t identity_len, password_len; password = eap_get_config_password(sm, &password_len); if (!password || password_len != 16) { wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not " "configured"); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; if (eap_psk_key_setup(password, data->ak, data->kdk)) { os_free(data); return NULL; } wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); data->state = PSK_INIT; identity = eap_get_config_identity(sm, &identity_len); if (identity) { data->id_p = os_malloc(identity_len); if (data->id_p) os_memcpy(data->id_p, identity, identity_len); data->id_p_len = identity_len; } if (data->id_p == NULL) { wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); os_free(data); return NULL; } return data; }
static void eap_psk_process_2(struct eap_sm *sm, struct eap_psk_data *data, struct wpabuf *respData) { const struct eap_psk_hdr_2 *resp; u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; size_t left, buflen; int i; const u8 *cpos; if (data->state != PSK_1) return; wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); if (cpos == NULL || left < sizeof(*resp)) { wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); return; } resp = (const struct eap_psk_hdr_2 *) cpos; cpos = (const u8 *) (resp + 1); left -= sizeof(*resp); os_free(data->id_p); data->id_p = os_malloc(left); if (data->id_p == NULL) { wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " "ID_P"); return; } os_memcpy(data->id_p, cpos, left); data->id_p_len = left; wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P", data->id_p, data->id_p_len); if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P", data->id_p, data->id_p_len); data->state = FAILURE; return; } for (i = 0; i < EAP_MAX_METHODS && (sm->user->methods[i].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_NONE); i++) { if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && sm->user->methods[i].method == EAP_TYPE_PSK) break; } if (i >= EAP_MAX_METHODS || sm->user->methods[i].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_PSK) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: EAP-PSK not enabled for ID_P", data->id_p, data->id_p_len); data->state = FAILURE; return; } if (sm->user->password == NULL || sm->user->password_len != EAP_PSK_PSK_LEN) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in " "user database for ID_P", data->id_p, data->id_p_len); data->state = FAILURE; return; } if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) { data->state = FAILURE; return; } wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)", resp->rand_p, EAP_PSK_RAND_LEN); os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN); /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; buf = os_malloc(buflen); if (buf == NULL) { data->state = FAILURE; return; } os_memcpy(buf, data->id_p, data->id_p_len); pos = buf + data->id_p_len; os_memcpy(pos, data->id_s, data->id_s_len); pos += data->id_s_len; os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); pos += EAP_PSK_RAND_LEN; os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); if (omac1_aes_128(data->ak, buf, buflen, mac)) { os_free(buf); data->state = FAILURE; return; } os_free(buf); wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P"); wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P", mac, EAP_PSK_MAC_LEN); data->state = FAILURE; return; } data->state = PSK_3; }