LCOV - code coverage report
Current view: top level - src/eap_peer - eap_tls.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 181 214 84.6 %
Date: 2015-09-27 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP peer method: EAP-TLS (RFC 2716)
       3             :  * Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "crypto/tls.h"
      13             : #include "eap_i.h"
      14             : #include "eap_tls_common.h"
      15             : #include "eap_config.h"
      16             : 
      17             : 
      18             : static void eap_tls_deinit(struct eap_sm *sm, void *priv);
      19             : 
      20             : 
      21             : struct eap_tls_data {
      22             :         struct eap_ssl_data ssl;
      23             :         u8 *key_data;
      24             :         u8 *session_id;
      25             :         size_t id_len;
      26             :         void *ssl_ctx;
      27             :         u8 eap_type;
      28             : };
      29             : 
      30             : 
      31          45 : static void * eap_tls_init(struct eap_sm *sm)
      32             : {
      33             :         struct eap_tls_data *data;
      34          45 :         struct eap_peer_config *config = eap_get_config(sm);
      35          91 :         if (config == NULL ||
      36          90 :             ((sm->init_phase2 ? config->private_key2 : config->private_key)
      37          44 :              == NULL &&
      38           0 :              (sm->init_phase2 ? config->engine2 : config->engine) == 0)) {
      39           0 :                 wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured");
      40           0 :                 return NULL;
      41             :         }
      42             : 
      43          45 :         data = os_zalloc(sizeof(*data));
      44          45 :         if (data == NULL)
      45           0 :                 return NULL;
      46             : 
      47          45 :         data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
      48             :                 sm->ssl_ctx;
      49             : 
      50          45 :         if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) {
      51           5 :                 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
      52           5 :                 eap_tls_deinit(sm, data);
      53           5 :                 if (config->engine) {
      54           0 :                         wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
      55             :                                    "PIN");
      56           0 :                         eap_sm_request_pin(sm);
      57           0 :                         sm->ignore = TRUE;
      58           5 :                 } else if (config->private_key && !config->private_key_passwd)
      59             :                 {
      60           5 :                         wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
      61             :                                    "key passphrase");
      62           5 :                         eap_sm_request_passphrase(sm);
      63           5 :                         sm->ignore = TRUE;
      64             :                 }
      65           5 :                 return NULL;
      66             :         }
      67             : 
      68          40 :         data->eap_type = EAP_TYPE_TLS;
      69             : 
      70          40 :         return data;
      71             : }
      72             : 
      73             : 
      74             : #ifdef EAP_UNAUTH_TLS
      75           1 : static void * eap_unauth_tls_init(struct eap_sm *sm)
      76             : {
      77             :         struct eap_tls_data *data;
      78           1 :         struct eap_peer_config *config = eap_get_config(sm);
      79             : 
      80           1 :         data = os_zalloc(sizeof(*data));
      81           1 :         if (data == NULL)
      82           0 :                 return NULL;
      83             : 
      84           1 :         data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
      85             :                 sm->ssl_ctx;
      86             : 
      87           1 :         if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
      88             :                                   EAP_UNAUTH_TLS_TYPE)) {
      89           0 :                 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
      90           0 :                 eap_tls_deinit(sm, data);
      91           0 :                 return NULL;
      92             :         }
      93             : 
      94           1 :         data->eap_type = EAP_UNAUTH_TLS_TYPE;
      95             : 
      96           1 :         return data;
      97             : }
      98             : #endif /* EAP_UNAUTH_TLS */
      99             : 
     100             : 
     101             : #ifdef CONFIG_HS20
     102           2 : static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
     103             : {
     104             :         struct eap_tls_data *data;
     105           2 :         struct eap_peer_config *config = eap_get_config(sm);
     106             : 
     107           2 :         data = os_zalloc(sizeof(*data));
     108           2 :         if (data == NULL)
     109           0 :                 return NULL;
     110             : 
     111           2 :         data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
     112             :                 sm->ssl_ctx;
     113             : 
     114           2 :         if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
     115             :                                   EAP_WFA_UNAUTH_TLS_TYPE)) {
     116           0 :                 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
     117           0 :                 eap_tls_deinit(sm, data);
     118           0 :                 return NULL;
     119             :         }
     120             : 
     121           2 :         data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE;
     122             : 
     123           2 :         return data;
     124             : }
     125             : #endif /* CONFIG_HS20 */
     126             : 
     127             : 
     128         103 : static void eap_tls_free_key(struct eap_tls_data *data)
     129             : {
     130         103 :         if (data->key_data) {
     131          45 :                 bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
     132          45 :                 data->key_data = NULL;
     133             :         }
     134         103 : }
     135             : 
     136             : 
     137          48 : static void eap_tls_deinit(struct eap_sm *sm, void *priv)
     138             : {
     139          48 :         struct eap_tls_data *data = priv;
     140          48 :         if (data == NULL)
     141          48 :                 return;
     142          48 :         eap_peer_tls_ssl_deinit(sm, &data->ssl);
     143          48 :         eap_tls_free_key(data);
     144          48 :         os_free(data->session_id);
     145          48 :         os_free(data);
     146             : }
     147             : 
     148             : 
     149           7 : static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
     150             :                                        struct eap_tls_data *data,
     151             :                                        struct eap_method_ret *ret, int res,
     152             :                                        struct wpabuf *resp, u8 id)
     153             : {
     154           7 :         wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
     155             : 
     156           7 :         ret->methodState = METHOD_DONE;
     157           7 :         ret->decision = DECISION_FAIL;
     158             : 
     159           7 :         if (resp) {
     160             :                 /*
     161             :                  * This is likely an alert message, so send it instead of just
     162             :                  * ACKing the error.
     163             :                  */
     164           7 :                 return resp;
     165             :         }
     166             : 
     167           0 :         return eap_peer_tls_build_ack(id, data->eap_type, 0);
     168             : }
     169             : 
     170             : 
     171          45 : static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
     172             :                             struct eap_method_ret *ret)
     173             : {
     174          45 :         wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
     175             : 
     176          45 :         ret->methodState = METHOD_DONE;
     177          45 :         ret->decision = DECISION_UNCOND_SUCC;
     178             : 
     179          45 :         eap_tls_free_key(data);
     180          45 :         data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
     181             :                                                  "client EAP encryption",
     182             :                                                  EAP_TLS_KEY_LEN +
     183             :                                                  EAP_EMSK_LEN);
     184          45 :         if (data->key_data) {
     185          45 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
     186          45 :                                 data->key_data, EAP_TLS_KEY_LEN);
     187          45 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK",
     188          45 :                                 data->key_data + EAP_TLS_KEY_LEN,
     189             :                                 EAP_EMSK_LEN);
     190             :         } else {
     191           0 :                 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
     192             :         }
     193             : 
     194          45 :         os_free(data->session_id);
     195          45 :         data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
     196             :                                                           EAP_TYPE_TLS,
     197             :                                                           &data->id_len);
     198          45 :         if (data->session_id) {
     199          90 :                 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id",
     200          45 :                             data->session_id, data->id_len);
     201             :         } else {
     202           0 :                 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id");
     203             :         }
     204          45 : }
     205             : 
     206             : 
     207         221 : static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
     208             :                                        struct eap_method_ret *ret,
     209             :                                        const struct wpabuf *reqData)
     210             : {
     211             :         size_t left;
     212             :         int res;
     213             :         struct wpabuf *resp;
     214             :         u8 flags, id;
     215             :         const u8 *pos;
     216         221 :         struct eap_tls_data *data = priv;
     217             :         struct wpabuf msg;
     218             : 
     219         221 :         pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
     220             :                                         reqData, &left, &flags);
     221         221 :         if (pos == NULL)
     222           0 :                 return NULL;
     223         221 :         id = eap_get_id(reqData);
     224             : 
     225         221 :         if (flags & EAP_TLS_FLAGS_START) {
     226          53 :                 wpa_printf(MSG_DEBUG, "EAP-TLS: Start");
     227          53 :                 left = 0; /* make sure that this frame is empty, even though it
     228             :                            * should always be, anyway */
     229             :         }
     230             : 
     231         221 :         resp = NULL;
     232         221 :         wpabuf_set(&msg, pos, left);
     233         221 :         res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0,
     234             :                                           id, &msg, &resp);
     235             : 
     236         221 :         if (res < 0) {
     237           7 :                 return eap_tls_failure(sm, data, ret, res, resp, id);
     238             :         }
     239             : 
     240         214 :         if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
     241          45 :                 eap_tls_success(sm, data, ret);
     242             : 
     243         214 :         if (res == 1) {
     244          81 :                 wpabuf_free(resp);
     245          81 :                 return eap_peer_tls_build_ack(id, data->eap_type, 0);
     246             :         }
     247             : 
     248         133 :         return resp;
     249             : }
     250             : 
     251             : 
     252          22 : static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
     253             : {
     254          22 :         struct eap_tls_data *data = priv;
     255          22 :         return tls_connection_established(data->ssl_ctx, data->ssl.conn);
     256             : }
     257             : 
     258             : 
     259          13 : static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
     260             : {
     261          13 : }
     262             : 
     263             : 
     264          10 : static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
     265             : {
     266          10 :         struct eap_tls_data *data = priv;
     267          10 :         eap_tls_free_key(data);
     268          10 :         os_free(data->session_id);
     269          10 :         data->session_id = NULL;
     270          10 :         if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
     271           0 :                 os_free(data);
     272           0 :                 return NULL;
     273             :         }
     274          10 :         return priv;
     275             : }
     276             : 
     277             : 
     278          41 : static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf,
     279             :                               size_t buflen, int verbose)
     280             : {
     281          41 :         struct eap_tls_data *data = priv;
     282          41 :         return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
     283             : }
     284             : 
     285             : 
     286         211 : static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv)
     287             : {
     288         211 :         struct eap_tls_data *data = priv;
     289         211 :         return data->key_data != NULL;
     290             : }
     291             : 
     292             : 
     293          43 : static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
     294             : {
     295          43 :         struct eap_tls_data *data = priv;
     296             :         u8 *key;
     297             : 
     298          43 :         if (data->key_data == NULL)
     299           0 :                 return NULL;
     300             : 
     301          43 :         key = os_malloc(EAP_TLS_KEY_LEN);
     302          43 :         if (key == NULL)
     303           0 :                 return NULL;
     304             : 
     305          43 :         *len = EAP_TLS_KEY_LEN;
     306          43 :         os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
     307             : 
     308          43 :         return key;
     309             : }
     310             : 
     311             : 
     312           1 : static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
     313             : {
     314           1 :         struct eap_tls_data *data = priv;
     315             :         u8 *key;
     316             : 
     317           1 :         if (data->key_data == NULL)
     318           0 :                 return NULL;
     319             : 
     320           1 :         key = os_malloc(EAP_EMSK_LEN);
     321           1 :         if (key == NULL)
     322           0 :                 return NULL;
     323             : 
     324           1 :         *len = EAP_EMSK_LEN;
     325           1 :         os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
     326             : 
     327           1 :         return key;
     328             : }
     329             : 
     330             : 
     331          39 : static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
     332             : {
     333          39 :         struct eap_tls_data *data = priv;
     334             :         u8 *id;
     335             : 
     336          39 :         if (data->session_id == NULL)
     337           0 :                 return NULL;
     338             : 
     339          39 :         id = os_malloc(data->id_len);
     340          39 :         if (id == NULL)
     341           0 :                 return NULL;
     342             : 
     343          39 :         *len = data->id_len;
     344          39 :         os_memcpy(id, data->session_id, data->id_len);
     345             : 
     346          39 :         return id;
     347             : }
     348             : 
     349             : 
     350          49 : int eap_peer_tls_register(void)
     351             : {
     352             :         struct eap_method *eap;
     353             :         int ret;
     354             : 
     355          49 :         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
     356             :                                     EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
     357          49 :         if (eap == NULL)
     358           0 :                 return -1;
     359             : 
     360          49 :         eap->init = eap_tls_init;
     361          49 :         eap->deinit = eap_tls_deinit;
     362          49 :         eap->process = eap_tls_process;
     363          49 :         eap->isKeyAvailable = eap_tls_isKeyAvailable;
     364          49 :         eap->getKey = eap_tls_getKey;
     365          49 :         eap->getSessionId = eap_tls_get_session_id;
     366          49 :         eap->get_status = eap_tls_get_status;
     367          49 :         eap->has_reauth_data = eap_tls_has_reauth_data;
     368          49 :         eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
     369          49 :         eap->init_for_reauth = eap_tls_init_for_reauth;
     370          49 :         eap->get_emsk = eap_tls_get_emsk;
     371             : 
     372          49 :         ret = eap_peer_method_register(eap);
     373          49 :         if (ret)
     374           0 :                 eap_peer_method_free(eap);
     375          49 :         return ret;
     376             : }
     377             : 
     378             : 
     379             : #ifdef EAP_UNAUTH_TLS
     380          49 : int eap_peer_unauth_tls_register(void)
     381             : {
     382             :         struct eap_method *eap;
     383             :         int ret;
     384             : 
     385          49 :         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
     386             :                                     EAP_VENDOR_UNAUTH_TLS,
     387             :                                     EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS");
     388          49 :         if (eap == NULL)
     389           0 :                 return -1;
     390             : 
     391          49 :         eap->init = eap_unauth_tls_init;
     392          49 :         eap->deinit = eap_tls_deinit;
     393          49 :         eap->process = eap_tls_process;
     394          49 :         eap->isKeyAvailable = eap_tls_isKeyAvailable;
     395          49 :         eap->getKey = eap_tls_getKey;
     396          49 :         eap->get_status = eap_tls_get_status;
     397          49 :         eap->has_reauth_data = eap_tls_has_reauth_data;
     398          49 :         eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
     399          49 :         eap->init_for_reauth = eap_tls_init_for_reauth;
     400          49 :         eap->get_emsk = eap_tls_get_emsk;
     401             : 
     402          49 :         ret = eap_peer_method_register(eap);
     403          49 :         if (ret)
     404           0 :                 eap_peer_method_free(eap);
     405          49 :         return ret;
     406             : }
     407             : #endif /* EAP_UNAUTH_TLS */
     408             : 
     409             : 
     410             : #ifdef CONFIG_HS20
     411          49 : int eap_peer_wfa_unauth_tls_register(void)
     412             : {
     413             :         struct eap_method *eap;
     414             :         int ret;
     415             : 
     416          49 :         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
     417             :                                     EAP_VENDOR_WFA_NEW,
     418             :                                     EAP_VENDOR_WFA_UNAUTH_TLS,
     419             :                                     "WFA-UNAUTH-TLS");
     420          49 :         if (eap == NULL)
     421           0 :                 return -1;
     422             : 
     423          49 :         eap->init = eap_wfa_unauth_tls_init;
     424          49 :         eap->deinit = eap_tls_deinit;
     425          49 :         eap->process = eap_tls_process;
     426          49 :         eap->isKeyAvailable = eap_tls_isKeyAvailable;
     427          49 :         eap->getKey = eap_tls_getKey;
     428          49 :         eap->get_status = eap_tls_get_status;
     429          49 :         eap->has_reauth_data = eap_tls_has_reauth_data;
     430          49 :         eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
     431          49 :         eap->init_for_reauth = eap_tls_init_for_reauth;
     432          49 :         eap->get_emsk = eap_tls_get_emsk;
     433             : 
     434          49 :         ret = eap_peer_method_register(eap);
     435          49 :         if (ret)
     436           0 :                 eap_peer_method_free(eap);
     437          49 :         return ret;
     438             : }
     439             : #endif /* CONFIG_HS20 */

Generated by: LCOV version 1.10