1 /* 2 * Wi-Fi Protected Setup - attribute building 3 * Copyright (c) 2008-2016, 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/aes_wrap.h" 13 #include "crypto/crypto.h" 14 #include "crypto/dh_group5.h" 15 #include "crypto/sha256.h" 16 #include "crypto/random.h" 17 #include "common/ieee802_11_defs.h" 18 #include "wps_i.h" 19 20 21 int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) 22 { 23 struct wpabuf *pubkey = NULL; 24 25 wpa_printf(MSG_DEBUG, "WPS: * Public Key"); 26 wpabuf_clear_free(wps->dh_privkey); 27 wps->dh_privkey = NULL; 28 if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey && 29 wps->wps->dh_ctx) { 30 wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); 31 if (wps->wps->dh_pubkey == NULL) { 32 wpa_printf(MSG_DEBUG, 33 "WPS: wps->wps->dh_pubkey == NULL"); 34 return -1; 35 } 36 wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); 37 wps->dh_ctx = wps->wps->dh_ctx; 38 wps->wps->dh_ctx = NULL; 39 pubkey = wpabuf_dup(wps->wps->dh_pubkey); 40 #ifdef CONFIG_WPS_NFC 41 } else if ((wps->dev_pw_id >= 0x10 || 42 wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) && 43 (wps->wps->ap || 44 (wps->wps->ap_nfc_dh_pubkey && 45 wps->wps->ap_nfc_dev_pw_id == 46 DEV_PW_NFC_CONNECTION_HANDOVER && 47 wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) && 48 (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id || 49 wps->wps->ap_nfc_dh_pubkey)) { 50 wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); 51 if (wps->wps->ap_nfc_dh_privkey == NULL) { 52 wpa_printf(MSG_DEBUG, 53 "WPS: wps->wps->ap_nfc_dh_privkey == NULL"); 54 return -1; 55 } 56 if (wps->wps->ap_nfc_dh_pubkey == NULL) { 57 wpa_printf(MSG_DEBUG, 58 "WPS: wps->wps->ap_nfc_dh_pubkey == NULL"); 59 return -1; 60 } 61 wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); 62 pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); 63 if (wps->dh_privkey && pubkey) 64 wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); 65 #endif /* CONFIG_WPS_NFC */ 66 } else { 67 wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); 68 dh5_free(wps->dh_ctx); 69 wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); 70 pubkey = wpabuf_zeropad(pubkey, 192); 71 } 72 if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { 73 wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " 74 "Diffie-Hellman handshake"); 75 wpabuf_free(pubkey); 76 return -1; 77 } 78 wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 79 wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); 80 81 wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); 82 wpabuf_put_be16(msg, wpabuf_len(pubkey)); 83 wpabuf_put_buf(msg, pubkey); 84 85 if (wps->registrar) { 86 wpabuf_free(wps->dh_pubkey_r); 87 wps->dh_pubkey_r = pubkey; 88 } else { 89 wpabuf_free(wps->dh_pubkey_e); 90 wps->dh_pubkey_e = pubkey; 91 } 92 93 return 0; 94 } 95 96 97 int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) 98 { 99 wpa_printf(MSG_DEBUG, "WPS: * Request Type"); 100 wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); 101 wpabuf_put_be16(msg, 1); 102 wpabuf_put_u8(msg, type); 103 return 0; 104 } 105 106 107 int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) 108 { 109 wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); 110 wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); 111 wpabuf_put_be16(msg, 1); 112 wpabuf_put_u8(msg, type); 113 return 0; 114 } 115 116 117 int wps_build_config_methods(struct wpabuf *msg, u16 methods) 118 { 119 wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); 120 wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); 121 wpabuf_put_be16(msg, 2); 122 wpabuf_put_be16(msg, methods); 123 return 0; 124 } 125 126 127 int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) 128 { 129 if (wpabuf_tailroom(msg) < 4 + WPS_UUID_LEN) 130 return -1; 131 wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); 132 wpabuf_put_be16(msg, ATTR_UUID_E); 133 wpabuf_put_be16(msg, WPS_UUID_LEN); 134 wpabuf_put_data(msg, uuid, WPS_UUID_LEN); 135 return 0; 136 } 137 138 139 int wps_build_dev_password_id(struct wpabuf *msg, u16 id) 140 { 141 wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); 142 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 143 wpabuf_put_be16(msg, 2); 144 wpabuf_put_be16(msg, id); 145 return 0; 146 } 147 148 149 int wps_build_config_error(struct wpabuf *msg, u16 err) 150 { 151 wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); 152 wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); 153 wpabuf_put_be16(msg, 2); 154 wpabuf_put_be16(msg, err); 155 return 0; 156 } 157 158 159 int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) 160 { 161 u8 hash[SHA256_MAC_LEN]; 162 const u8 *addr[2]; 163 size_t len[2]; 164 165 if (wps->last_msg == NULL) { 166 wpa_printf(MSG_DEBUG, "WPS: Last message not available for " 167 "building authenticator"); 168 return -1; 169 } 170 171 /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) 172 * (M_curr* is M_curr without the Authenticator attribute) 173 */ 174 addr[0] = wpabuf_head(wps->last_msg); 175 len[0] = wpabuf_len(wps->last_msg); 176 addr[1] = wpabuf_head(msg); 177 len[1] = wpabuf_len(msg); 178 if (hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, 179 hash) < 0) 180 return -1; 181 182 wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); 183 wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); 184 wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); 185 wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); 186 187 return 0; 188 } 189 190 191 int wps_build_version(struct wpabuf *msg) 192 { 193 /* 194 * Note: This attribute is deprecated and set to hardcoded 0x10 for 195 * backwards compatibility reasons. The real version negotiation is 196 * done with Version2. 197 */ 198 if (wpabuf_tailroom(msg) < 5) 199 return -1; 200 wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); 201 wpabuf_put_be16(msg, ATTR_VERSION); 202 wpabuf_put_be16(msg, 1); 203 wpabuf_put_u8(msg, 0x10); 204 return 0; 205 } 206 207 208 int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, 209 const u8 *auth_macs, size_t auth_macs_count, 210 u8 multi_ap_subelem) 211 { 212 u8 *len; 213 214 #ifdef CONFIG_WPS_TESTING 215 if (WPS_VERSION == 0x10) 216 return 0; 217 #endif /* CONFIG_WPS_TESTING */ 218 219 if (wpabuf_tailroom(msg) < 220 7 + 3 + (req_to_enroll ? 3 : 0) + 221 (auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0)) 222 return -1; 223 wpabuf_put_be16(msg, ATTR_VENDOR_EXT); 224 len = wpabuf_put(msg, 2); /* to be filled */ 225 wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA); 226 227 wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); 228 wpabuf_put_u8(msg, WFA_ELEM_VERSION2); 229 wpabuf_put_u8(msg, 1); 230 wpabuf_put_u8(msg, WPS_VERSION); 231 232 if (req_to_enroll) { 233 wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); 234 wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL); 235 wpabuf_put_u8(msg, 1); 236 wpabuf_put_u8(msg, 1); 237 } 238 239 if (auth_macs && auth_macs_count) { 240 size_t i; 241 wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", 242 (int) auth_macs_count); 243 wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS); 244 wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN); 245 wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN); 246 for (i = 0; i < auth_macs_count; i++) 247 wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, 248 MAC2STR(&auth_macs[i * ETH_ALEN])); 249 } 250 251 if (multi_ap_subelem) { 252 wpa_printf(MSG_DEBUG, "WPS: * Multi-AP (0x%x)", 253 multi_ap_subelem); 254 wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP); 255 wpabuf_put_u8(msg, 1); /* length */ 256 wpabuf_put_u8(msg, multi_ap_subelem); 257 } 258 259 WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); 260 261 #ifdef CONFIG_WPS_TESTING 262 if (WPS_VERSION > 0x20) { 263 if (wpabuf_tailroom(msg) < 5) 264 return -1; 265 wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " 266 "attribute"); 267 wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST); 268 wpabuf_put_be16(msg, 1); 269 wpabuf_put_u8(msg, 42); 270 } 271 #endif /* CONFIG_WPS_TESTING */ 272 return 0; 273 } 274 275 276 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) 277 { 278 wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); 279 wpabuf_put_be16(msg, ATTR_MSG_TYPE); 280 wpabuf_put_be16(msg, 1); 281 wpabuf_put_u8(msg, msg_type); 282 return 0; 283 } 284 285 286 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) 287 { 288 wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); 289 wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); 290 wpabuf_put_be16(msg, WPS_NONCE_LEN); 291 wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); 292 return 0; 293 } 294 295 296 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) 297 { 298 wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); 299 wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); 300 wpabuf_put_be16(msg, WPS_NONCE_LEN); 301 wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); 302 return 0; 303 } 304 305 306 int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) 307 { 308 u16 auth_types = WPS_AUTH_TYPES; 309 /* WPA/WPA2-Enterprise enrollment not supported through WPS */ 310 auth_types &= ~WPS_AUTH_WPA; 311 auth_types &= ~WPS_AUTH_WPA2; 312 auth_types &= ~WPS_AUTH_SHARED; 313 #ifdef CONFIG_NO_TKIP 314 auth_types &= ~WPS_AUTH_WPAPSK; 315 #endif /* CONFIG_NO_TKIP */ 316 #ifdef CONFIG_WPS_TESTING 317 if (wps_force_auth_types_in_use) { 318 wpa_printf(MSG_DEBUG, 319 "WPS: Testing - replace auth type 0x%x with 0x%x", 320 auth_types, wps_force_auth_types); 321 auth_types = wps_force_auth_types; 322 } 323 #endif /* CONFIG_WPS_TESTING */ 324 wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags (0x%x)", 325 auth_types); 326 wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); 327 wpabuf_put_be16(msg, 2); 328 wpabuf_put_be16(msg, auth_types); 329 return 0; 330 } 331 332 333 int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) 334 { 335 u16 encr_types = WPS_ENCR_TYPES; 336 encr_types &= ~WPS_ENCR_WEP; 337 #ifdef CONFIG_NO_TKIP 338 encr_types &= ~WPS_ENCR_TKIP; 339 #endif /* CONFIG_NO_TKIP */ 340 #ifdef CONFIG_WPS_TESTING 341 if (wps_force_encr_types_in_use) { 342 wpa_printf(MSG_DEBUG, 343 "WPS: Testing - replace encr type 0x%x with 0x%x", 344 encr_types, wps_force_encr_types); 345 encr_types = wps_force_encr_types; 346 } 347 #endif /* CONFIG_WPS_TESTING */ 348 wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags (0x%x)", 349 encr_types); 350 wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); 351 wpabuf_put_be16(msg, 2); 352 wpabuf_put_be16(msg, encr_types); 353 return 0; 354 } 355 356 357 int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) 358 { 359 wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); 360 wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); 361 wpabuf_put_be16(msg, 1); 362 wpabuf_put_u8(msg, WPS_CONN_ESS); 363 return 0; 364 } 365 366 367 int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) 368 { 369 wpa_printf(MSG_DEBUG, "WPS: * Association State"); 370 wpabuf_put_be16(msg, ATTR_ASSOC_STATE); 371 wpabuf_put_be16(msg, 2); 372 wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); 373 return 0; 374 } 375 376 377 int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) 378 { 379 u8 hash[SHA256_MAC_LEN]; 380 381 wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); 382 if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), 383 wpabuf_len(msg), hash) < 0) 384 return -1; 385 386 wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); 387 wpabuf_put_be16(msg, WPS_KWA_LEN); 388 wpabuf_put_data(msg, hash, WPS_KWA_LEN); 389 return 0; 390 } 391 392 393 int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, 394 struct wpabuf *plain) 395 { 396 size_t pad_len; 397 const size_t block_size = 16; 398 u8 *iv, *data; 399 400 wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); 401 402 /* PKCS#5 v2.0 pad */ 403 pad_len = block_size - wpabuf_len(plain) % block_size; 404 os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); 405 406 wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); 407 wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); 408 409 iv = wpabuf_put(msg, block_size); 410 if (random_get_bytes(iv, block_size) < 0) 411 return -1; 412 413 data = wpabuf_put(msg, 0); 414 wpabuf_put_buf(msg, plain); 415 if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) 416 return -1; 417 418 return 0; 419 } 420 421 422 #ifdef CONFIG_WPS_OOB 423 int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, 424 const struct wpabuf *pubkey, const u8 *dev_pw, 425 size_t dev_pw_len) 426 { 427 size_t hash_len; 428 const u8 *addr[1]; 429 u8 pubkey_hash[WPS_HASH_LEN]; 430 431 wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password (dev_pw_id=%u)", 432 dev_pw_id); 433 addr[0] = wpabuf_head(pubkey); 434 hash_len = wpabuf_len(pubkey); 435 if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0) 436 return -1; 437 #ifdef CONFIG_WPS_TESTING 438 if (wps_corrupt_pkhash) { 439 wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash", 440 pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 441 wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash"); 442 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++; 443 } 444 #endif /* CONFIG_WPS_TESTING */ 445 446 wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); 447 wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len); 448 wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash", 449 pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 450 wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 451 wpabuf_put_be16(msg, dev_pw_id); 452 if (dev_pw) { 453 wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password", 454 dev_pw, dev_pw_len); 455 wpabuf_put_data(msg, dev_pw, dev_pw_len); 456 } 457 458 return 0; 459 } 460 #endif /* CONFIG_WPS_OOB */ 461 462 463 /* Encapsulate WPS IE data with one (or more, if needed) IE headers */ 464 struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) 465 { 466 struct wpabuf *ie; 467 const u8 *pos, *end; 468 469 ie = wpabuf_alloc(wpabuf_len(data) + 100); 470 if (ie == NULL) { 471 wpabuf_free(data); 472 return NULL; 473 } 474 475 pos = wpabuf_head(data); 476 end = pos + wpabuf_len(data); 477 478 while (end > pos) { 479 size_t frag_len = end - pos; 480 if (frag_len > 251) 481 frag_len = 251; 482 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 483 wpabuf_put_u8(ie, 4 + frag_len); 484 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 485 wpabuf_put_data(ie, pos, frag_len); 486 pos += frag_len; 487 } 488 489 wpabuf_free(data); 490 491 return ie; 492 } 493 494 495 int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr) 496 { 497 wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", 498 MAC2STR(addr)); 499 wpabuf_put_be16(msg, ATTR_MAC_ADDR); 500 wpabuf_put_be16(msg, ETH_ALEN); 501 wpabuf_put_data(msg, addr, ETH_ALEN); 502 return 0; 503 } 504 505 506 int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands) 507 { 508 wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", rf_bands); 509 wpabuf_put_be16(msg, ATTR_RF_BANDS); 510 wpabuf_put_be16(msg, 1); 511 wpabuf_put_u8(msg, rf_bands); 512 return 0; 513 } 514 515 516 int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel) 517 { 518 wpa_printf(MSG_DEBUG, "WPS: * AP Channel (%u)", ap_channel); 519 wpabuf_put_be16(msg, ATTR_AP_CHANNEL); 520 wpabuf_put_be16(msg, 2); 521 wpabuf_put_be16(msg, ap_channel); 522 return 0; 523 } 524