1 /* 2 * Wi-Fi Protected Setup - attribute parsing 3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "wps_i.h" 19 20 21 static int wps_set_attr(struct wps_parse_attr *attr, u16 type, 22 const u8 *pos, u16 len) 23 { 24 switch (type) { 25 case ATTR_VERSION: 26 if (len != 1) { 27 wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", 28 len); 29 return -1; 30 } 31 attr->version = pos; 32 break; 33 case ATTR_MSG_TYPE: 34 if (len != 1) { 35 wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " 36 "length %u", len); 37 return -1; 38 } 39 attr->msg_type = pos; 40 break; 41 case ATTR_ENROLLEE_NONCE: 42 if (len != WPS_NONCE_LEN) { 43 wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " 44 "length %u", len); 45 return -1; 46 } 47 attr->enrollee_nonce = pos; 48 break; 49 case ATTR_REGISTRAR_NONCE: 50 if (len != WPS_NONCE_LEN) { 51 wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " 52 "length %u", len); 53 return -1; 54 } 55 attr->registrar_nonce = pos; 56 break; 57 case ATTR_UUID_E: 58 if (len != WPS_UUID_LEN) { 59 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", 60 len); 61 return -1; 62 } 63 attr->uuid_e = pos; 64 break; 65 case ATTR_UUID_R: 66 if (len != WPS_UUID_LEN) { 67 wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", 68 len); 69 return -1; 70 } 71 attr->uuid_r = pos; 72 break; 73 case ATTR_AUTH_TYPE_FLAGS: 74 if (len != 2) { 75 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " 76 "Type Flags length %u", len); 77 return -1; 78 } 79 attr->auth_type_flags = pos; 80 break; 81 case ATTR_ENCR_TYPE_FLAGS: 82 if (len != 2) { 83 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " 84 "Flags length %u", len); 85 return -1; 86 } 87 attr->encr_type_flags = pos; 88 break; 89 case ATTR_CONN_TYPE_FLAGS: 90 if (len != 1) { 91 wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " 92 "Flags length %u", len); 93 return -1; 94 } 95 attr->conn_type_flags = pos; 96 break; 97 case ATTR_CONFIG_METHODS: 98 if (len != 2) { 99 wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " 100 "length %u", len); 101 return -1; 102 } 103 attr->config_methods = pos; 104 break; 105 case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: 106 if (len != 2) { 107 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " 108 "Registrar Config Methods length %u", len); 109 return -1; 110 } 111 attr->sel_reg_config_methods = pos; 112 break; 113 case ATTR_PRIMARY_DEV_TYPE: 114 if (len != sizeof(struct wps_dev_type)) { 115 wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " 116 "Type length %u", len); 117 return -1; 118 } 119 attr->primary_dev_type = pos; 120 break; 121 case ATTR_RF_BANDS: 122 if (len != 1) { 123 wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " 124 "%u", len); 125 return -1; 126 } 127 attr->rf_bands = pos; 128 break; 129 case ATTR_ASSOC_STATE: 130 if (len != 2) { 131 wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " 132 "length %u", len); 133 return -1; 134 } 135 attr->assoc_state = pos; 136 break; 137 case ATTR_CONFIG_ERROR: 138 if (len != 2) { 139 wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " 140 "Error length %u", len); 141 return -1; 142 } 143 attr->config_error = pos; 144 break; 145 case ATTR_DEV_PASSWORD_ID: 146 if (len != 2) { 147 wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " 148 "ID length %u", len); 149 return -1; 150 } 151 attr->dev_password_id = pos; 152 break; 153 case ATTR_OS_VERSION: 154 if (len != 4) { 155 wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " 156 "%u", len); 157 return -1; 158 } 159 attr->os_version = pos; 160 break; 161 case ATTR_WPS_STATE: 162 if (len != 1) { 163 wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " 164 "Setup State length %u", len); 165 return -1; 166 } 167 attr->wps_state = pos; 168 break; 169 case ATTR_AUTHENTICATOR: 170 if (len != WPS_AUTHENTICATOR_LEN) { 171 wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " 172 "length %u", len); 173 return -1; 174 } 175 attr->authenticator = pos; 176 break; 177 case ATTR_R_HASH1: 178 if (len != WPS_HASH_LEN) { 179 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", 180 len); 181 return -1; 182 } 183 attr->r_hash1 = pos; 184 break; 185 case ATTR_R_HASH2: 186 if (len != WPS_HASH_LEN) { 187 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", 188 len); 189 return -1; 190 } 191 attr->r_hash2 = pos; 192 break; 193 case ATTR_E_HASH1: 194 if (len != WPS_HASH_LEN) { 195 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", 196 len); 197 return -1; 198 } 199 attr->e_hash1 = pos; 200 break; 201 case ATTR_E_HASH2: 202 if (len != WPS_HASH_LEN) { 203 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", 204 len); 205 return -1; 206 } 207 attr->e_hash2 = pos; 208 break; 209 case ATTR_R_SNONCE1: 210 if (len != WPS_SECRET_NONCE_LEN) { 211 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " 212 "%u", len); 213 return -1; 214 } 215 attr->r_snonce1 = pos; 216 break; 217 case ATTR_R_SNONCE2: 218 if (len != WPS_SECRET_NONCE_LEN) { 219 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " 220 "%u", len); 221 return -1; 222 } 223 attr->r_snonce2 = pos; 224 break; 225 case ATTR_E_SNONCE1: 226 if (len != WPS_SECRET_NONCE_LEN) { 227 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " 228 "%u", len); 229 return -1; 230 } 231 attr->e_snonce1 = pos; 232 break; 233 case ATTR_E_SNONCE2: 234 if (len != WPS_SECRET_NONCE_LEN) { 235 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " 236 "%u", len); 237 return -1; 238 } 239 attr->e_snonce2 = pos; 240 break; 241 case ATTR_KEY_WRAP_AUTH: 242 if (len != WPS_KWA_LEN) { 243 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " 244 "Authenticator length %u", len); 245 return -1; 246 } 247 attr->key_wrap_auth = pos; 248 break; 249 case ATTR_AUTH_TYPE: 250 if (len != 2) { 251 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " 252 "Type length %u", len); 253 return -1; 254 } 255 attr->auth_type = pos; 256 break; 257 case ATTR_ENCR_TYPE: 258 if (len != 2) { 259 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " 260 "Type length %u", len); 261 return -1; 262 } 263 attr->encr_type = pos; 264 break; 265 case ATTR_NETWORK_INDEX: 266 if (len != 1) { 267 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " 268 "length %u", len); 269 return -1; 270 } 271 attr->network_idx = pos; 272 break; 273 case ATTR_NETWORK_KEY_INDEX: 274 if (len != 1) { 275 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " 276 "length %u", len); 277 return -1; 278 } 279 attr->network_key_idx = pos; 280 break; 281 case ATTR_MAC_ADDR: 282 if (len != ETH_ALEN) { 283 wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " 284 "length %u", len); 285 return -1; 286 } 287 attr->mac_addr = pos; 288 break; 289 case ATTR_KEY_PROVIDED_AUTO: 290 if (len != 1) { 291 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " 292 "Automatically length %u", len); 293 return -1; 294 } 295 attr->key_prov_auto = pos; 296 break; 297 case ATTR_802_1X_ENABLED: 298 if (len != 1) { 299 wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " 300 "length %u", len); 301 return -1; 302 } 303 attr->dot1x_enabled = pos; 304 break; 305 case ATTR_SELECTED_REGISTRAR: 306 if (len != 1) { 307 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" 308 " length %u", len); 309 return -1; 310 } 311 attr->selected_registrar = pos; 312 break; 313 case ATTR_REQUEST_TYPE: 314 if (len != 1) { 315 wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " 316 "length %u", len); 317 return -1; 318 } 319 attr->request_type = pos; 320 break; 321 case ATTR_RESPONSE_TYPE: 322 if (len != 1) { 323 wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " 324 "length %u", len); 325 return -1; 326 } 327 attr->request_type = pos; 328 break; 329 case ATTR_MANUFACTURER: 330 attr->manufacturer = pos; 331 attr->manufacturer_len = len; 332 break; 333 case ATTR_MODEL_NAME: 334 attr->model_name = pos; 335 attr->model_name_len = len; 336 break; 337 case ATTR_MODEL_NUMBER: 338 attr->model_number = pos; 339 attr->model_number_len = len; 340 break; 341 case ATTR_SERIAL_NUMBER: 342 attr->serial_number = pos; 343 attr->serial_number_len = len; 344 break; 345 case ATTR_DEV_NAME: 346 attr->dev_name = pos; 347 attr->dev_name_len = len; 348 break; 349 case ATTR_PUBLIC_KEY: 350 attr->public_key = pos; 351 attr->public_key_len = len; 352 break; 353 case ATTR_ENCR_SETTINGS: 354 attr->encr_settings = pos; 355 attr->encr_settings_len = len; 356 break; 357 case ATTR_CRED: 358 if (attr->num_cred >= MAX_CRED_COUNT) { 359 wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " 360 "attribute (max %d credentials)", 361 MAX_CRED_COUNT); 362 break; 363 } 364 attr->cred[attr->num_cred] = pos; 365 attr->cred_len[attr->num_cred] = len; 366 attr->num_cred++; 367 break; 368 case ATTR_SSID: 369 attr->ssid = pos; 370 attr->ssid_len = len; 371 break; 372 case ATTR_NETWORK_KEY: 373 attr->network_key = pos; 374 attr->network_key_len = len; 375 break; 376 case ATTR_EAP_TYPE: 377 attr->eap_type = pos; 378 attr->eap_type_len = len; 379 break; 380 case ATTR_EAP_IDENTITY: 381 attr->eap_identity = pos; 382 attr->eap_identity_len = len; 383 break; 384 default: 385 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " 386 "len=%u", type, len); 387 break; 388 } 389 390 return 0; 391 } 392 393 394 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) 395 { 396 const u8 *pos, *end; 397 u16 type, len; 398 399 os_memset(attr, 0, sizeof(*attr)); 400 pos = wpabuf_head(msg); 401 end = pos + wpabuf_len(msg); 402 403 while (pos < end) { 404 if (end - pos < 4) { 405 wpa_printf(MSG_DEBUG, "WPS: Invalid message - " 406 "%lu bytes remaining", 407 (unsigned long) (end - pos)); 408 return -1; 409 } 410 411 type = WPA_GET_BE16(pos); 412 pos += 2; 413 len = WPA_GET_BE16(pos); 414 pos += 2; 415 wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u", 416 type, len); 417 if (len > end - pos) { 418 wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); 419 return -1; 420 } 421 422 if (wps_set_attr(attr, type, pos, len) < 0) 423 return -1; 424 425 pos += len; 426 } 427 428 return 0; 429 } 430