LCOV - code coverage report
Current view: top level - src/wps - wps.c (source / functions) Hit Total Coverage
Test: wpa_supplicant hwsim test run 1388240082 Lines: 217 290 74.8 %
Date: 2013-12-28 Functions: 16 17 94.1 %
Branches: 143 243 58.8 %

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

Generated by: LCOV version 1.9