1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-FAST server (RFC 4851) 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 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "aes_wrap.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "sha1.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_tls_common.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "tls.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_common/eap_tlv_common.h" 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_common/eap_fast_common.h" 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_reset(struct eap_sm *sm, void *priv); 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Private PAC-Opaque TLV types */ 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define PAC_OPAQUE_TYPE_PAD 0 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define PAC_OPAQUE_TYPE_KEY 1 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define PAC_OPAQUE_TYPE_LIFETIME 2 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define PAC_OPAQUE_TYPE_IDENTITY 3 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_fast_data { 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_ssl_data ssl; 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum { 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt START, PHASE1, PHASE2_START, PHASE2_ID, PHASE2_METHOD, 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt CRYPTO_BINDING, REQUEST_PAC, SUCCESS, FAILURE 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } state; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int fast_version; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_method *phase2_method; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *phase2_priv; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int force_version; 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int peer_version; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 crypto_binding_nonce[32]; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int final_result; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_key_block_provisioning *key_block_p; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 simck[EAP_FAST_SIMCK_LEN]; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 cmk[EAP_FAST_CMK_LEN]; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int simck_idx; 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 pac_opaque_encr[16]; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *srv_id; 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t srv_id_len; 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *srv_id_info; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int anon_provisioning; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int send_new_pac; /* server triggered re-keying of Tunnel PAC */ 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *pending_phase2_resp; 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *identity; /* from PAC-Opaque */ 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t identity_len; 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int eap_seq; 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int tnc_started; 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pac_key_lifetime; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pac_key_refresh_time; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 76dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidtstatic int eap_fast_process_phase2_start(struct eap_sm *sm, 77dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct eap_fast_data *data); 78dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 79dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char * eap_fast_state_txt(int state) 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (state) { 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case START: 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "START"; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE1: 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "PHASE1"; 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_START: 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "PHASE2_START"; 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_ID: 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "PHASE2_ID"; 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_METHOD: 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "PHASE2_METHOD"; 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CRYPTO_BINDING: 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "CRYPTO_BINDING"; 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case REQUEST_PAC: 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "REQUEST_PAC"; 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case SUCCESS: 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "SUCCESS"; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FAILURE: 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "FAILURE"; 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "Unknown?!"; 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_state(struct eap_fast_data *data, int state) 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: %s -> %s", 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state_txt(data->state), 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state_txt(state)); 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = state; 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic EapType eap_fast_req_failure(struct eap_sm *sm, 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data) 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: send Result TLV(FAILURE) */ 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return EAP_TYPE_NONE; 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *client_random, 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *server_random, 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *master_secret) 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = ctx; 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pac_opaque; 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t pac_opaque_len; 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *buf, *pos, *end, *pac_key = NULL; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_time_t lifetime = 0; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *identity = NULL; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t identity_len = 0; 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)", 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ticket, len); 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) { 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid " 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "SessionTicket"); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque_len = WPA_GET_BE16(ticket + 2); 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque = ticket + 4; 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pac_opaque_len < 8 || pac_opaque_len % 8 || 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque_len > len - 4) { 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid PAC-Opaque " 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(len=%lu left=%lu)", 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) pac_opaque_len, 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len); 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-FAST: Received PAC-Opaque", 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque, pac_opaque_len); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(pac_opaque_len - 8); 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "for decrypting PAC-Opaque"); 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (aes_unwrap(data->pac_opaque_encr, (pac_opaque_len - 8) / 8, 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque, buf) < 0) { 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt " 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "PAC-Opaque"); 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This may have been caused by server changing the PAC-Opaque 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * encryption key, so just ignore this PAC-Opaque instead of 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * failing the authentication completely. Provisioning can now 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * be used to provision a new PAC. 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = buf + pac_opaque_len - 8; 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted PAC-Opaque", 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf, end - buf); 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = buf; 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (pos + 1 < end) { 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos + 2 + pos[1] > end) 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (*pos) { 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PAC_OPAQUE_TYPE_PAD: 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = end; 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PAC_OPAQUE_TYPE_KEY: 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos[1] != EAP_FAST_PAC_KEY_LEN) { 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "PAC-Key length %d", pos[1]); 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_key = pos + 2; 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key from " 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "decrypted PAC-Opaque", 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_key, EAP_FAST_PAC_KEY_LEN); 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PAC_OPAQUE_TYPE_LIFETIME: 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos[1] != 4) { 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "PAC-Key lifetime length %d", 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos[1]); 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt lifetime = WPA_GET_BE32(pos + 2); 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PAC_OPAQUE_TYPE_IDENTITY: 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt identity = pos + 2; 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt identity_len = pos[1]; 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2 + pos[1]; 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pac_key == NULL) { 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key included in " 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "PAC-Opaque"); 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (identity) { 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Identity from " 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "PAC-Opaque", identity, identity_len); 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->identity); 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->identity = os_malloc(identity_len); 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->identity) { 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->identity, identity, identity_len); 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->identity_len = identity_len; 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) { 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore " 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(lifetime=%ld now=%ld)", lifetime, now.sec); 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->send_new_pac = 2; 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Allow PAC to be used to allow a PAC update with some level 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * of server authentication (i.e., do not fall back to full TLS 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * handshake since we cannot be sure that the peer would be 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * able to validate server certificate now). However, reject 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * the authentication since the PAC was not valid anymore. Peer 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * can connect again with the newly provisioned PAC after this. 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (lifetime - now.sec < data->pac_key_refresh_time) { 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key soft timeout; send " 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "an update if authentication succeeds"); 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->send_new_pac = 1; 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_derive_master_secret(pac_key, server_random, client_random, 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt master_secret); 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 1; 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_derive_key_auth(struct eap_sm *sm, 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data) 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *sks; 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RFC 4851, Section 5.1: 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Extra key material after TLS key_block: session_key_seed[40] 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_FAST_SKS_LEN); 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sks == NULL) { 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "session_key_seed"); 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4851, Section 5.2: 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * S-IMCK[0] = session_key_seed 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sks, EAP_FAST_SKS_LEN); 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->simck_idx = 0; 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN); 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sks); 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_derive_key_provisioning(struct eap_sm *sm, 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data) 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->key_block_p); 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_block_p = (struct eap_fast_key_block_provisioning *) 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "key expansion", 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(*data->key_block_p)); 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->key_block_p == NULL) { 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4851, Section 5.2: 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * S-IMCK[0] = session_key_seed 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_block_p->session_key_seed, 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(data->key_block_p->session_key_seed)); 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->simck_idx = 0; 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->simck, data->key_block_p->session_key_seed, 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_FAST_SIMCK_LEN); 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge", 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_block_p->server_challenge, 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(data->key_block_p->server_challenge)); 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->key_block_p->client_challenge, 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(data->key_block_p->client_challenge)); 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_get_phase2_key(struct eap_sm *sm, 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *isk, size_t isk_len) 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *key; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t key_len; 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(isk, 0, isk_len); 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->phase2_method == NULL || data->phase2_priv == NULL) { 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "available"); 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->phase2_method->getKey == NULL) 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((key = data->phase2_method->getKey(sm, data->phase2_priv, 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &key_len)) == NULL) { 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key material " 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "from Phase 2"); 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_len > isk_len) 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_len = isk_len; 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key_len == 32 && 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method->vendor == EAP_VENDOR_IETF && 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method->method == EAP_TYPE_MSCHAPV2) { 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-FAST uses reverse order for MS-MPPE keys when deriving 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ISK for EAP-FAST cryptobinding. 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(isk, key + 16, 16); 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(isk + 16, key, 16); 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(isk, key, key_len); 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(key); 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_update_icmk(struct eap_sm *sm, struct eap_fast_data *data) 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 isk[32], imck[60]; 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Deriving ICMK[%d] (S-IMCK and CMK)", 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->simck_idx + 1); 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4851, Section 5.2: 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys", 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * MSK[j], 60) 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * S-IMCK[j] = first 40 octets of IMCK[j] 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * CMK[j] = last 20 octets of IMCK[j] 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0) 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk)); 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Inner Methods Compound Keys", 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt isk, sizeof(isk), imck, sizeof(imck)); 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->simck_idx++; 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN); 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]", 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->simck, EAP_FAST_SIMCK_LEN); 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN); 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->cmk, EAP_FAST_CMK_LEN); 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_fast_init(struct eap_sm *sm) 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data; 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 ciphers[5] = { 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt TLS_CIPHER_ANON_DH_AES128_SHA, 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt TLS_CIPHER_AES128_SHA, 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt TLS_CIPHER_RSA_DHE_AES128_SHA, 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt TLS_CIPHER_RC4_SHA, 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt TLS_CIPHER_NONE 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt }; 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fast_version = EAP_FAST_VERSION; 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->force_version = -1; 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->user && sm->user->force_version >= 0) { 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->force_version = sm->user->force_version; 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: forcing version %d", 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->force_version); 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fast_version = data->force_version; 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = START; 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tls_connection_set_cipher_list(sm->ssl_ctx, data->ssl.conn, 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ciphers) < 0) { 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to set TLS cipher " 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "suites"); 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn, 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_session_ticket_cb, 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data) < 0) { 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket " 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "callback"); 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->pac_opaque_encr_key == NULL) { 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No PAC-Opaque encryption key " 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "configured"); 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->pac_opaque_encr, sm->pac_opaque_encr_key, 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(data->pac_opaque_encr)); 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->eap_fast_a_id == NULL) { 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No A-ID configured"); 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->srv_id = os_malloc(sm->eap_fast_a_id_len); 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->srv_id == NULL) { 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->srv_id, sm->eap_fast_a_id, sm->eap_fast_a_id_len); 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->srv_id_len = sm->eap_fast_a_id_len; 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->eap_fast_a_id_info == NULL) { 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No A-ID-Info configured"); 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->srv_id_info = os_strdup(sm->eap_fast_a_id_info); 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->srv_id_info == NULL) { 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_reset(sm, data); 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC-Key lifetime in seconds (hard limit) */ 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pac_key_lifetime = sm->pac_key_lifetime; 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * PAC-Key refresh time in seconds (soft limit on remaining hard 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * limit). The server will generate a new PAC-Key when this number of 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * seconds (or fewer) of the lifetime remains. 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pac_key_refresh_time = sm->pac_key_refresh_time; 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_reset(struct eap_sm *sm, void *priv) 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->phase2_priv && data->phase2_method) 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_tls_ssl_deinit(sm, &data->ssl); 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->srv_id); 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->srv_id_info); 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->key_block_p); 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->pending_phase2_resp); 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->identity); 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_fast_build_start(struct eap_sm *sm, 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, u8 id) 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req; 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_FAST, 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1 + sizeof(struct pac_tlv_hdr) + data->srv_id_len, 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_REQUEST, id); 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) { 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-FAST: Failed to allocate memory for" 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " request"); 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->fast_version); 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* RFC 4851, 4.1.1. Authority ID Data */ 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, PHASE1); 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return req; 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_phase1_done(struct eap_sm *sm, struct eap_fast_data *data) 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char cipher[64]; 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Phase1 done, starting Phase2"); 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher)) 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt < 0) { 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to get cipher " 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "information"); 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->anon_provisioning = os_strstr(cipher, "ADH") != NULL; 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->anon_provisioning) { 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Anonymous provisioning"); 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_derive_key_provisioning(sm, data); 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_derive_key_auth(sm, data); 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, PHASE2_START); 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_fast_build_phase2_req(struct eap_sm *sm, 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 id) 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req; 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->phase2_priv == NULL) { 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "initialized"); 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = data->phase2_method->buildReq(sm, data->phase2_priv, id); 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-FAST: Phase 2 EAP-Request", req); 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_fast_tlv_eap_payload(req); 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_fast_build_crypto_binding( 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_sm *sm, struct eap_fast_data *data) 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *buf; 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tlv_result_tlv *result; 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tlv_crypto_binding_tlv *binding; 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = wpabuf_alloc(2 * sizeof(*result) + sizeof(*binding)); 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->send_new_pac || data->anon_provisioning || 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method) 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->final_result = 0; 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->final_result = 1; 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->final_result || data->eap_seq > 1) { 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Intermediate-Result */ 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Add Intermediate-Result TLV " 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(status=SUCCESS)"); 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result = wpabuf_put(buf, sizeof(*result)); 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result->tlv_type = host_to_be16( 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLV_TYPE_MANDATORY | 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLV_INTERMEDIATE_RESULT_TLV); 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result->length = host_to_be16(2); 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->final_result) { 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Result TLV */ 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV " 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(status=SUCCESS)"); 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result = wpabuf_put(buf, sizeof(*result)); 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLV_RESULT_TLV); 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result->length = host_to_be16(2); 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Crypto-Binding TLV */ 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding = wpabuf_put(buf, sizeof(*binding)); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLV_CRYPTO_BINDING_TLV); 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->length = host_to_be16(sizeof(*binding) - 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct eap_tlv_hdr)); 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->version = EAP_FAST_VERSION; 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->received_version = data->peer_version; 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST; 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(binding->nonce, sizeof(binding->nonce)) < 0) { 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(buf); 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4851, Section 4.2.8: 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * The nonce in a request MUST have its least significant bit set to 0. 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->nonce[sizeof(binding->nonce) - 1] &= ~0x01; 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->crypto_binding_nonce, binding->nonce, 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(binding->nonce)); 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 4851, Section 5.3: 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * CMK = CMK[j] 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Compound-MAC = HMAC-SHA1( CMK, Crypto-Binding TLV ) 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) binding, sizeof(*binding), 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->compound_mac); 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Add Crypto-Binding TLV: Version %d " 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Received Version %d SubType %d", 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->version, binding->received_version, 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->subtype); 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->nonce, sizeof(binding->nonce)); 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt binding->compound_mac, sizeof(binding->compound_mac)); 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return buf; 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_fast_build_pac(struct eap_sm *sm, 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data) 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 pac_key[EAP_FAST_PAC_KEY_LEN]; 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pac_buf, *pac_opaque; 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *buf; 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos; 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buf_len, srv_id_info_len, pac_len; 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tlv_hdr *pac_tlv; 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct pac_tlv_hdr *pac_info; 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tlv_result_tlv *result; 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 || 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now) < 0) 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key", 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_key, EAP_FAST_PAC_KEY_LEN); 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) + 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (2 + sm->identity_len) + 8; 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_buf = os_malloc(pac_len); 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pac_buf == NULL) 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt srv_id_info_len = os_strlen(data->srv_id_info); 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = pac_buf; 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = PAC_OPAQUE_TYPE_KEY; 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = EAP_FAST_PAC_KEY_LEN; 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN); 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += EAP_FAST_PAC_KEY_LEN; 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = PAC_OPAQUE_TYPE_LIFETIME; 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = 4; 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime); 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 4; 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->identity) { 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = PAC_OPAQUE_TYPE_IDENTITY; 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = sm->identity_len; 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(pos, sm->identity, sm->identity_len); 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += sm->identity_len; 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_len = pos - pac_buf; 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (pac_len % 8) { 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *pos++ = PAC_OPAQUE_TYPE_PAD; 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_len++; 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque = os_malloc(pac_len + 8); 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pac_opaque == NULL) { 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pac_buf); 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf, 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque) < 0) { 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pac_buf); 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pac_opaque); 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pac_buf); 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_len += 8; 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_opaque, pac_len); 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len = sizeof(*pac_tlv) + 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN + 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct pac_tlv_hdr) + pac_len + 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->srv_id_len + srv_id_info_len + 100 + sizeof(*result); 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = wpabuf_alloc(buf_len); 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf == NULL) { 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pac_opaque); 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Result TLV */ 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)"); 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt result = wpabuf_put(buf, sizeof(*result)); 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16((u8 *) &result->tlv_type, 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV); 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16((u8 *) &result->length, 2); 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS); 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC TLV */ 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV"); 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv)); 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLV_PAC_TLV); 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC-Key */ 775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN); 776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC-Opaque */ 778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len); 779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(pac_opaque); 780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC-Info */ 782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_info = wpabuf_put(buf, sizeof(*pac_info)); 783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO); 784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC-Lifetime (inside PAC-Info) */ 786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4); 787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime); 788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* A-ID (inside PAC-Info) */ 790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Note: headers may be misaligned after A-ID */ 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* A-ID-Info (inside PAC-Info) */ 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info, 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt srv_id_info_len); 797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PAC-Type (inside PAC-Info) */ 799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2); 800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC); 801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Update PAC-Info and PAC TLV Length fields */ 803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = wpabuf_put(buf, 0); 804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1)); 805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1)); 806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return buf; 808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 811dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidtstatic int eap_fast_encrypt_phase2(struct eap_sm *sm, 812dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct eap_fast_data *data, 813dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct wpabuf *plain, int piggyback) 814dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt{ 815dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct wpabuf *encr; 816dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 817dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs", 818dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt plain); 819dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain), 820dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpabuf_len(plain)); 821dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpabuf_free(plain); 822dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 823dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (data->ssl.out_buf && piggyback) { 824dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Piggyback Phase 2 data " 825dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt "(len=%d) with last Phase 1 Message (len=%d " 826dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt "used=%d)", 827dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt (int) wpabuf_len(encr), 828dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt (int) wpabuf_len(data->ssl.out_buf), 829dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt (int) data->ssl.out_used); 830dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(encr)) < 0) { 831dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-FAST: Failed to resize " 832dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt "output buffer"); 833dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpabuf_free(encr); 834dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt return -1; 835dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } 836dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpabuf_put_buf(data->ssl.out_buf, encr); 837dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpabuf_free(encr); 838dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } else { 839dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpabuf_free(data->ssl.out_buf); 840dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt data->ssl.out_used = 0; 841dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt data->ssl.out_buf = encr; 842dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } 843dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 844dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt return 0; 845dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt} 846dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 847dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) 849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req = NULL; 852dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt int piggyback = 0; 853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ssl.state == FRAG_ACK) { 855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_server_tls_build_ack(id, EAP_TYPE_FAST, 856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fast_version); 857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ssl.state == WAIT_FRAG_ACK) { 860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, 861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fast_version, id); 862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case START: 866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_fast_build_start(sm, data, id); 867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE1: 868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_fast_phase1_done(sm, data) < 0) 870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 871dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (data->state == PHASE2_START) { 872dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt /* 873dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt * Try to generate Phase 2 data to piggyback 874dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt * with the end of Phase 1 to avoid extra 875dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt * roundtrip. 876dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt */ 877dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Try to start " 878dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt "Phase 2"); 879dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (eap_fast_process_phase2_start(sm, data)) 880dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt break; 881dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt req = eap_fast_build_phase2_req(sm, data, id); 882dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt piggyback = 1; 883dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } 884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_ID: 887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_METHOD: 888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_fast_build_phase2_req(sm, data, id); 889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CRYPTO_BINDING: 891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_fast_build_crypto_binding(sm, data); 892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->phase2_method) { 893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Include the start of the next EAP method in the 895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * sequence in the same message with Crypto-Binding to 896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * save a round-trip. 897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *eap; 899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_fast_build_phase2_req(sm, data, id); 900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = wpabuf_concat(req, eap); 901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, PHASE2_METHOD); 902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case REQUEST_PAC: 905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_fast_build_pac(sm, data); 906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d", 909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, data->state); 910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 913dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (req && 914dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt eap_fast_encrypt_phase2(sm, data, req, piggyback) < 0) 915dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt return NULL; 916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, 918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fast_version, id); 919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_fast_check(struct eap_sm *sm, void *priv, 923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData, &len); 929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < 1) { 930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame"); 931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return TRUE; 932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return FALSE; 935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_phase2_init(struct eap_sm *sm, struct eap_fast_data *data, 939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EapType eap_type) 940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->phase2_priv && data->phase2_method) { 942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method = NULL; 944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_priv = NULL; 945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, 947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_type); 948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->phase2_method) 949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->key_block_p) { 952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->auth_challenge = data->key_block_p->server_challenge; 953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->peer_challenge = data->key_block_p->client_challenge; 954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->init_phase2 = 1; 956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2_priv = data->phase2_method->init(sm); 957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->init_phase2 = 0; 958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->auth_challenge = NULL; 959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->peer_challenge = NULL; 960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->phase2_priv == NULL ? -1 : 0; 962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_process_phase2_response(struct eap_sm *sm, 966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, 967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *in_data, size_t in_len) 968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 next_type = EAP_TYPE_NONE; 970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_hdr *hdr; 971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos; 972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t left; 973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf buf; 974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_method *m = data->phase2_method; 975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *priv = data->phase2_priv; 976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (priv == NULL) { 978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: %s - Phase2 not " 979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "initialized?!", __func__); 980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = (struct eap_hdr *) in_data; 984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (u8 *) (hdr + 1); 985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt left = in_len - sizeof(*hdr); 988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; " 989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "allowed types", pos + 1, left - 1); 990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef EAP_TNC 991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (m && m->vendor == EAP_VENDOR_IETF && 992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt m->method == EAP_TYPE_TNC) { 993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required " 994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "TNC negotiation"); 995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = eap_fast_req_failure(sm, data); 996526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_phase2_init(sm, data, next_type); 997526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 999526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* EAP_TNC */ 1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_process_nak(sm, pos + 1, left - 1); 1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->user->methods[sm->user_eap_method_index].method != 1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TYPE_NONE) { 1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = sm->user->methods[ 1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->user_eap_method_index++].method; 1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", 1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type); 1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = eap_fast_req_failure(sm, data); 1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_phase2_init(sm, data, next_type); 1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_set(&buf, in_data, in_len); 1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (m->check(sm, priv, &buf)) { 1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 check() asked to " 1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "ignore the packet"); 1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = eap_fast_req_failure(sm, data); 1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt m->process(sm, priv, &buf); 1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!m->isDone(sm, priv)) 1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!m->isSuccess(sm, priv)) { 1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method failed"); 1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = eap_fast_req_failure(sm, data); 1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_phase2_init(sm, data, next_type); 1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_ID: 1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Phase2 " 1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Identity not found in the user " 1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "database", 1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity, sm->identity_len); 1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = eap_fast_req_failure(sm, data); 1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, PHASE2_METHOD); 1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->anon_provisioning) { 1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Only EAP-MSCHAPv2 is allowed for anonymous 1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * provisioning. 1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = EAP_TYPE_MSCHAPV2; 1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->user_eap_method_index = 0; 1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = sm->user->methods[0].method; 1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->user_eap_method_index = 1; 1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", next_type); 1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_METHOD: 1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CRYPTO_BINDING: 1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_update_icmk(sm, data); 1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, CRYPTO_BINDING); 1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->eap_seq++; 1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = EAP_TYPE_NONE; 1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef EAP_TNC 1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->tnc && !data->tnc_started) { 1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC"); 1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = EAP_TYPE_TNC; 1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->tnc_started = 1; 1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* EAP_TNC */ 1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FAILURE: 1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d", 1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, data->state); 1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1083526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_phase2_init(sm, data, next_type); 1084526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1085526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1086526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1087526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_process_phase2_eap(struct eap_sm *sm, 1088526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, 1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *in_data, size_t in_len) 1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_hdr *hdr; 1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hdr = (struct eap_hdr *) in_data; 1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (in_len < (int) sizeof(*hdr)) { 1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " 1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP frame (len=%lu)", (unsigned long) in_len); 1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_req_failure(sm, data); 1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = be_to_host16(hdr->length); 1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len > in_len) { 1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Length mismatch in " 1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) in_len, (unsigned long) len); 1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_req_failure(sm, data); 1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: code=%d " 1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "identifier=%d length=%lu", hdr->code, hdr->identifier, 1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len); 1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (hdr->code) { 1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case EAP_CODE_RESPONSE: 1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_phase2_response(sm, data, (u8 *) hdr, len); 1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " 1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Phase 2 EAP header", hdr->code); 1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_parse_tlvs(u8 *data, size_t data_len, 1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_tlv_parse *tlv) 1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int mandatory, tlv_type, len, res; 1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *pos, *end; 1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(tlv, 0, sizeof(*tlv)); 1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = data; 1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = data + data_len; 1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (pos + 4 < end) { 1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mandatory = pos[0] & 0x80; 1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv_type = WPA_GET_BE16(pos) & 0x3fff; 1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = WPA_GET_BE16(pos); 1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos + len > end) { 1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); 1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " 1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "TLV type %d length %d%s", 1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv_type, len, mandatory ? " (mandatory)" : ""); 1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); 1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res == -2) 1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) { 1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (mandatory) { 1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " 1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "mandatory TLV type %d", tlv_type); 1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: generate Nak TLV */ 1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored " 1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "unknown optional TLV type %d", 1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv_type); 1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += len; 1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_validate_crypto_binding( 1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, struct eap_tlv_crypto_binding_tlv *b, 1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t bind_len) 1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 cmac[SHA1_MAC_LEN]; 1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: " 1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Version %d Received Version %d SubType %d", 1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->version, b->received_version, b->subtype); 1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", 1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->nonce, sizeof(b->nonce)); 1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", 1183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->compound_mac, sizeof(b->compound_mac)); 1184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (b->version != EAP_FAST_VERSION || 1186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->received_version != EAP_FAST_VERSION) { 1187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected version " 1188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in Crypto-Binding: version %d " 1189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "received_version %d", b->version, 1190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->received_version); 1191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (b->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE) { 1195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected subtype in " 1196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Crypto-Binding: %d", b->subtype); 1197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(data->crypto_binding_nonce, b->nonce, 31) != 0 || 1201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (data->crypto_binding_nonce[31] | 1) != b->nonce[31]) { 1202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid nonce in " 1203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Crypto-Binding"); 1204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(cmac, b->compound_mac, sizeof(cmac)); 1208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(b->compound_mac, 0, sizeof(cmac)); 1209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for " 1210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Compound MAC calculation", 1211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (u8 *) b, bind_len); 1212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, (u8 *) b, bind_len, 1213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->compound_mac); 1214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_memcmp(cmac, b->compound_mac, sizeof(cmac)) != 0) { 1215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, 1216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP-FAST: Calculated Compound MAC", 1217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt b->compound_mac, sizeof(cmac)); 1218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not " 1219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "match"); 1220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_pac_type(u8 *pac, size_t len, u16 type) 1228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tlv_pac_type_tlv *tlv; 1230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pac == NULL || len != sizeof(*tlv)) 1232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv = (struct eap_tlv_pac_type_tlv *) pac; 1235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return be_to_host16(tlv->tlv_type) == PAC_TYPE_PAC_TYPE && 1237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt be_to_host16(tlv->length) == 2 && 1238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt be_to_host16(tlv->pac_type) == type; 1239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_process_phase2_tlvs(struct eap_sm *sm, 1243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, 1244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *in_data, size_t in_len) 1245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_tlv_parse tlv; 1247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int check_crypto_binding = data->state == CRYPTO_BINDING; 1248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_fast_parse_tlvs(in_data, in_len, &tlv) < 0) { 1250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received " 1251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Phase 2 TLVs"); 1252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tlv.result == EAP_TLV_RESULT_FAILURE) { 1256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Result TLV indicated " 1257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "failure"); 1258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == REQUEST_PAC) { 1263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 type, len, res; 1264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tlv.pac == NULL || tlv.pac_len < 6) { 1265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC " 1266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Acknowledgement received"); 1267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt type = WPA_GET_BE16(tlv.pac); 1272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = WPA_GET_BE16(tlv.pac + 2); 1273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = WPA_GET_BE16(tlv.pac + 4); 1274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (type != PAC_TYPE_PAC_ACKNOWLEDGEMENT || len != 2 || 1276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res != EAP_TLV_RESULT_SUCCESS) { 1277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV did not " 1278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "contain acknowledgement"); 1279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Acknowledgement received " 1284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "- PAC provisioning succeeded"); 1285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, (data->anon_provisioning || 1286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->send_new_pac == 2) ? 1287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt FAILURE : SUCCESS); 1288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (check_crypto_binding) { 1292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tlv.crypto_binding == NULL) { 1293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: No Crypto-Binding " 1294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "TLV received"); 1295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->final_result && 1300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv.result != EAP_TLV_RESULT_SUCCESS) { 1301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " 1302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "without Success Result"); 1303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->final_result && 1308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv.iresult != EAP_TLV_RESULT_SUCCESS) { 1309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " 1310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "without intermediate Success Result"); 1311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_fast_validate_crypto_binding(data, tlv.crypto_binding, 1316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv.crypto_binding_len)) { 1317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Valid Crypto-Binding TLV " 1322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "received"); 1323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->final_result) { 1324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication " 1325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "completed successfully"); 1326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->anon_provisioning && 1329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->eap_fast_prov != ANON_PROV && 1330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->eap_fast_prov != BOTH_PROV) { 1331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " 1332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "use unauthenticated provisioning which is " 1333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "disabled"); 1334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->eap_fast_prov != AUTH_PROV && 1339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->eap_fast_prov != BOTH_PROV && 1340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && 1341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_pac_type(tlv.pac, tlv.pac_len, 1342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt PAC_TYPE_TUNNEL_PAC)) { 1343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " 1344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "use authenticated provisioning which is " 1345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "disabled"); 1346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->anon_provisioning || 1351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && 1352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_pac_type(tlv.pac, tlv.pac_len, 1353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt PAC_TYPE_TUNNEL_PAC))) { 1354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Requested a new " 1355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Tunnel PAC"); 1356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, REQUEST_PAC); 1357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (data->send_new_pac) { 1358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Server triggered " 1359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "re-keying of Tunnel PAC"); 1360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, REQUEST_PAC); 1361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (data->final_result) 1362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, SUCCESS); 1363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tlv.eap_payload_tlv) { 1366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_phase2_eap(sm, data, tlv.eap_payload_tlv, 1367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tlv.eap_payload_tlv_len); 1368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_process_phase2(struct eap_sm *sm, 1373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data, 1374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *in_buf) 1375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *in_decrypted; 1377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int len_decrypted; 1378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buf_len; 1379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *in_data; 1380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t in_len; 1381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt in_data = wpabuf_mhead(in_buf); 1383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt in_len = wpabuf_len(in_buf); 1384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for" 1386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " Phase 2", (unsigned long) in_len); 1387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->pending_phase2_resp) { 1389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " 1390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "skip decryption and use old data"); 1391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_phase2_tlvs( 1392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm, data, wpabuf_mhead(data->pending_phase2_resp), 1393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_len(data->pending_phase2_resp)); 1394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->pending_phase2_resp); 1395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pending_phase2_resp = NULL; 1396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len = in_len; 1400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 1401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Even though we try to disable TLS compression, it is possible that 1402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * this cannot be done with all TLS libraries. Add extra buffer space 1403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * to handle the possibility of the decrypted data being longer than 1404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * input data. 1405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 1406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len += 500; 1407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf_len *= 3; 1408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt in_decrypted = os_malloc(buf_len); 1409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (in_decrypted == NULL) { 1410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "EAP-FAST: Failed to allocate memory " 1411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "for decryption"); 1412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 1416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt in_data, in_len, 1417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt in_decrypted, buf_len); 1418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len_decrypted < 0) { 1419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 " 1420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "data"); 1421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(in_decrypted); 1422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs", 1427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt in_decrypted, len_decrypted); 1428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_phase2_tlvs(sm, data, in_decrypted, len_decrypted); 1430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->method_pending == METHOD_PENDING_WAIT) { 1432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in " 1433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "pending wait state - save decrypted response"); 1434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->pending_phase2_resp); 1435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pending_phase2_resp = wpabuf_alloc_copy(in_decrypted, 1436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len_decrypted); 1437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(in_decrypted); 1440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_process_version(struct eap_sm *sm, void *priv, 1444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int peer_version) 1445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->peer_version = peer_version; 1449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->force_version >= 0 && peer_version != data->force_version) { 1451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: peer did not select the forced" 1452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " version (forced=%d peer=%d) - reject", 1453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->force_version, peer_version); 1454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (peer_version < data->fast_version) { 1458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: peer ver=%d, own ver=%d; " 1459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "use version %d", 1460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peer_version, data->fast_version, peer_version); 1461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fast_version = peer_version; 1462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_fast_process_phase1(struct eap_sm *sm, 1469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data) 1470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_server_tls_phase1(sm, &data->ssl) < 0) { 1472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: TLS processing failed"); 1473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) || 1478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_len(data->ssl.out_buf) > 0) 1479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 1; 1480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 1482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Phase 1 was completed with the received message (e.g., when using 1483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * abbreviated handshake), so Phase 2 can be started immediately 1484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * without having to send through an empty message to the peer. 1485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 1486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_fast_phase1_done(sm, data); 1488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1491dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidtstatic int eap_fast_process_phase2_start(struct eap_sm *sm, 1492dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt struct eap_fast_data *data) 1493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 next_type; 1495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->identity) { 1497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sm->identity); 1498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity = data->identity; 1499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->identity = NULL; 1500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity_len = data->identity_len; 1501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->identity_len = 0; 1502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->require_identity_match = 1; 1503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 1504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: " 1505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Phase2 Identity not found " 1506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in the user database", 1507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity, sm->identity_len); 1508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = eap_fast_req_failure(sm, data); 1509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Identity already " 1511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "known - skip Phase 2 Identity Request"); 1512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = sm->user->methods[0].method; 1513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->user_eap_method_index = 1; 1514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, PHASE2_METHOD); 1517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 1518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, PHASE2_ID); 1519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next_type = EAP_TYPE_IDENTITY; 1520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1522dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt return eap_fast_phase2_init(sm, data, next_type); 1523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_process_msg(struct eap_sm *sm, void *priv, 1527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *respData) 1528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 1532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE1: 1533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_fast_process_phase1(sm, data)) 1534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* fall through to PHASE2_START */ 1537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_START: 1538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_phase2_start(sm, data); 1539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_ID: 1541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case PHASE2_METHOD: 1542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CRYPTO_BINDING: 1543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case REQUEST_PAC: 1544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_phase2(sm, data, data->ssl.in_buf); 1545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 1547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected state %d in %s", 1548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state, __func__); 1549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 1550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_fast_process(struct eap_sm *sm, void *priv, 1555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 1556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_server_tls_process(sm, &data->ssl, respData, data, 1559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TYPE_FAST, eap_fast_process_version, 1560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_process_msg) < 0) 1561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_state(data, FAILURE); 1562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_fast_isDone(struct eap_sm *sm, void *priv) 1566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 1569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) 1573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *eapKeyData; 1576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != SUCCESS) 1578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapKeyData = os_malloc(EAP_FAST_KEY_LEN); 1581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eapKeyData == NULL) 1582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_derive_eap_msk(data->simck, eapKeyData); 1585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = EAP_FAST_KEY_LEN; 1586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eapKeyData; 1588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 1592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *eapKeyData; 1595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != SUCCESS) 1597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapKeyData = os_malloc(EAP_EMSK_LEN); 1600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eapKeyData == NULL) 1601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_fast_derive_eap_emsk(data->simck, eapKeyData); 1604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = EAP_EMSK_LEN; 1605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eapKeyData; 1607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_fast_isSuccess(struct eap_sm *sm, void *priv) 1611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_fast_data *data = priv; 1613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == SUCCESS; 1614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_server_fast_register(void) 1618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 1620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 1621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST"); 1624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 1625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_fast_init; 1628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->reset = eap_fast_reset; 1629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->buildReq = eap_fast_buildReq; 1630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->check = eap_fast_check; 1631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_fast_process; 1632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isDone = eap_fast_isDone; 1633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->getKey = eap_fast_getKey; 1634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->get_emsk = eap_fast_get_emsk; 1635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isSuccess = eap_fast_isSuccess; 1636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_server_method_register(eap); 1638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 1639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_method_free(eap); 1640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 1641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1642