LCOV - code coverage report
Current view: top level - src/eap_peer - eap_tls_common.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 355 448 79.2 %
Date: 2015-09-27 Functions: 26 26 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
       3             :  * Copyright (c) 2004-2013, 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/sha1.h"
      13             : #include "crypto/tls.h"
      14             : #include "eap_i.h"
      15             : #include "eap_tls_common.h"
      16             : #include "eap_config.h"
      17             : 
      18             : 
      19        1680 : static struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
      20             :                                          u8 code, u8 identifier)
      21             : {
      22        1680 :         if (type == EAP_UNAUTH_TLS_TYPE)
      23           8 :                 return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
      24             :                                      EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
      25             :                                      code, identifier);
      26        1672 :         if (type == EAP_WFA_UNAUTH_TLS_TYPE)
      27           8 :                 return eap_msg_alloc(EAP_VENDOR_WFA_NEW,
      28             :                                      EAP_VENDOR_WFA_UNAUTH_TLS, payload_len,
      29             :                                      code, identifier);
      30        1664 :         return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
      31             :                              identifier);
      32             : }
      33             : 
      34             : 
      35        1192 : static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
      36             :                               const u8 **data, size_t *data_len)
      37             : {
      38             :         const struct wpa_config_blob *blob;
      39             : 
      40        1192 :         if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0)
      41        1185 :                 return 0;
      42             : 
      43           7 :         blob = eap_get_config_blob(sm, *name + 7);
      44           7 :         if (blob == NULL) {
      45           0 :                 wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not "
      46           0 :                            "found", __func__, *name + 7);
      47           0 :                 return -1;
      48             :         }
      49             : 
      50           7 :         *name = NULL;
      51           7 :         *data = blob->data;
      52           7 :         *data_len = blob->len;
      53             : 
      54           7 :         return 0;
      55             : }
      56             : 
      57             : 
      58         298 : static void eap_tls_params_flags(struct tls_connection_params *params,
      59             :                                  const char *txt)
      60             : {
      61         298 :         if (txt == NULL)
      62         551 :                 return;
      63          45 :         if (os_strstr(txt, "tls_allow_md5=1"))
      64           0 :                 params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5;
      65          45 :         if (os_strstr(txt, "tls_disable_time_checks=1"))
      66           1 :                 params->flags |= TLS_CONN_DISABLE_TIME_CHECKS;
      67          45 :         if (os_strstr(txt, "tls_disable_session_ticket=1"))
      68           0 :                 params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
      69          45 :         if (os_strstr(txt, "tls_disable_session_ticket=0"))
      70           1 :                 params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET;
      71          45 :         if (os_strstr(txt, "tls_disable_tlsv1_0=1"))
      72           2 :                 params->flags |= TLS_CONN_DISABLE_TLSv1_0;
      73          45 :         if (os_strstr(txt, "tls_disable_tlsv1_0=0"))
      74           0 :                 params->flags &= ~TLS_CONN_DISABLE_TLSv1_0;
      75          45 :         if (os_strstr(txt, "tls_disable_tlsv1_1=1"))
      76           2 :                 params->flags |= TLS_CONN_DISABLE_TLSv1_1;
      77          45 :         if (os_strstr(txt, "tls_disable_tlsv1_1=0"))
      78           0 :                 params->flags &= ~TLS_CONN_DISABLE_TLSv1_1;
      79          45 :         if (os_strstr(txt, "tls_disable_tlsv1_2=1"))
      80           2 :                 params->flags |= TLS_CONN_DISABLE_TLSv1_2;
      81          45 :         if (os_strstr(txt, "tls_disable_tlsv1_2=0"))
      82           0 :                 params->flags &= ~TLS_CONN_DISABLE_TLSv1_2;
      83             : }
      84             : 
      85             : 
      86         297 : static void eap_tls_params_from_conf1(struct tls_connection_params *params,
      87             :                                       struct eap_peer_config *config)
      88             : {
      89         297 :         params->ca_cert = (char *) config->ca_cert;
      90         297 :         params->ca_path = (char *) config->ca_path;
      91         297 :         params->client_cert = (char *) config->client_cert;
      92         297 :         params->private_key = (char *) config->private_key;
      93         297 :         params->private_key_passwd = (char *) config->private_key_passwd;
      94         297 :         params->dh_file = (char *) config->dh_file;
      95         297 :         params->subject_match = (char *) config->subject_match;
      96         297 :         params->altsubject_match = (char *) config->altsubject_match;
      97         297 :         params->suffix_match = config->domain_suffix_match;
      98         297 :         params->domain_match = config->domain_match;
      99         297 :         params->engine = config->engine;
     100         297 :         params->engine_id = config->engine_id;
     101         297 :         params->pin = config->pin;
     102         297 :         params->key_id = config->key_id;
     103         297 :         params->cert_id = config->cert_id;
     104         297 :         params->ca_cert_id = config->ca_cert_id;
     105         297 :         eap_tls_params_flags(params, config->phase1);
     106         297 : }
     107             : 
     108             : 
     109           1 : static void eap_tls_params_from_conf2(struct tls_connection_params *params,
     110             :                                       struct eap_peer_config *config)
     111             : {
     112           1 :         params->ca_cert = (char *) config->ca_cert2;
     113           1 :         params->ca_path = (char *) config->ca_path2;
     114           1 :         params->client_cert = (char *) config->client_cert2;
     115           1 :         params->private_key = (char *) config->private_key2;
     116           1 :         params->private_key_passwd = (char *) config->private_key2_passwd;
     117           1 :         params->dh_file = (char *) config->dh_file2;
     118           1 :         params->subject_match = (char *) config->subject_match2;
     119           1 :         params->altsubject_match = (char *) config->altsubject_match2;
     120           1 :         params->suffix_match = config->domain_suffix_match2;
     121           1 :         params->domain_match = config->domain_match2;
     122           1 :         params->engine = config->engine2;
     123           1 :         params->engine_id = config->engine2_id;
     124           1 :         params->pin = config->pin2;
     125           1 :         params->key_id = config->key2_id;
     126           1 :         params->cert_id = config->cert2_id;
     127           1 :         params->ca_cert_id = config->ca_cert2_id;
     128           1 :         eap_tls_params_flags(params, config->phase2);
     129           1 : }
     130             : 
     131             : 
     132         298 : static int eap_tls_params_from_conf(struct eap_sm *sm,
     133             :                                     struct eap_ssl_data *data,
     134             :                                     struct tls_connection_params *params,
     135             :                                     struct eap_peer_config *config, int phase2)
     136             : {
     137         298 :         os_memset(params, 0, sizeof(*params));
     138         298 :         if (sm->workaround && data->eap_type != EAP_TYPE_FAST) {
     139             :                 /*
     140             :                  * Some deployed authentication servers seem to be unable to
     141             :                  * handle the TLS Session Ticket extension (they are supposed
     142             :                  * to ignore unrecognized TLS extensions, but end up rejecting
     143             :                  * the ClientHello instead). As a workaround, disable use of
     144             :                  * TLS Sesson Ticket extension for EAP-TLS, EAP-PEAP, and
     145             :                  * EAP-TTLS (EAP-FAST uses session ticket, so any server that
     146             :                  * supports EAP-FAST does not need this workaround).
     147             :                  */
     148         269 :                 params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
     149             :         }
     150         298 :         if (phase2) {
     151           1 :                 wpa_printf(MSG_DEBUG, "TLS: using phase2 config options");
     152           1 :                 eap_tls_params_from_conf2(params, config);
     153             :         } else {
     154         297 :                 wpa_printf(MSG_DEBUG, "TLS: using phase1 config options");
     155         297 :                 eap_tls_params_from_conf1(params, config);
     156         297 :                 if (data->eap_type == EAP_TYPE_FAST)
     157          26 :                         params->flags |= TLS_CONN_EAP_FAST;
     158             :         }
     159             : 
     160             :         /*
     161             :          * Use blob data, if available. Otherwise, leave reference to external
     162             :          * file as-is.
     163             :          */
     164         298 :         if (eap_tls_check_blob(sm, &params->ca_cert, &params->ca_cert_blob,
     165         298 :                                &params->ca_cert_blob_len) ||
     166         298 :             eap_tls_check_blob(sm, &params->client_cert,
     167             :                                &params->client_cert_blob,
     168         298 :                                &params->client_cert_blob_len) ||
     169         298 :             eap_tls_check_blob(sm, &params->private_key,
     170             :                                &params->private_key_blob,
     171         298 :                                &params->private_key_blob_len) ||
     172         298 :             eap_tls_check_blob(sm, &params->dh_file, &params->dh_blob,
     173             :                                &params->dh_blob_len)) {
     174           0 :                 wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs");
     175           0 :                 return -1;
     176             :         }
     177             : 
     178         298 :         params->openssl_ciphers = config->openssl_ciphers;
     179             : 
     180         298 :         return 0;
     181             : }
     182             : 
     183             : 
     184         298 : static int eap_tls_init_connection(struct eap_sm *sm,
     185             :                                    struct eap_ssl_data *data,
     186             :                                    struct eap_peer_config *config,
     187             :                                    struct tls_connection_params *params)
     188             : {
     189             :         int res;
     190             : 
     191         298 :         if (config->ocsp)
     192           7 :                 params->flags |= TLS_CONN_REQUEST_OCSP;
     193         298 :         if (config->ocsp == 2)
     194           6 :                 params->flags |= TLS_CONN_REQUIRE_OCSP;
     195         298 :         data->conn = tls_connection_init(data->ssl_ctx);
     196         298 :         if (data->conn == NULL) {
     197           0 :                 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
     198             :                            "connection");
     199           0 :                 return -1;
     200             :         }
     201             : 
     202         298 :         res = tls_connection_set_params(data->ssl_ctx, data->conn, params);
     203         298 :         if (res == TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN) {
     204             :                 /*
     205             :                  * At this point with the pkcs11 engine the PIN is wrong. We
     206             :                  * reset the PIN in the configuration to be sure to not use it
     207             :                  * again and the calling function must request a new one.
     208             :                  */
     209           0 :                 wpa_printf(MSG_INFO,
     210             :                            "TLS: Bad PIN provided, requesting a new one");
     211           0 :                 os_free(config->pin);
     212           0 :                 config->pin = NULL;
     213           0 :                 eap_sm_request_pin(sm);
     214           0 :                 sm->ignore = TRUE;
     215         298 :         } else if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
     216           0 :                 wpa_printf(MSG_INFO, "TLS: Failed to initialize engine");
     217         298 :         } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) {
     218           0 :                 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
     219           0 :                 sm->ignore = TRUE;
     220             :         }
     221         298 :         if (res) {
     222           9 :                 wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
     223             :                            "parameters");
     224           9 :                 tls_connection_deinit(data->ssl_ctx, data->conn);
     225           9 :                 data->conn = NULL;
     226           9 :                 return -1;
     227             :         }
     228             : 
     229         289 :         return 0;
     230             : }
     231             : 
     232             : 
     233             : /**
     234             :  * eap_peer_tls_ssl_init - Initialize shared TLS functionality
     235             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     236             :  * @data: Data for TLS processing
     237             :  * @config: Pointer to the network configuration
     238             :  * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
     239             :  * Returns: 0 on success, -1 on failure
     240             :  *
     241             :  * This function is used to initialize shared TLS functionality for EAP-TLS,
     242             :  * EAP-PEAP, EAP-TTLS, and EAP-FAST.
     243             :  */
     244         298 : int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
     245             :                           struct eap_peer_config *config, u8 eap_type)
     246             : {
     247             :         struct tls_connection_params params;
     248             : 
     249         298 :         if (config == NULL)
     250           0 :                 return -1;
     251             : 
     252         298 :         data->eap = sm;
     253         298 :         data->eap_type = eap_type;
     254         298 :         data->phase2 = sm->init_phase2;
     255         298 :         data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
     256             :                 sm->ssl_ctx;
     257         298 :         if (eap_tls_params_from_conf(sm, data, &params, config, data->phase2) <
     258             :             0)
     259           0 :                 return -1;
     260             : 
     261         298 :         if (eap_tls_init_connection(sm, data, config, &params) < 0)
     262           9 :                 return -1;
     263             : 
     264         289 :         data->tls_out_limit = config->fragment_size;
     265         289 :         if (data->phase2) {
     266             :                 /* Limit the fragment size in the inner TLS authentication
     267             :                  * since the outer authentication with EAP-PEAP does not yet
     268             :                  * support fragmentation */
     269           1 :                 if (data->tls_out_limit > 100)
     270           1 :                         data->tls_out_limit -= 100;
     271             :         }
     272             : 
     273         333 :         if (config->phase1 &&
     274          44 :             os_strstr(config->phase1, "include_tls_length=1")) {
     275           0 :                 wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in "
     276             :                            "unfragmented packets");
     277           0 :                 data->include_tls_length = 1;
     278             :         }
     279             : 
     280         289 :         return 0;
     281             : }
     282             : 
     283             : 
     284             : /**
     285             :  * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality
     286             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     287             :  * @data: Data for TLS processing
     288             :  *
     289             :  * This function deinitializes shared TLS functionality that was initialized
     290             :  * with eap_peer_tls_ssl_init().
     291             :  */
     292         298 : void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
     293             : {
     294         298 :         tls_connection_deinit(data->ssl_ctx, data->conn);
     295         298 :         eap_peer_tls_reset_input(data);
     296         298 :         eap_peer_tls_reset_output(data);
     297         298 : }
     298             : 
     299             : 
     300             : /**
     301             :  * eap_peer_tls_derive_key - Derive a key based on TLS session data
     302             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     303             :  * @data: Data for TLS processing
     304             :  * @label: Label string for deriving the keys, e.g., "client EAP encryption"
     305             :  * @len: Length of the key material to generate (usually 64 for MSK)
     306             :  * Returns: Pointer to allocated key on success or %NULL on failure
     307             :  *
     308             :  * This function uses TLS-PRF to generate pseudo-random data based on the TLS
     309             :  * session data (client/server random and master key). Each key type may use a
     310             :  * different label to bind the key usage into the generated material.
     311             :  *
     312             :  * The caller is responsible for freeing the returned buffer.
     313             :  */
     314         377 : u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
     315             :                              const char *label, size_t len)
     316             : {
     317             :         u8 *out;
     318             : 
     319         377 :         out = os_malloc(len);
     320         377 :         if (out == NULL)
     321           0 :                 return NULL;
     322             : 
     323         377 :         if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0,
     324             :                                out, len)) {
     325           0 :                 os_free(out);
     326           0 :                 return NULL;
     327             :         }
     328             : 
     329         377 :         return out;
     330             : }
     331             : 
     332             : 
     333             : /**
     334             :  * eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data
     335             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     336             :  * @data: Data for TLS processing
     337             :  * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
     338             :  * @len: Pointer to length of the session ID generated
     339             :  * Returns: Pointer to allocated Session-Id on success or %NULL on failure
     340             :  *
     341             :  * This function derive the Session-Id based on the TLS session data
     342             :  * (client/server random and method type).
     343             :  *
     344             :  * The caller is responsible for freeing the returned buffer.
     345             :  */
     346         285 : u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
     347             :                                     struct eap_ssl_data *data, u8 eap_type,
     348             :                                     size_t *len)
     349             : {
     350             :         struct tls_random keys;
     351             :         u8 *out;
     352             : 
     353         285 :         if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
     354           0 :                 return NULL;
     355             : 
     356         285 :         if (keys.client_random == NULL || keys.server_random == NULL)
     357           0 :                 return NULL;
     358             : 
     359         285 :         *len = 1 + keys.client_random_len + keys.server_random_len;
     360         285 :         out = os_malloc(*len);
     361         285 :         if (out == NULL)
     362           0 :                 return NULL;
     363             : 
     364             :         /* Session-Id = EAP type || client.random || server.random */
     365         285 :         out[0] = eap_type;
     366         285 :         os_memcpy(out + 1, keys.client_random, keys.client_random_len);
     367         285 :         os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
     368             :                   keys.server_random_len);
     369             : 
     370         285 :         return out;
     371             : }
     372             : 
     373             : 
     374             : /**
     375             :  * eap_peer_tls_reassemble_fragment - Reassemble a received fragment
     376             :  * @data: Data for TLS processing
     377             :  * @in_data: Next incoming TLS segment
     378             :  * Returns: 0 on success, 1 if more data is needed for the full message, or
     379             :  * -1 on error
     380             :  */
     381         505 : static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
     382             :                                             const struct wpabuf *in_data)
     383             : {
     384             :         size_t tls_in_len, in_len;
     385             : 
     386         505 :         tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0;
     387         505 :         in_len = in_data ? wpabuf_len(in_data) : 0;
     388             : 
     389         505 :         if (tls_in_len + in_len == 0) {
     390             :                 /* No message data received?! */
     391           0 :                 wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
     392             :                            "tls_in_left=%lu tls_in_len=%lu in_len=%lu",
     393             :                            (unsigned long) data->tls_in_left,
     394             :                            (unsigned long) tls_in_len,
     395             :                            (unsigned long) in_len);
     396           0 :                 eap_peer_tls_reset_input(data);
     397           0 :                 return -1;
     398             :         }
     399             : 
     400         505 :         if (tls_in_len + in_len > 65536) {
     401             :                 /*
     402             :                  * Limit length to avoid rogue servers from causing large
     403             :                  * memory allocations.
     404             :                  */
     405           0 :                 wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over "
     406             :                            "64 kB)");
     407           0 :                 eap_peer_tls_reset_input(data);
     408           0 :                 return -1;
     409             :         }
     410             : 
     411         505 :         if (in_len > data->tls_in_left) {
     412             :                 /* Sender is doing something odd - reject message */
     413           0 :                 wpa_printf(MSG_INFO, "SSL: more data than TLS message length "
     414             :                            "indicated");
     415           0 :                 eap_peer_tls_reset_input(data);
     416           0 :                 return -1;
     417             :         }
     418             : 
     419         505 :         if (wpabuf_resize(&data->tls_in, in_len) < 0) {
     420           0 :                 wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
     421             :                            "data");
     422           0 :                 eap_peer_tls_reset_input(data);
     423           0 :                 return -1;
     424             :         }
     425         505 :         if (in_data)
     426         505 :                 wpabuf_put_buf(data->tls_in, in_data);
     427         505 :         data->tls_in_left -= in_len;
     428             : 
     429         505 :         if (data->tls_in_left > 0) {
     430         257 :                 wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
     431             :                            "data", (unsigned long) data->tls_in_left);
     432         257 :                 return 1;
     433             :         }
     434             : 
     435         248 :         return 0;
     436             : }
     437             : 
     438             : 
     439             : /**
     440             :  * eap_peer_tls_data_reassemble - Reassemble TLS data
     441             :  * @data: Data for TLS processing
     442             :  * @in_data: Next incoming TLS segment
     443             :  * @need_more_input: Variable for returning whether more input data is needed
     444             :  * to reassemble this TLS packet
     445             :  * Returns: Pointer to output data, %NULL on error or when more data is needed
     446             :  * for the full message (in which case, *need_more_input is also set to 1).
     447             :  *
     448             :  * This function reassembles TLS fragments. Caller must not free the returned
     449             :  * data buffer since an internal pointer to it is maintained.
     450             :  */
     451        1591 : static const struct wpabuf * eap_peer_tls_data_reassemble(
     452             :         struct eap_ssl_data *data, const struct wpabuf *in_data,
     453             :         int *need_more_input)
     454             : {
     455        1591 :         *need_more_input = 0;
     456             : 
     457        1839 :         if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) {
     458             :                 /* Message has fragments */
     459         505 :                 int res = eap_peer_tls_reassemble_fragment(data, in_data);
     460         505 :                 if (res) {
     461         257 :                         if (res == 1)
     462         257 :                                 *need_more_input = 1;
     463         257 :                         return NULL;
     464             :                 }
     465             : 
     466             :                 /* Message is now fully reassembled. */
     467             :         } else {
     468             :                 /* No fragments in this message, so just make a copy of it. */
     469        1086 :                 data->tls_in_left = 0;
     470        1086 :                 data->tls_in = wpabuf_dup(in_data);
     471        1086 :                 if (data->tls_in == NULL)
     472           0 :                         return NULL;
     473             :         }
     474             : 
     475        1334 :         return data->tls_in;
     476             : }
     477             : 
     478             : 
     479             : /**
     480             :  * eap_tls_process_input - Process incoming TLS message
     481             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     482             :  * @data: Data for TLS processing
     483             :  * @in_data: Message received from the server
     484             :  * @out_data: Buffer for returning a pointer to application data (if available)
     485             :  * Returns: 0 on success, 1 if more input data is needed, 2 if application data
     486             :  * is available, -1 on failure
     487             :  */
     488        1175 : static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
     489             :                                  const struct wpabuf *in_data,
     490             :                                  struct wpabuf **out_data)
     491             : {
     492             :         const struct wpabuf *msg;
     493             :         int need_more_input;
     494             :         struct wpabuf *appl_data;
     495             : 
     496        1175 :         msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input);
     497        1175 :         if (msg == NULL)
     498         257 :                 return need_more_input ? 1 : -1;
     499             : 
     500             :         /* Full TLS message reassembled - continue handshake processing */
     501         918 :         if (data->tls_out) {
     502             :                 /* This should not happen.. */
     503           0 :                 wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
     504             :                            "tls_out data even though tls_out_len = 0");
     505           0 :                 wpabuf_free(data->tls_out);
     506             :                 WPA_ASSERT(data->tls_out == NULL);
     507             :         }
     508         918 :         appl_data = NULL;
     509         918 :         data->tls_out = tls_connection_handshake(data->ssl_ctx, data->conn,
     510             :                                                  msg, &appl_data);
     511             : 
     512         918 :         eap_peer_tls_reset_input(data);
     513             : 
     514         931 :         if (appl_data &&
     515          26 :             tls_connection_established(data->ssl_ctx, data->conn) &&
     516          13 :             !tls_connection_get_failed(data->ssl_ctx, data->conn)) {
     517          13 :                 wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data",
     518             :                                     appl_data);
     519          13 :                 *out_data = appl_data;
     520          13 :                 return 2;
     521             :         }
     522             : 
     523         905 :         wpabuf_free(appl_data);
     524             : 
     525         905 :         return 0;
     526             : }
     527             : 
     528             : 
     529             : /**
     530             :  * eap_tls_process_output - Process outgoing TLS message
     531             :  * @data: Data for TLS processing
     532             :  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
     533             :  * @peap_version: Version number for EAP-PEAP/TTLS
     534             :  * @id: EAP identifier for the response
     535             :  * @ret: Return value to use on success
     536             :  * @out_data: Buffer for returning the allocated output buffer
     537             :  * Returns: ret (0 or 1) on success, -1 on failure
     538             :  */
     539        1221 : static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
     540             :                                   int peap_version, u8 id, int ret,
     541             :                                   struct wpabuf **out_data)
     542             : {
     543             :         size_t len;
     544             :         u8 *flags;
     545             :         int more_fragments, length_included;
     546             : 
     547        1221 :         if (data->tls_out == NULL)
     548           0 :                 return -1;
     549        1221 :         len = wpabuf_len(data->tls_out) - data->tls_out_pos;
     550        1221 :         wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
     551             :                    "%lu bytes)",
     552             :                    (unsigned long) len,
     553        1221 :                    (unsigned long) wpabuf_len(data->tls_out));
     554             : 
     555             :         /*
     556             :          * Limit outgoing message to the configured maximum size. Fragment
     557             :          * message if needed.
     558             :          */
     559        1221 :         if (len > data->tls_out_limit) {
     560          92 :                 more_fragments = 1;
     561          92 :                 len = data->tls_out_limit;
     562          92 :                 wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
     563             :                            "will follow", (unsigned long) len);
     564             :         } else
     565        1129 :                 more_fragments = 0;
     566             : 
     567        2393 :         length_included = data->tls_out_pos == 0 &&
     568        2218 :                 (wpabuf_len(data->tls_out) > data->tls_out_limit ||
     569        1088 :                  data->include_tls_length);
     570        1221 :         if (!length_included &&
     571         294 :             eap_type == EAP_TYPE_PEAP && peap_version == 0 &&
     572          56 :             !tls_connection_established(data->eap->ssl_ctx, data->conn)) {
     573             :                 /*
     574             :                  * Windows Server 2008 NPS really wants to have the TLS Message
     575             :                  * length included in phase 0 even for unfragmented frames or
     576             :                  * it will get very confused with Compound MAC calculation and
     577             :                  * Outer TLVs.
     578             :                  */
     579          18 :                 length_included = 1;
     580             :         }
     581             : 
     582        1221 :         *out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len,
     583             :                                       EAP_CODE_RESPONSE, id);
     584        1221 :         if (*out_data == NULL)
     585           0 :                 return -1;
     586             : 
     587        1221 :         flags = wpabuf_put(*out_data, 1);
     588        1221 :         *flags = peap_version;
     589        1221 :         if (more_fragments)
     590          92 :                 *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
     591        1221 :         if (length_included) {
     592          60 :                 *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
     593          60 :                 wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out));
     594             :         }
     595             : 
     596        1221 :         wpabuf_put_data(*out_data,
     597        1221 :                         wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
     598             :                         len);
     599        1221 :         data->tls_out_pos += len;
     600             : 
     601        1221 :         if (!more_fragments)
     602        1129 :                 eap_peer_tls_reset_output(data);
     603             : 
     604        1221 :         return ret;
     605             : }
     606             : 
     607             : 
     608             : /**
     609             :  * eap_peer_tls_process_helper - Process TLS handshake message
     610             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     611             :  * @data: Data for TLS processing
     612             :  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
     613             :  * @peap_version: Version number for EAP-PEAP/TTLS
     614             :  * @id: EAP identifier for the response
     615             :  * @in_data: Message received from the server
     616             :  * @out_data: Buffer for returning a pointer to the response message
     617             :  * Returns: 0 on success, 1 if more input data is needed, 2 if application data
     618             :  * is available, or -1 on failure
     619             :  *
     620             :  * This function can be used to process TLS handshake messages. It reassembles
     621             :  * the received fragments and uses a TLS library to process the messages. The
     622             :  * response data from the TLS library is fragmented to suitable output messages
     623             :  * that the caller can send out.
     624             :  *
     625             :  * out_data is used to return the response message if the return value of this
     626             :  * function is 0, 2, or -1. In case of failure, the message is likely a TLS
     627             :  * alarm message. The caller is responsible for freeing the allocated buffer if
     628             :  * *out_data is not %NULL.
     629             :  *
     630             :  * This function is called for each received TLS message during the TLS
     631             :  * handshake after eap_peer_tls_process_init() call and possible processing of
     632             :  * TLS Flags field. Once the handshake has been completed, i.e., when
     633             :  * tls_connection_established() returns 1, EAP method specific decrypting of
     634             :  * the tunneled data is used.
     635             :  */
     636        1260 : int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
     637             :                                 EapType eap_type, int peap_version,
     638             :                                 u8 id, const struct wpabuf *in_data,
     639             :                                 struct wpabuf **out_data)
     640             : {
     641        1260 :         int ret = 0;
     642             : 
     643        1260 :         *out_data = NULL;
     644             : 
     645        1345 :         if (data->tls_out && wpabuf_len(data->tls_out) > 0 &&
     646          85 :             wpabuf_len(in_data) > 0) {
     647           0 :                 wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output "
     648             :                            "fragments are waiting to be sent out");
     649           0 :                 return -1;
     650             :         }
     651             : 
     652        1260 :         if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) {
     653             :                 /*
     654             :                  * No more data to send out - expect to receive more data from
     655             :                  * the AS.
     656             :                  */
     657        1175 :                 int res = eap_tls_process_input(sm, data, in_data, out_data);
     658        1175 :                 if (res) {
     659             :                         /*
     660             :                          * Input processing failed (res = -1) or more data is
     661             :                          * needed (res = 1).
     662             :                          */
     663         270 :                         return res;
     664             :                 }
     665             : 
     666             :                 /*
     667             :                  * The incoming message has been reassembled and processed. The
     668             :                  * response was allocated into data->tls_out buffer.
     669             :                  */
     670             :         }
     671             : 
     672         990 :         if (data->tls_out == NULL) {
     673             :                 /*
     674             :                  * No outgoing fragments remaining from the previous message
     675             :                  * and no new message generated. This indicates an error in TLS
     676             :                  * processing.
     677             :                  */
     678           0 :                 eap_peer_tls_reset_output(data);
     679           0 :                 return -1;
     680             :         }
     681             : 
     682         990 :         if (tls_connection_get_failed(data->ssl_ctx, data->conn)) {
     683             :                 /* TLS processing has failed - return error */
     684          27 :                 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
     685             :                            "report error (len=%u)",
     686          27 :                            (unsigned int) wpabuf_len(data->tls_out));
     687          27 :                 ret = -1;
     688             :                 /* TODO: clean pin if engine used? */
     689          27 :                 if (wpabuf_len(data->tls_out) == 0) {
     690           0 :                         wpabuf_free(data->tls_out);
     691           0 :                         data->tls_out = NULL;
     692           0 :                         return -1;
     693             :                 }
     694             :         }
     695             : 
     696         990 :         if (wpabuf_len(data->tls_out) == 0) {
     697             :                 /*
     698             :                  * TLS negotiation should now be complete since all other cases
     699             :                  * needing more data should have been caught above based on
     700             :                  * the TLS Message Length field.
     701             :                  */
     702         258 :                 wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
     703         258 :                 wpabuf_free(data->tls_out);
     704         258 :                 data->tls_out = NULL;
     705         258 :                 return 1;
     706             :         }
     707             : 
     708             :         /* Send the pending message (in fragments, if needed). */
     709         732 :         return eap_tls_process_output(data, eap_type, peap_version, id, ret,
     710             :                                       out_data);
     711             : }
     712             : 
     713             : 
     714             : /**
     715             :  * eap_peer_tls_build_ack - Build a TLS ACK frame
     716             :  * @id: EAP identifier for the response
     717             :  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
     718             :  * @peap_version: Version number for EAP-PEAP/TTLS
     719             :  * Returns: Pointer to the allocated ACK frame or %NULL on failure
     720             :  */
     721         459 : struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type,
     722             :                                        int peap_version)
     723             : {
     724             :         struct wpabuf *resp;
     725             : 
     726         459 :         resp = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_RESPONSE, id);
     727         459 :         if (resp == NULL)
     728           0 :                 return NULL;
     729         459 :         wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)",
     730             :                    (int) eap_type, id, peap_version);
     731         459 :         wpabuf_put_u8(resp, peap_version); /* Flags */
     732         459 :         return resp;
     733             : }
     734             : 
     735             : 
     736             : /**
     737             :  * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption
     738             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     739             :  * @data: Data for TLS processing
     740             :  * Returns: 0 on success, -1 on failure
     741             :  */
     742          39 : int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
     743             : {
     744          39 :         eap_peer_tls_reset_input(data);
     745          39 :         eap_peer_tls_reset_output(data);
     746          39 :         return tls_connection_shutdown(data->ssl_ctx, data->conn);
     747             : }
     748             : 
     749             : 
     750             : /**
     751             :  * eap_peer_tls_status - Get TLS status
     752             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     753             :  * @data: Data for TLS processing
     754             :  * @buf: Buffer for status information
     755             :  * @buflen: Maximum buffer length
     756             :  * @verbose: Whether to include verbose status information
     757             :  * Returns: Number of bytes written to buf.
     758             :  */
     759         198 : int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data,
     760             :                         char *buf, size_t buflen, int verbose)
     761             : {
     762             :         char version[20], name[128];
     763         198 :         int len = 0, ret;
     764             : 
     765         198 :         if (tls_get_version(data->ssl_ctx, data->conn, version,
     766             :                             sizeof(version)) < 0)
     767           0 :                 version[0] = '\0';
     768         198 :         if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) < 0)
     769           0 :                 name[0] = '\0';
     770             : 
     771         198 :         ret = os_snprintf(buf + len, buflen - len,
     772             :                           "eap_tls_version=%s\n"
     773             :                           "EAP TLS cipher=%s\n"
     774             :                           "tls_session_reused=%d\n",
     775             :                           version, name,
     776             :                           tls_connection_resumed(data->ssl_ctx, data->conn));
     777         198 :         if (os_snprintf_error(buflen - len, ret))
     778           0 :                 return len;
     779         198 :         len += ret;
     780             : 
     781         198 :         return len;
     782             : }
     783             : 
     784             : 
     785             : /**
     786             :  * eap_peer_tls_process_init - Initial validation/processing of EAP requests
     787             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     788             :  * @data: Data for TLS processing
     789             :  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
     790             :  * @ret: Return values from EAP request validation and processing
     791             :  * @reqData: EAP request to be processed (eapReqData)
     792             :  * @len: Buffer for returning length of the remaining payload
     793             :  * @flags: Buffer for returning TLS flags
     794             :  * Returns: Pointer to payload after TLS flags and length or %NULL on failure
     795             :  *
     796             :  * This function validates the EAP header and processes the optional TLS
     797             :  * Message Length field. If this is the first fragment of a TLS message, the
     798             :  * TLS reassembly code is initialized to receive the indicated number of bytes.
     799             :  *
     800             :  * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this
     801             :  * function as the first step in processing received messages. They will need
     802             :  * to process the flags (apart from Message Length Included) that are returned
     803             :  * through the flags pointer and the message payload that will be returned (and
     804             :  * the length is returned through the len pointer). Return values (ret) are set
     805             :  * for continuation of EAP method processing. The caller is responsible for
     806             :  * setting these to indicate completion (either success or failure) based on
     807             :  * the authentication result.
     808             :  */
     809        1691 : const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
     810             :                                      struct eap_ssl_data *data,
     811             :                                      EapType eap_type,
     812             :                                      struct eap_method_ret *ret,
     813             :                                      const struct wpabuf *reqData,
     814             :                                      size_t *len, u8 *flags)
     815             : {
     816             :         const u8 *pos;
     817             :         size_t left;
     818             :         unsigned int tls_msg_len;
     819             : 
     820        1691 :         if (tls_get_errors(data->ssl_ctx)) {
     821           0 :                 wpa_printf(MSG_INFO, "SSL: TLS errors detected");
     822           0 :                 ret->ignore = TRUE;
     823           0 :                 return NULL;
     824             :         }
     825             : 
     826        1691 :         if (eap_type == EAP_UNAUTH_TLS_TYPE)
     827           8 :                 pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
     828             :                                        EAP_VENDOR_TYPE_UNAUTH_TLS, reqData,
     829             :                                        &left);
     830        1683 :         else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
     831           8 :                 pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
     832             :                                        EAP_VENDOR_WFA_UNAUTH_TLS, reqData,
     833             :                                        &left);
     834             :         else
     835        1675 :                 pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData,
     836             :                                        &left);
     837        1691 :         if (pos == NULL) {
     838           0 :                 ret->ignore = TRUE;
     839           0 :                 return NULL;
     840             :         }
     841        1691 :         if (left == 0) {
     842           0 :                 wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags "
     843             :                            "octet included");
     844           0 :                 if (!sm->workaround) {
     845           0 :                         ret->ignore = TRUE;
     846           0 :                         return NULL;
     847             :                 }
     848             : 
     849           0 :                 wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags "
     850             :                            "indicates ACK frame");
     851           0 :                 *flags = 0;
     852             :         } else {
     853        1691 :                 *flags = *pos++;
     854        1691 :                 left--;
     855             :         }
     856        1691 :         wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - "
     857             :                    "Flags 0x%02x", (unsigned long) wpabuf_len(reqData),
     858        1691 :                    *flags);
     859        1691 :         if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
     860         250 :                 if (left < 4) {
     861           0 :                         wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
     862             :                                    "length");
     863           0 :                         ret->ignore = TRUE;
     864           0 :                         return NULL;
     865             :                 }
     866         250 :                 tls_msg_len = WPA_GET_BE32(pos);
     867         250 :                 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
     868             :                            tls_msg_len);
     869         250 :                 if (data->tls_in_left == 0) {
     870         250 :                         data->tls_in_total = tls_msg_len;
     871         250 :                         data->tls_in_left = tls_msg_len;
     872         250 :                         wpabuf_free(data->tls_in);
     873         250 :                         data->tls_in = NULL;
     874             :                 }
     875         250 :                 pos += 4;
     876         250 :                 left -= 4;
     877             : 
     878         250 :                 if (left > tls_msg_len) {
     879           0 :                         wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
     880             :                                    "bytes) smaller than this fragment (%d "
     881             :                                    "bytes)", (int) tls_msg_len, (int) left);
     882           0 :                         ret->ignore = TRUE;
     883           0 :                         return NULL;
     884             :                 }
     885             :         }
     886             : 
     887        1691 :         ret->ignore = FALSE;
     888        1691 :         ret->methodState = METHOD_MAY_CONT;
     889        1691 :         ret->decision = DECISION_FAIL;
     890        1691 :         ret->allowNotifications = TRUE;
     891             : 
     892        1691 :         *len = left;
     893        1691 :         return pos;
     894             : }
     895             : 
     896             : 
     897             : /**
     898             :  * eap_peer_tls_reset_input - Reset input buffers
     899             :  * @data: Data for TLS processing
     900             :  *
     901             :  * This function frees any allocated memory for input buffers and resets input
     902             :  * state.
     903             :  */
     904        1692 : void eap_peer_tls_reset_input(struct eap_ssl_data *data)
     905             : {
     906        1692 :         data->tls_in_left = data->tls_in_total = 0;
     907        1692 :         wpabuf_free(data->tls_in);
     908        1692 :         data->tls_in = NULL;
     909        1692 : }
     910             : 
     911             : 
     912             : /**
     913             :  * eap_peer_tls_reset_output - Reset output buffers
     914             :  * @data: Data for TLS processing
     915             :  *
     916             :  * This function frees any allocated memory for output buffers and resets
     917             :  * output state.
     918             :  */
     919        1949 : void eap_peer_tls_reset_output(struct eap_ssl_data *data)
     920             : {
     921        1949 :         data->tls_out_pos = 0;
     922        1949 :         wpabuf_free(data->tls_out);
     923        1949 :         data->tls_out = NULL;
     924        1949 : }
     925             : 
     926             : 
     927             : /**
     928             :  * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message
     929             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     930             :  * @data: Data for TLS processing
     931             :  * @in_data: Message received from the server
     932             :  * @in_decrypted: Buffer for returning a pointer to the decrypted message
     933             :  * Returns: 0 on success, 1 if more input data is needed, or -1 on failure
     934             :  */
     935         416 : int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data,
     936             :                          const struct wpabuf *in_data,
     937             :                          struct wpabuf **in_decrypted)
     938             : {
     939             :         const struct wpabuf *msg;
     940             :         int need_more_input;
     941             : 
     942         416 :         msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input);
     943         416 :         if (msg == NULL)
     944           0 :                 return need_more_input ? 1 : -1;
     945             : 
     946         416 :         *in_decrypted = tls_connection_decrypt(data->ssl_ctx, data->conn, msg);
     947         416 :         eap_peer_tls_reset_input(data);
     948         416 :         if (*in_decrypted == NULL) {
     949           0 :                 wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
     950           0 :                 return -1;
     951             :         }
     952         416 :         return 0;
     953             : }
     954             : 
     955             : 
     956             : /**
     957             :  * eap_peer_tls_encrypt - Encrypt phase 2 TLS message
     958             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     959             :  * @data: Data for TLS processing
     960             :  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
     961             :  * @peap_version: Version number for EAP-PEAP/TTLS
     962             :  * @id: EAP identifier for the response
     963             :  * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments
     964             :  * @out_data: Buffer for returning a pointer to the encrypted response message
     965             :  * Returns: 0 on success, -1 on failure
     966             :  */
     967         489 : int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
     968             :                          EapType eap_type, int peap_version, u8 id,
     969             :                          const struct wpabuf *in_data,
     970             :                          struct wpabuf **out_data)
     971             : {
     972         489 :         if (in_data) {
     973         483 :                 eap_peer_tls_reset_output(data);
     974         483 :                 data->tls_out = tls_connection_encrypt(data->ssl_ctx,
     975             :                                                        data->conn, in_data);
     976         483 :                 if (data->tls_out == NULL) {
     977           0 :                         wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
     978             :                                    "data (in_len=%lu)",
     979             :                                    (unsigned long) wpabuf_len(in_data));
     980           0 :                         eap_peer_tls_reset_output(data);
     981           0 :                         return -1;
     982             :                 }
     983             :         }
     984             : 
     985         489 :         return eap_tls_process_output(data, eap_type, peap_version, id, 0,
     986             :                                       out_data);
     987             : }
     988             : 
     989             : 
     990             : /**
     991             :  * eap_peer_select_phase2_methods - Select phase 2 EAP method
     992             :  * @config: Pointer to the network configuration
     993             :  * @prefix: 'phase2' configuration prefix, e.g., "auth="
     994             :  * @types: Buffer for returning allocated list of allowed EAP methods
     995             :  * @num_types: Buffer for returning number of allocated EAP methods
     996             :  * Returns: 0 on success, -1 on failure
     997             :  *
     998             :  * This function is used to parse EAP method list and select allowed methods
     999             :  * for Phase2 authentication.
    1000             :  */
    1001          91 : int eap_peer_select_phase2_methods(struct eap_peer_config *config,
    1002             :                                    const char *prefix,
    1003             :                                    struct eap_method_type **types,
    1004             :                                    size_t *num_types)
    1005             : {
    1006             :         char *start, *pos, *buf;
    1007          91 :         struct eap_method_type *methods = NULL, *_methods;
    1008             :         u32 method;
    1009          91 :         size_t num_methods = 0, prefix_len;
    1010             : 
    1011          91 :         if (config == NULL || config->phase2 == NULL)
    1012             :                 goto get_defaults;
    1013             : 
    1014          82 :         start = buf = os_strdup(config->phase2);
    1015          82 :         if (buf == NULL)
    1016           0 :                 return -1;
    1017             : 
    1018          82 :         prefix_len = os_strlen(prefix);
    1019             : 
    1020         246 :         while (start && *start != '\0') {
    1021             :                 int vendor;
    1022          82 :                 pos = os_strstr(start, prefix);
    1023          82 :                 if (pos == NULL)
    1024           0 :                         break;
    1025          82 :                 if (start != pos && *(pos - 1) != ' ') {
    1026           0 :                         start = pos + prefix_len;
    1027           0 :                         continue;
    1028             :                 }
    1029             : 
    1030          82 :                 start = pos + prefix_len;
    1031          82 :                 pos = os_strchr(start, ' ');
    1032          82 :                 if (pos)
    1033           0 :                         *pos++ = '\0';
    1034          82 :                 method = eap_get_phase2_type(start, &vendor);
    1035          82 :                 if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
    1036           0 :                         wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
    1037             :                                    "method '%s'", start);
    1038             :                 } else {
    1039          82 :                         num_methods++;
    1040          82 :                         _methods = os_realloc_array(methods, num_methods,
    1041             :                                                     sizeof(*methods));
    1042          82 :                         if (_methods == NULL) {
    1043           0 :                                 os_free(methods);
    1044           0 :                                 os_free(buf);
    1045           0 :                                 return -1;
    1046             :                         }
    1047          82 :                         methods = _methods;
    1048          82 :                         methods[num_methods - 1].vendor = vendor;
    1049          82 :                         methods[num_methods - 1].method = method;
    1050             :                 }
    1051             : 
    1052          82 :                 start = pos;
    1053             :         }
    1054             : 
    1055          82 :         os_free(buf);
    1056             : 
    1057             : get_defaults:
    1058          91 :         if (methods == NULL)
    1059           9 :                 methods = eap_get_phase2_types(config, &num_methods);
    1060             : 
    1061          91 :         if (methods == NULL) {
    1062           0 :                 wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available");
    1063           0 :                 return -1;
    1064             :         }
    1065          91 :         wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types",
    1066             :                     (u8 *) methods,
    1067             :                     num_methods * sizeof(struct eap_method_type));
    1068             : 
    1069          91 :         *types = methods;
    1070          91 :         *num_types = num_methods;
    1071             : 
    1072          91 :         return 0;
    1073             : }
    1074             : 
    1075             : 
    1076             : /**
    1077             :  * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2
    1078             :  * @types: Buffer for returning allocated list of allowed EAP methods
    1079             :  * @num_types: Buffer for returning number of allocated EAP methods
    1080             :  * @hdr: EAP-Request header (and the following EAP type octet)
    1081             :  * @resp: Buffer for returning the EAP-Nak message
    1082             :  * Returns: 0 on success, -1 on failure
    1083             :  */
    1084          22 : int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types,
    1085             :                             struct eap_hdr *hdr, struct wpabuf **resp)
    1086             : {
    1087          22 :         u8 *pos = (u8 *) (hdr + 1);
    1088             :         size_t i;
    1089             : 
    1090             :         /* TODO: add support for expanded Nak */
    1091          22 :         wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos);
    1092          22 :         wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types",
    1093             :                     (u8 *) types, num_types * sizeof(struct eap_method_type));
    1094          22 :         *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types,
    1095          22 :                               EAP_CODE_RESPONSE, hdr->identifier);
    1096          22 :         if (*resp == NULL)
    1097           0 :                 return -1;
    1098             : 
    1099          44 :         for (i = 0; i < num_types; i++) {
    1100          44 :                 if (types[i].vendor == EAP_VENDOR_IETF &&
    1101          22 :                     types[i].method < 256)
    1102          22 :                         wpabuf_put_u8(*resp, types[i].method);
    1103             :         }
    1104             : 
    1105          22 :         eap_update_len(*resp);
    1106             : 
    1107          22 :         return 0;
    1108             : }

Generated by: LCOV version 1.10