1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd / EAP-TLS (RFC 2716) 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 "eap_i.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_tls_common.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "tls.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_tls_reset(struct eap_sm *sm, void *priv); 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_tls_data { 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_ssl_data ssl; 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum { START, CONTINUE, SUCCESS, FAILURE } state; 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int established; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char * eap_tls_state_txt(int state) 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (state) { 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case START: 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "START"; 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CONTINUE: 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "CONTINUE"; 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case SUCCESS: 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "SUCCESS"; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FAILURE: 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "FAILURE"; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "Unknown?!"; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_tls_state(struct eap_tls_data *data, int state) 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s", 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state_txt(data->state), 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state_txt(state)); 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = state; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_tls_init(struct eap_sm *sm) 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = START; 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) { 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_reset(sm, data); 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_tls_reset(struct eap_sm *sm, void *priv) 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_tls_ssl_deinit(sm, &data->ssl); 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_tls_build_start(struct eap_sm *sm, 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data, u8 id) 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req; 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST, 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id); 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) { 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for " 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "request"); 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state(data, FAILURE); 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(req, EAP_TLS_FLAGS_START); 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state(data, CONTINUE); 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return req; 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id) 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *res; 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ssl.state == FRAG_ACK) { 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0); 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ssl.state == WAIT_FRAG_ACK) { 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto check_established; 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case START: 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_tls_build_start(sm, data, id); 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CONTINUE: 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->established = 1; 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d", 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, data->state); 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id); 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtcheck_established: 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->established && data->ssl.state != WAIT_FRAG_ACK) { 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TLS handshake has been completed and there are no more 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * fragments waiting to be sent out. */ 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state(data, SUCCESS); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return res; 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_tls_check(struct eap_sm *sm, void *priv, 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len); 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < 1) { 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return TRUE; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return FALSE; 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_tls_process_msg(struct eap_sm *sm, void *priv, 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *respData) 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == SUCCESS && wpabuf_len(data->ssl.in_buf) == 0) { 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS " 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "handshake message"); 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_server_tls_phase1(sm, &data->ssl) < 0) 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state(data, FAILURE); 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_tls_process(struct eap_sm *sm, void *priv, 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_server_tls_process(sm, &data->ssl, respData, data, 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TYPE_TLS, NULL, eap_tls_process_msg) < 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_tls_state(data, FAILURE); 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_tls_isDone(struct eap_sm *sm, void *priv) 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *eapKeyData; 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != SUCCESS) 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "client EAP encryption", 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLS_KEY_LEN); 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eapKeyData) { 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = EAP_TLS_KEY_LEN; 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key", 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapKeyData, EAP_TLS_KEY_LEN); 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key"); 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eapKeyData; 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *eapKeyData, *emsk; 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state != SUCCESS) 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "client EAP encryption", 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_TLS_KEY_LEN + EAP_EMSK_LEN); 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eapKeyData) { 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt emsk = os_malloc(EAP_EMSK_LEN); 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (emsk) 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN, 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_EMSK_LEN); 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(eapKeyData); 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt emsk = NULL; 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (emsk) { 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = EAP_EMSK_LEN; 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK", 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt emsk, EAP_EMSK_LEN); 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK"); 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return emsk; 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv) 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_tls_data *data = priv; 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == SUCCESS; 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_server_tls_register(void) 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_tls_init; 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->reset = eap_tls_reset; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->buildReq = eap_tls_buildReq; 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->check = eap_tls_check; 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_tls_process; 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isDone = eap_tls_isDone; 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->getKey = eap_tls_getKey; 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isSuccess = eap_tls_isSuccess; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->get_emsk = eap_tls_get_emsk; 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_server_method_register(eap); 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_method_free(eap); 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 287