LCOV - code coverage report
Current view: top level - src/wps - wps.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 238 289 82.4 %
Date: 2014-03-02 Functions: 17 17 100.0 %
Branches: 153 241 63.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Wi-Fi Protected Setup
       3                 :            :  * Copyright (c) 2007-2009, 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/dh_group5.h"
      13                 :            : #include "common/ieee802_11_defs.h"
      14                 :            : #include "wps_i.h"
      15                 :            : #include "wps_dev_attr.h"
      16                 :            : 
      17                 :            : 
      18                 :            : #ifdef CONFIG_WPS_TESTING
      19                 :            : int wps_version_number = 0x20;
      20                 :            : int wps_testing_dummy_cred = 0;
      21                 :            : int wps_corrupt_pkhash = 0;
      22                 :            : #endif /* CONFIG_WPS_TESTING */
      23                 :            : 
      24                 :            : 
      25                 :            : /**
      26                 :            :  * wps_init - Initialize WPS Registration protocol data
      27                 :            :  * @cfg: WPS configuration
      28                 :            :  * Returns: Pointer to allocated data or %NULL on failure
      29                 :            :  *
      30                 :            :  * This function is used to initialize WPS data for a registration protocol
      31                 :            :  * instance (i.e., each run of registration protocol as a Registrar of
      32                 :            :  * Enrollee. The caller is responsible for freeing this data after the
      33                 :            :  * registration run has been completed by calling wps_deinit().
      34                 :            :  */
      35                 :        310 : struct wps_data * wps_init(const struct wps_config *cfg)
      36                 :            : {
      37                 :        310 :         struct wps_data *data = os_zalloc(sizeof(*data));
      38         [ -  + ]:        310 :         if (data == NULL)
      39                 :          0 :                 return NULL;
      40                 :        310 :         data->wps = cfg->wps;
      41                 :        310 :         data->registrar = cfg->registrar;
      42         [ +  + ]:        310 :         if (cfg->registrar) {
      43                 :        154 :                 os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN);
      44                 :            :         } else {
      45                 :        156 :                 os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN);
      46                 :        156 :                 os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
      47                 :            :         }
      48         [ +  + ]:        310 :         if (cfg->pin) {
      49                 :        147 :                 data->dev_pw_id = cfg->dev_pw_id;
      50                 :        147 :                 data->dev_password = os_malloc(cfg->pin_len);
      51         [ -  + ]:        147 :                 if (data->dev_password == NULL) {
      52                 :          0 :                         os_free(data);
      53                 :          0 :                         return NULL;
      54                 :            :                 }
      55                 :        147 :                 os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
      56                 :        147 :                 data->dev_password_len = cfg->pin_len;
      57                 :        147 :                 wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
      58                 :        147 :                                 data->dev_password, data->dev_password_len);
      59                 :            :         }
      60                 :            : 
      61                 :            : #ifdef CONFIG_WPS_NFC
      62 [ +  + ][ +  + ]:        310 :         if (cfg->pin == NULL &&
      63                 :        163 :             cfg->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)
      64                 :         15 :                 data->dev_pw_id = cfg->dev_pw_id;
      65                 :            : 
      66 [ +  + ][ +  + ]:        310 :         if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
                 [ +  + ]
      67                 :            :                 /* Keep AP PIN as alternative Device Password */
      68                 :          1 :                 data->alt_dev_pw_id = data->dev_pw_id;
      69                 :          1 :                 data->alt_dev_password = data->dev_password;
      70                 :          1 :                 data->alt_dev_password_len = data->dev_password_len;
      71                 :            : 
      72                 :          1 :                 data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
      73                 :          1 :                 data->dev_password =
      74                 :          1 :                         os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw));
      75         [ -  + ]:          1 :                 if (data->dev_password == NULL) {
      76                 :          0 :                         os_free(data);
      77                 :          0 :                         return NULL;
      78                 :            :                 }
      79                 :          1 :                 os_memcpy(data->dev_password,
      80                 :            :                           wpabuf_head(cfg->wps->ap_nfc_dev_pw),
      81                 :            :                           wpabuf_len(cfg->wps->ap_nfc_dev_pw));
      82                 :          1 :                 data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
      83                 :          1 :                 wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
      84                 :          1 :                             data->dev_password, data->dev_password_len);
      85                 :            :         }
      86                 :            : #endif /* CONFIG_WPS_NFC */
      87                 :            : 
      88                 :        310 :         data->pbc = cfg->pbc;
      89         [ +  + ]:        310 :         if (cfg->pbc) {
      90                 :            :                 /* Use special PIN '00000000' for PBC */
      91                 :         17 :                 data->dev_pw_id = DEV_PW_PUSHBUTTON;
      92                 :         17 :                 os_free(data->dev_password);
      93                 :         17 :                 data->dev_password = (u8 *) os_strdup("00000000");
      94         [ -  + ]:         17 :                 if (data->dev_password == NULL) {
      95                 :          0 :                         os_free(data);
      96                 :          0 :                         return NULL;
      97                 :            :                 }
      98                 :         17 :                 data->dev_password_len = 8;
      99                 :            :         }
     100                 :            : 
     101         [ +  + ]:        310 :         data->state = data->registrar ? RECV_M1 : SEND_M1;
     102                 :            : 
     103         [ +  + ]:        310 :         if (cfg->assoc_wps_ie) {
     104                 :            :                 struct wps_parse_attr attr;
     105                 :        144 :                 wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq",
     106                 :            :                                 cfg->assoc_wps_ie);
     107         [ -  + ]:        144 :                 if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) {
     108                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE "
     109                 :            :                                    "from (Re)AssocReq");
     110         [ -  + ]:        144 :                 } else if (attr.request_type == NULL) {
     111                 :          0 :                         wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute "
     112                 :            :                                    "in (Re)AssocReq WPS IE");
     113                 :            :                 } else {
     114                 :        144 :                         wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE "
     115                 :            :                                    "in (Re)AssocReq WPS IE): %d",
     116                 :        144 :                                    *attr.request_type);
     117                 :        144 :                         data->request_type = *attr.request_type;
     118                 :            :                 }
     119                 :            :         }
     120                 :            : 
     121         [ +  + ]:        310 :         if (cfg->new_ap_settings) {
     122                 :         11 :                 data->new_ap_settings =
     123                 :         11 :                         os_malloc(sizeof(*data->new_ap_settings));
     124         [ -  + ]:         11 :                 if (data->new_ap_settings == NULL) {
     125                 :          0 :                         os_free(data->dev_password);
     126                 :          0 :                         os_free(data);
     127                 :          0 :                         return NULL;
     128                 :            :                 }
     129                 :         11 :                 os_memcpy(data->new_ap_settings, cfg->new_ap_settings,
     130                 :            :                           sizeof(*data->new_ap_settings));
     131                 :            :         }
     132                 :            : 
     133         [ +  + ]:        310 :         if (cfg->peer_addr)
     134                 :        152 :                 os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN);
     135         [ +  + ]:        310 :         if (cfg->p2p_dev_addr)
     136                 :         77 :                 os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN);
     137                 :            : 
     138                 :        310 :         data->use_psk_key = cfg->use_psk_key;
     139                 :        310 :         data->pbc_in_m1 = cfg->pbc_in_m1;
     140                 :            : 
     141         [ +  + ]:        310 :         if (cfg->peer_pubkey_hash) {
     142                 :         15 :                 os_memcpy(data->peer_pubkey_hash, cfg->peer_pubkey_hash,
     143                 :            :                           WPS_OOB_PUBKEY_HASH_LEN);
     144                 :         15 :                 data->peer_pubkey_hash_set = 1;
     145                 :            :         }
     146                 :            : 
     147                 :        310 :         return data;
     148                 :            : }
     149                 :            : 
     150                 :            : 
     151                 :            : /**
     152                 :            :  * wps_deinit - Deinitialize WPS Registration protocol data
     153                 :            :  * @data: WPS Registration protocol data from wps_init()
     154                 :            :  */
     155                 :        310 : void wps_deinit(struct wps_data *data)
     156                 :            : {
     157                 :            : #ifdef CONFIG_WPS_NFC
     158 [ +  + ][ +  + ]:        310 :         if (data->registrar && data->nfc_pw_token)
     159                 :         23 :                 wps_registrar_remove_nfc_pw_token(data->wps->registrar,
     160                 :            :                                                   data->nfc_pw_token);
     161                 :            : #endif /* CONFIG_WPS_NFC */
     162                 :            : 
     163         [ +  + ]:        310 :         if (data->wps_pin_revealed) {
     164                 :          3 :                 wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and "
     165                 :            :                            "negotiation failed");
     166         [ +  - ]:          3 :                 if (data->registrar)
     167                 :          3 :                         wps_registrar_invalidate_pin(data->wps->registrar,
     168                 :          3 :                                                      data->uuid_e);
     169         [ +  + ]:        307 :         } else if (data->registrar)
     170                 :        151 :                 wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
     171                 :            : 
     172                 :        310 :         wpabuf_free(data->dh_privkey);
     173                 :        310 :         wpabuf_free(data->dh_pubkey_e);
     174                 :        310 :         wpabuf_free(data->dh_pubkey_r);
     175                 :        310 :         wpabuf_free(data->last_msg);
     176                 :        310 :         os_free(data->dev_password);
     177                 :        310 :         os_free(data->alt_dev_password);
     178                 :        310 :         os_free(data->new_psk);
     179                 :        310 :         wps_device_data_free(&data->peer_dev);
     180                 :        310 :         os_free(data->new_ap_settings);
     181                 :        310 :         dh5_free(data->dh_ctx);
     182                 :        310 :         os_free(data);
     183                 :        310 : }
     184                 :            : 
     185                 :            : 
     186                 :            : /**
     187                 :            :  * wps_process_msg - Process a WPS message
     188                 :            :  * @wps: WPS Registration protocol data from wps_init()
     189                 :            :  * @op_code: Message OP Code
     190                 :            :  * @msg: Message data
     191                 :            :  * Returns: Processing result
     192                 :            :  *
     193                 :            :  * This function is used to process WPS messages with OP Codes WSC_ACK,
     194                 :            :  * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is
     195                 :            :  * responsible for reassembling the messages before calling this function.
     196                 :            :  * Response to this message is built by calling wps_get_msg().
     197                 :            :  */
     198                 :       1214 : enum wps_process_res wps_process_msg(struct wps_data *wps,
     199                 :            :                                      enum wsc_op_code op_code,
     200                 :            :                                      const struct wpabuf *msg)
     201                 :            : {
     202         [ +  + ]:       1214 :         if (wps->registrar)
     203                 :        692 :                 return wps_registrar_process_msg(wps, op_code, msg);
     204                 :            :         else
     205                 :       1214 :                 return wps_enrollee_process_msg(wps, op_code, msg);
     206                 :            : }
     207                 :            : 
     208                 :            : 
     209                 :            : /**
     210                 :            :  * wps_get_msg - Build a WPS message
     211                 :            :  * @wps: WPS Registration protocol data from wps_init()
     212                 :            :  * @op_code: Buffer for returning message OP Code
     213                 :            :  * Returns: The generated WPS message or %NULL on failure
     214                 :            :  *
     215                 :            :  * This function is used to build a response to a message processed by calling
     216                 :            :  * wps_process_msg(). The caller is responsible for freeing the buffer.
     217                 :            :  */
     218                 :       1194 : struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code)
     219                 :            : {
     220         [ +  + ]:       1194 :         if (wps->registrar)
     221                 :        545 :                 return wps_registrar_get_msg(wps, op_code);
     222                 :            :         else
     223                 :       1194 :                 return wps_enrollee_get_msg(wps, op_code);
     224                 :            : }
     225                 :            : 
     226                 :            : 
     227                 :            : /**
     228                 :            :  * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC
     229                 :            :  * @msg: WPS IE contents from Beacon or Probe Response frame
     230                 :            :  * Returns: 1 if PBC Registrar is active, 0 if not
     231                 :            :  */
     232                 :        327 : int wps_is_selected_pbc_registrar(const struct wpabuf *msg)
     233                 :            : {
     234                 :            :         struct wps_parse_attr attr;
     235                 :            : 
     236                 :            :         /*
     237                 :            :          * In theory, this could also verify that attr.sel_reg_config_methods
     238                 :            :          * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations
     239                 :            :          * do not set Selected Registrar Config Methods attribute properly, so
     240                 :            :          * it is safer to just use Device Password ID here.
     241                 :            :          */
     242                 :            : 
     243 [ +  - ][ +  + ]:        327 :         if (wps_parse_msg(msg, &attr) < 0 ||
     244 [ +  - ][ +  - ]:        225 :             !attr.selected_registrar || *attr.selected_registrar == 0 ||
     245         [ +  + ]:        225 :             !attr.dev_password_id ||
     246                 :        225 :             WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
     247                 :        260 :                 return 0;
     248                 :            : 
     249                 :            : #ifdef CONFIG_WPS_STRICT
     250                 :            :         if (!attr.sel_reg_config_methods ||
     251                 :            :             !(WPA_GET_BE16(attr.sel_reg_config_methods) &
     252                 :            :               WPS_CONFIG_PUSHBUTTON))
     253                 :            :                 return 0;
     254                 :            : #endif /* CONFIG_WPS_STRICT */
     255                 :            : 
     256                 :        327 :         return 1;
     257                 :            : }
     258                 :            : 
     259                 :            : 
     260                 :        115 : static int is_selected_pin_registrar(struct wps_parse_attr *attr)
     261                 :            : {
     262                 :            :         /*
     263                 :            :          * In theory, this could also verify that attr.sel_reg_config_methods
     264                 :            :          * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD,
     265                 :            :          * but some deployed AP implementations do not set Selected Registrar
     266                 :            :          * Config Methods attribute properly, so it is safer to just use
     267                 :            :          * Device Password ID here.
     268                 :            :          */
     269                 :            : 
     270 [ +  + ][ -  + ]:        115 :         if (!attr->selected_registrar || *attr->selected_registrar == 0)
     271                 :        101 :                 return 0;
     272                 :            : 
     273   [ +  -  -  + ]:         28 :         if (attr->dev_password_id != NULL &&
     274                 :         14 :             WPA_GET_BE16(attr->dev_password_id) == DEV_PW_PUSHBUTTON)
     275                 :          0 :                 return 0;
     276                 :            : 
     277                 :            : #ifdef CONFIG_WPS_STRICT
     278                 :            :         if (!attr->sel_reg_config_methods ||
     279                 :            :             !(WPA_GET_BE16(attr->sel_reg_config_methods) &
     280                 :            :               (WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD)))
     281                 :            :                 return 0;
     282                 :            : #endif /* CONFIG_WPS_STRICT */
     283                 :            : 
     284                 :        115 :         return 1;
     285                 :            : }
     286                 :            : 
     287                 :            : 
     288                 :            : /**
     289                 :            :  * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN
     290                 :            :  * @msg: WPS IE contents from Beacon or Probe Response frame
     291                 :            :  * Returns: 1 if PIN Registrar is active, 0 if not
     292                 :            :  */
     293                 :        115 : int wps_is_selected_pin_registrar(const struct wpabuf *msg)
     294                 :            : {
     295                 :            :         struct wps_parse_attr attr;
     296                 :            : 
     297         [ -  + ]:        115 :         if (wps_parse_msg(msg, &attr) < 0)
     298                 :          0 :                 return 0;
     299                 :            : 
     300                 :        115 :         return is_selected_pin_registrar(&attr);
     301                 :            : }
     302                 :            : 
     303                 :            : 
     304                 :            : /**
     305                 :            :  * wps_is_addr_authorized - Check whether WPS IE authorizes MAC address
     306                 :            :  * @msg: WPS IE contents from Beacon or Probe Response frame
     307                 :            :  * @addr: MAC address to search for
     308                 :            :  * @ver1_compat: Whether to use version 1 compatibility mode
     309                 :            :  * Returns: 2 if the specified address is explicit authorized, 1 if address is
     310                 :            :  * authorized (broadcast), 0 if not
     311                 :            :  */
     312                 :        616 : int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
     313                 :            :                            int ver1_compat)
     314                 :            : {
     315                 :            :         struct wps_parse_attr attr;
     316                 :            :         unsigned int i;
     317                 :            :         const u8 *pos;
     318                 :        616 :         const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     319                 :            : 
     320         [ -  + ]:        616 :         if (wps_parse_msg(msg, &attr) < 0)
     321                 :          0 :                 return 0;
     322                 :            : 
     323 [ -  + ][ #  # ]:        616 :         if (!attr.version2 && ver1_compat) {
     324                 :            :                 /*
     325                 :            :                  * Version 1.0 AP - AuthorizedMACs not used, so revert back to
     326                 :            :                  * old mechanism of using SelectedRegistrar.
     327                 :            :                  */
     328                 :          0 :                 return is_selected_pin_registrar(&attr);
     329                 :            :         }
     330                 :            : 
     331         [ +  + ]:        616 :         if (!attr.authorized_macs)
     332                 :        227 :                 return 0;
     333                 :            : 
     334                 :        389 :         pos = attr.authorized_macs;
     335         [ +  + ]:        407 :         for (i = 0; i < attr.authorized_macs_len / ETH_ALEN; i++) {
     336         [ +  + ]:        389 :                 if (os_memcmp(pos, addr, ETH_ALEN) == 0)
     337                 :        143 :                         return 2;
     338         [ +  + ]:        246 :                 if (os_memcmp(pos, bcast, ETH_ALEN) == 0)
     339                 :        228 :                         return 1;
     340                 :         18 :                 pos += ETH_ALEN;
     341                 :            :         }
     342                 :            : 
     343                 :        616 :         return 0;
     344                 :            : }
     345                 :            : 
     346                 :            : 
     347                 :            : /**
     348                 :            :  * wps_ap_priority_compar - Prioritize WPS IE from two APs
     349                 :            :  * @wps_a: WPS IE contents from Beacon or Probe Response frame
     350                 :            :  * @wps_b: WPS IE contents from Beacon or Probe Response frame
     351                 :            :  * Returns: 1 if wps_b is considered more likely selection for WPS
     352                 :            :  * provisioning, -1 if wps_a is considered more like, or 0 if no preference
     353                 :            :  */
     354                 :         26 : int wps_ap_priority_compar(const struct wpabuf *wps_a,
     355                 :            :                            const struct wpabuf *wps_b)
     356                 :            : {
     357                 :            :         struct wps_parse_attr attr_a, attr_b;
     358                 :            :         int sel_a, sel_b;
     359                 :            : 
     360 [ +  - ][ -  + ]:         26 :         if (wps_a == NULL || wps_parse_msg(wps_a, &attr_a) < 0)
     361                 :          0 :                 return 1;
     362 [ +  - ][ -  + ]:         26 :         if (wps_b == NULL || wps_parse_msg(wps_b, &attr_b) < 0)
     363                 :          0 :                 return -1;
     364                 :            : 
     365 [ +  + ][ +  - ]:         26 :         sel_a = attr_a.selected_registrar && *attr_a.selected_registrar != 0;
     366 [ +  + ][ +  - ]:         26 :         sel_b = attr_b.selected_registrar && *attr_b.selected_registrar != 0;
     367                 :            : 
     368 [ +  + ][ +  + ]:         26 :         if (sel_a && !sel_b)
     369                 :          1 :                 return -1;
     370 [ +  + ][ +  + ]:         25 :         if (!sel_a && sel_b)
     371                 :         12 :                 return 1;
     372                 :            : 
     373                 :         26 :         return 0;
     374                 :            : }
     375                 :            : 
     376                 :            : 
     377                 :            : /**
     378                 :            :  * wps_get_uuid_e - Get UUID-E from WPS IE
     379                 :            :  * @msg: WPS IE contents from Beacon or Probe Response frame
     380                 :            :  * Returns: Pointer to UUID-E or %NULL if not included
     381                 :            :  *
     382                 :            :  * The returned pointer is to the msg contents and it remains valid only as
     383                 :            :  * long as the msg buffer is valid.
     384                 :            :  */
     385                 :         20 : const u8 * wps_get_uuid_e(const struct wpabuf *msg)
     386                 :            : {
     387                 :            :         struct wps_parse_attr attr;
     388                 :            : 
     389         [ -  + ]:         20 :         if (wps_parse_msg(msg, &attr) < 0)
     390                 :          0 :                 return NULL;
     391                 :         20 :         return attr.uuid_e;
     392                 :            : }
     393                 :            : 
     394                 :            : 
     395                 :            : /**
     396                 :            :  * wps_is_20 - Check whether WPS attributes claim support for WPS 2.0
     397                 :            :  */
     398                 :        144 : int wps_is_20(const struct wpabuf *msg)
     399                 :            : {
     400                 :            :         struct wps_parse_attr attr;
     401                 :            : 
     402 [ +  - ][ -  + ]:        144 :         if (msg == NULL || wps_parse_msg(msg, &attr) < 0)
     403                 :          0 :                 return 0;
     404                 :        144 :         return attr.version2 != NULL;
     405                 :            : }
     406                 :            : 
     407                 :            : 
     408                 :            : /**
     409                 :            :  * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request
     410                 :            :  * @req_type: Value for Request Type attribute
     411                 :            :  * Returns: WPS IE or %NULL on failure
     412                 :            :  *
     413                 :            :  * The caller is responsible for freeing the buffer.
     414                 :            :  */
     415                 :        144 : struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type)
     416                 :            : {
     417                 :            :         struct wpabuf *ie;
     418                 :            :         u8 *len;
     419                 :            : 
     420                 :        144 :         wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association "
     421                 :            :                    "Request");
     422                 :        144 :         ie = wpabuf_alloc(100);
     423         [ -  + ]:        144 :         if (ie == NULL)
     424                 :          0 :                 return NULL;
     425                 :            : 
     426                 :        144 :         wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
     427                 :        144 :         len = wpabuf_put(ie, 1);
     428                 :        144 :         wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
     429                 :            : 
     430   [ +  -  +  - ]:        288 :         if (wps_build_version(ie) ||
     431         [ -  + ]:        288 :             wps_build_req_type(ie, req_type) ||
     432                 :        144 :             wps_build_wfa_ext(ie, 0, NULL, 0)) {
     433                 :          0 :                 wpabuf_free(ie);
     434                 :          0 :                 return NULL;
     435                 :            :         }
     436                 :            : 
     437                 :        144 :         *len = wpabuf_len(ie) - 2;
     438                 :            : 
     439                 :        144 :         return ie;
     440                 :            : }
     441                 :            : 
     442                 :            : 
     443                 :            : /**
     444                 :            :  * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response
     445                 :            :  * Returns: WPS IE or %NULL on failure
     446                 :            :  *
     447                 :            :  * The caller is responsible for freeing the buffer.
     448                 :            :  */
     449                 :        982 : struct wpabuf * wps_build_assoc_resp_ie(void)
     450                 :            : {
     451                 :            :         struct wpabuf *ie;
     452                 :            :         u8 *len;
     453                 :            : 
     454                 :        982 :         wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association "
     455                 :            :                    "Response");
     456                 :        982 :         ie = wpabuf_alloc(100);
     457         [ -  + ]:        982 :         if (ie == NULL)
     458                 :          0 :                 return NULL;
     459                 :            : 
     460                 :        982 :         wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
     461                 :        982 :         len = wpabuf_put(ie, 1);
     462                 :        982 :         wpabuf_put_be32(ie, WPS_DEV_OUI_WFA);
     463                 :            : 
     464   [ +  -  +  - ]:       1964 :         if (wps_build_version(ie) ||
     465         [ -  + ]:       1964 :             wps_build_resp_type(ie, WPS_RESP_AP) ||
     466                 :        982 :             wps_build_wfa_ext(ie, 0, NULL, 0)) {
     467                 :          0 :                 wpabuf_free(ie);
     468                 :          0 :                 return NULL;
     469                 :            :         }
     470                 :            : 
     471                 :        982 :         *len = wpabuf_len(ie) - 2;
     472                 :            : 
     473                 :        982 :         return ie;
     474                 :            : }
     475                 :            : 
     476                 :            : 
     477                 :            : /**
     478                 :            :  * wps_build_probe_req_ie - Build WPS IE for Probe Request
     479                 :            :  * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for
     480                 :            :  * most other use cases)
     481                 :            :  * @dev: Device attributes
     482                 :            :  * @uuid: Own UUID
     483                 :            :  * @req_type: Value for Request Type attribute
     484                 :            :  * @num_req_dev_types: Number of requested device types
     485                 :            :  * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or
     486                 :            :  *      %NULL if none
     487                 :            :  * Returns: WPS IE or %NULL on failure
     488                 :            :  *
     489                 :            :  * The caller is responsible for freeing the buffer.
     490                 :            :  */
     491                 :       1355 : struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
     492                 :            :                                        const u8 *uuid,
     493                 :            :                                        enum wps_request_type req_type,
     494                 :            :                                        unsigned int num_req_dev_types,
     495                 :            :                                        const u8 *req_dev_types)
     496                 :            : {
     497                 :            :         struct wpabuf *ie;
     498                 :            : 
     499                 :       1355 :         wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request");
     500                 :            : 
     501                 :       1355 :         ie = wpabuf_alloc(500);
     502         [ -  + ]:       1355 :         if (ie == NULL)
     503                 :          0 :                 return NULL;
     504                 :            : 
     505   [ +  -  +  - ]:       2710 :         if (wps_build_version(ie) ||
     506         [ +  - ]:       2710 :             wps_build_req_type(ie, req_type) ||
     507         [ +  - ]:       2710 :             wps_build_config_methods(ie, dev->config_methods) ||
     508         [ +  - ]:       2710 :             wps_build_uuid_e(ie, uuid) ||
     509         [ +  - ]:       2710 :             wps_build_primary_dev_type(dev, ie) ||
     510         [ +  - ]:       2710 :             wps_build_rf_bands(dev, ie, 0) ||
     511         [ +  - ]:       2710 :             wps_build_assoc_state(NULL, ie) ||
     512         [ +  - ]:       2710 :             wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
     513         [ +  - ]:       2710 :             wps_build_dev_password_id(ie, pw_id) ||
     514                 :            : #ifdef CONFIG_WPS2
     515         [ +  - ]:       2710 :             wps_build_manufacturer(dev, ie) ||
     516         [ +  - ]:       2710 :             wps_build_model_name(dev, ie) ||
     517         [ +  - ]:       2710 :             wps_build_model_number(dev, ie) ||
     518         [ +  - ]:       2710 :             wps_build_dev_name(dev, ie) ||
     519         [ +  - ]:       2710 :             wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) ||
     520                 :            : #endif /* CONFIG_WPS2 */
     521                 :       1355 :             wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types)
     522         [ -  + ]:       1355 :             ||
     523                 :       1355 :             wps_build_secondary_dev_type(dev, ie)
     524                 :            :                 ) {
     525                 :          0 :                 wpabuf_free(ie);
     526                 :          0 :                 return NULL;
     527                 :            :         }
     528                 :            : 
     529                 :            : #ifndef CONFIG_WPS2
     530                 :            :         if (dev->p2p && wps_build_dev_name(dev, ie)) {
     531                 :            :                 wpabuf_free(ie);
     532                 :            :                 return NULL;
     533                 :            :         }
     534                 :            : #endif /* CONFIG_WPS2 */
     535                 :            : 
     536                 :       1355 :         return wps_ie_encapsulate(ie);
     537                 :            : }
     538                 :            : 
     539                 :            : 
     540                 :        144 : void wps_free_pending_msgs(struct upnp_pending_message *msgs)
     541                 :            : {
     542                 :            :         struct upnp_pending_message *p, *prev;
     543                 :        144 :         p = msgs;
     544         [ -  + ]:        144 :         while (p) {
     545                 :          0 :                 prev = p;
     546                 :          0 :                 p = p->next;
     547                 :          0 :                 wpabuf_free(prev->msg);
     548                 :          0 :                 os_free(prev);
     549                 :            :         }
     550                 :        144 : }
     551                 :            : 
     552                 :            : 
     553                 :         20 : int wps_attr_text(struct wpabuf *data, char *buf, char *end)
     554                 :            : {
     555                 :            :         struct wps_parse_attr attr;
     556                 :         20 :         char *pos = buf;
     557                 :            :         int ret;
     558                 :            : 
     559         [ -  + ]:         20 :         if (wps_parse_msg(data, &attr) < 0)
     560                 :          0 :                 return -1;
     561                 :            : 
     562         [ +  - ]:         20 :         if (attr.wps_state) {
     563         [ +  + ]:         20 :                 if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED)
     564                 :          4 :                         ret = os_snprintf(pos, end - pos,
     565                 :            :                                           "wps_state=unconfigured\n");
     566         [ +  - ]:         16 :                 else if (*attr.wps_state == WPS_STATE_CONFIGURED)
     567                 :         16 :                         ret = os_snprintf(pos, end - pos,
     568                 :            :                                           "wps_state=configured\n");
     569                 :            :                 else
     570                 :          0 :                         ret = 0;
     571 [ +  - ][ -  + ]:         20 :                 if (ret < 0 || ret >= end - pos)
     572                 :          0 :                         return pos - buf;
     573                 :         20 :                 pos += ret;
     574                 :            :         }
     575                 :            : 
     576 [ -  + ][ #  # ]:         20 :         if (attr.ap_setup_locked && *attr.ap_setup_locked) {
     577                 :          0 :                 ret = os_snprintf(pos, end - pos,
     578                 :            :                                   "wps_ap_setup_locked=1\n");
     579 [ #  # ][ #  # ]:          0 :                 if (ret < 0 || ret >= end - pos)
     580                 :          0 :                         return pos - buf;
     581                 :          0 :                 pos += ret;
     582                 :            :         }
     583                 :            : 
     584 [ +  + ][ +  - ]:         20 :         if (attr.selected_registrar && *attr.selected_registrar) {
     585                 :         11 :                 ret = os_snprintf(pos, end - pos,
     586                 :            :                                   "wps_selected_registrar=1\n");
     587 [ +  - ][ -  + ]:         11 :                 if (ret < 0 || ret >= end - pos)
     588                 :          0 :                         return pos - buf;
     589                 :         11 :                 pos += ret;
     590                 :            :         }
     591                 :            : 
     592         [ +  + ]:         20 :         if (attr.dev_password_id) {
     593                 :         11 :                 ret = os_snprintf(pos, end - pos,
     594                 :            :                                   "wps_device_password_id=%u\n",
     595                 :         11 :                                   WPA_GET_BE16(attr.dev_password_id));
     596 [ -  + ][ +  - ]:         11 :                 if (ret < 0 || ret >= end - pos)
     597                 :          0 :                         return pos - buf;
     598                 :         11 :                 pos += ret;
     599                 :            :         }
     600                 :            : 
     601         [ +  + ]:         20 :         if (attr.sel_reg_config_methods) {
     602                 :         11 :                 ret = os_snprintf(pos, end - pos,
     603                 :            :                                   "wps_selected_registrar_config_methods="
     604                 :            :                                   "0x%04x\n",
     605                 :         11 :                                   WPA_GET_BE16(attr.sel_reg_config_methods));
     606 [ -  + ][ +  - ]:         11 :                 if (ret < 0 || ret >= end - pos)
     607                 :          0 :                         return pos - buf;
     608                 :         11 :                 pos += ret;
     609                 :            :         }
     610                 :            : 
     611         [ +  - ]:         20 :         if (attr.primary_dev_type) {
     612                 :            :                 char devtype[WPS_DEV_TYPE_BUFSIZE];
     613                 :         20 :                 ret = os_snprintf(pos, end - pos,
     614                 :            :                                   "wps_primary_device_type=%s\n",
     615                 :            :                                   wps_dev_type_bin2str(attr.primary_dev_type,
     616                 :            :                                                        devtype,
     617                 :            :                                                        sizeof(devtype)));
     618 [ -  + ][ +  - ]:         20 :                 if (ret < 0 || ret >= end - pos)
     619                 :          0 :                         return pos - buf;
     620                 :         20 :                 pos += ret;
     621                 :            :         }
     622                 :            : 
     623         [ +  - ]:         20 :         if (attr.dev_name) {
     624                 :         20 :                 char *str = os_malloc(attr.dev_name_len + 1);
     625                 :            :                 size_t i;
     626         [ -  + ]:         20 :                 if (str == NULL)
     627                 :          0 :                         return pos - buf;
     628         [ +  + ]:        119 :                 for (i = 0; i < attr.dev_name_len; i++) {
     629         [ -  + ]:         99 :                         if (attr.dev_name[i] < 32)
     630                 :          0 :                                 str[i] = '_';
     631                 :            :                         else
     632                 :         99 :                                 str[i] = attr.dev_name[i];
     633                 :            :                 }
     634                 :         20 :                 str[i] = '\0';
     635                 :         20 :                 ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str);
     636                 :         20 :                 os_free(str);
     637 [ -  + ][ +  - ]:         20 :                 if (ret < 0 || ret >= end - pos)
     638                 :          0 :                         return pos - buf;
     639                 :         20 :                 pos += ret;
     640                 :            :         }
     641                 :            : 
     642         [ +  - ]:         20 :         if (attr.config_methods) {
     643                 :         20 :                 ret = os_snprintf(pos, end - pos,
     644                 :            :                                   "wps_config_methods=0x%04x\n",
     645                 :         20 :                                   WPA_GET_BE16(attr.config_methods));
     646 [ -  + ][ +  - ]:         20 :                 if (ret < 0 || ret >= end - pos)
     647                 :          0 :                         return pos - buf;
     648                 :         20 :                 pos += ret;
     649                 :            :         }
     650                 :            : 
     651                 :         20 :         return pos - buf;
     652                 :            : }
     653                 :            : 
     654                 :            : 
     655                 :          2 : const char * wps_ei_str(enum wps_error_indication ei)
     656                 :            : {
     657   [ -  -  +  -  :          2 :         switch (ei) {
                      - ]
     658                 :            :         case WPS_EI_NO_ERROR:
     659                 :          0 :                 return "No Error";
     660                 :            :         case WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED:
     661                 :          0 :                 return "TKIP Only Prohibited";
     662                 :            :         case WPS_EI_SECURITY_WEP_PROHIBITED:
     663                 :          2 :                 return "WEP Prohibited";
     664                 :            :         case WPS_EI_AUTH_FAILURE:
     665                 :          0 :                 return "Authentication Failure";
     666                 :            :         default:
     667                 :          2 :                 return "Unknown";
     668                 :            :         }
     669                 :            : }

Generated by: LCOV version 1.9