1 /* 2 * Wi-Fi Protected Setup - attribute building 3 * Copyright (c) 2008, Jouni Malinen <j (at) 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; 24 25 wpa_printf(MSG_DEBUG, "WPS: * Public Key"); 26 wpabuf_free(wps->dh_privkey); 27 if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { 28 wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); 29 wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); 30 wps->dh_ctx = wps->wps->dh_ctx; 31 wps->wps->dh_ctx = NULL; 32 pubkey = wpabuf_dup(wps->wps->dh_pubkey); 33 } else { 34 wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); 35 wps->dh_privkey = NULL; 36 dh5_free(wps->dh_ctx); 37 wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); 38 pubkey = wpabuf_zeropad(pubkey, 192); 39 } 40 if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { 41 wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " 42 "Diffie-Hellman handshake"); 43 wpabuf_free(pubkey); 44 return -1; 45 } 46 wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 47 wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); 48 49 wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); 50 wpabuf_put_be16(msg, wpabuf_len(pubkey)); 51 wpabuf_put_buf(msg, pubkey); 52 53 if (wps->registrar) { 54 wpabuf_free(wps->dh_pubkey_r); 55 wps->dh_pubkey_r = pubkey; 56 } else { 57 wpabuf_free(wps->dh_pubkey_e); 58 wps->dh_pubkey_e = pubkey; 59 } 60 61 return 0; 62 } 63 64 65 int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) 66 { 67 wpa_printf(MSG_DEBUG, "WPS: * Request Type"); 68 wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); 69 wpabuf_put_be16(msg, 1); 70 wpabuf_put_u8(msg, type); 71 return 0; 72 } 73 74 75 int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) 76 { 77 wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); 78 wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); 79 wpabuf_put_be16(msg, 1); 80 wpabuf_put_u8(msg, type); 81 return 0; 82 } 83 84 85 int wps_build_config_methods(struct wpabuf *msg, u16 methods) 86 { 87 wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); 88 wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); 89 wpabuf_put_be16(msg, 2); 90 wpabuf_put_be16(msg, methods); 91 return 0; 92 } 93 94 95 int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) 96 { 97 wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); 98 wpabuf_put_be16(msg, ATTR_UUID_E); 99 wpabuf_put_be16(msg, WPS_UUID_LEN); 100 wpabuf_put_data(msg, uuid, WPS_UUID_LEN); 101 return 0; 102 } 103 104 105 int wps_build_dev_password_id(struct wpabuf *msg, u16 id) 106 { 107 wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); 108 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 109 wpabuf_put_be16(msg, 2); 110 wpabuf_put_be16(msg, id); 111 return 0; 112 } 113 114 115 int wps_build_config_error(struct wpabuf *msg, u16 err) 116 { 117 wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); 118 wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); 119 wpabuf_put_be16(msg, 2); 120 wpabuf_put_be16(msg, err); 121 return 0; 122 } 123 124 125 int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) 126 { 127 u8 hash[SHA256_MAC_LEN]; 128 const u8 *addr[2]; 129 size_t len[2]; 130 131 if (wps->last_msg == NULL) { 132 wpa_printf(MSG_DEBUG, "WPS: Last message not available for " 133 "building authenticator"); 134 return -1; 135 } 136 137 /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) 138 * (M_curr* is M_curr without the Authenticator attribute) 139 */ 140 addr[0] = wpabuf_head(wps->last_msg); 141 len[0] = wpabuf_len(wps->last_msg); 142 addr[1] = wpabuf_head(msg); 143 len[1] = wpabuf_len(msg); 144 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); 145 146 wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); 147 wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); 148 wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); 149 wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); 150 151 return 0; 152 } 153 154 155 int wps_build_version(struct wpabuf *msg) 156 { 157 /* 158 * Note: This attribute is deprecated and set to hardcoded 0x10 for 159 * backwards compatibility reasons. The real version negotiation is 160 * done with Version2. 161 */ 162 wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); 163 wpabuf_put_be16(msg, ATTR_VERSION); 164 wpabuf_put_be16(msg, 1); 165 wpabuf_put_u8(msg, 0x10); 166 return 0; 167 } 168 169 170 int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, 171 const u8 *auth_macs, size_t auth_macs_count) 172 { 173 #ifdef CONFIG_WPS2 174 u8 *len; 175 176 wpabuf_put_be16(msg, ATTR_VENDOR_EXT); 177 len = wpabuf_put(msg, 2); /* to be filled */ 178 wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA); 179 180 wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); 181 wpabuf_put_u8(msg, WFA_ELEM_VERSION2); 182 wpabuf_put_u8(msg, 1); 183 wpabuf_put_u8(msg, WPS_VERSION); 184 185 if (req_to_enroll) { 186 wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); 187 wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL); 188 wpabuf_put_u8(msg, 1); 189 wpabuf_put_u8(msg, 1); 190 } 191 192 if (auth_macs && auth_macs_count) { 193 size_t i; 194 wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", 195 (int) auth_macs_count); 196 wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS); 197 wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN); 198 wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN); 199 for (i = 0; i < auth_macs_count; i++) 200 wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, 201 MAC2STR(&auth_macs[i * ETH_ALEN])); 202 } 203 204 WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); 205 #endif /* CONFIG_WPS2 */ 206 207 #ifdef CONFIG_WPS_TESTING 208 if (WPS_VERSION > 0x20) { 209 wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " 210 "attribute"); 211 wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST); 212 wpabuf_put_be16(msg, 1); 213 wpabuf_put_u8(msg, 42); 214 } 215 #endif /* CONFIG_WPS_TESTING */ 216 return 0; 217 } 218 219 220 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) 221 { 222 wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); 223 wpabuf_put_be16(msg, ATTR_MSG_TYPE); 224 wpabuf_put_be16(msg, 1); 225 wpabuf_put_u8(msg, msg_type); 226 return 0; 227 } 228 229 230 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) 231 { 232 wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); 233 wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); 234 wpabuf_put_be16(msg, WPS_NONCE_LEN); 235 wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); 236 return 0; 237 } 238 239 240 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) 241 { 242 wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); 243 wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); 244 wpabuf_put_be16(msg, WPS_NONCE_LEN); 245 wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); 246 return 0; 247 } 248 249 250 int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) 251 { 252 u16 auth_types = WPS_AUTH_TYPES; 253 #ifdef CONFIG_WPS2 254 auth_types &= ~WPS_AUTH_SHARED; 255 #endif /* CONFIG_WPS2 */ 256 wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); 257 wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); 258 wpabuf_put_be16(msg, 2); 259 wpabuf_put_be16(msg, auth_types); 260 return 0; 261 } 262 263 264 int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) 265 { 266 u16 encr_types = WPS_ENCR_TYPES; 267 #ifdef CONFIG_WPS2 268 encr_types &= ~WPS_ENCR_WEP; 269 #endif /* CONFIG_WPS2 */ 270 wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); 271 wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); 272 wpabuf_put_be16(msg, 2); 273 wpabuf_put_be16(msg, encr_types); 274 return 0; 275 } 276 277 278 int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) 279 { 280 wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); 281 wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); 282 wpabuf_put_be16(msg, 1); 283 wpabuf_put_u8(msg, WPS_CONN_ESS); 284 return 0; 285 } 286 287 288 int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) 289 { 290 wpa_printf(MSG_DEBUG, "WPS: * Association State"); 291 wpabuf_put_be16(msg, ATTR_ASSOC_STATE); 292 wpabuf_put_be16(msg, 2); 293 wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); 294 return 0; 295 } 296 297 298 int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) 299 { 300 u8 hash[SHA256_MAC_LEN]; 301 302 wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); 303 hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), 304 wpabuf_len(msg), hash); 305 306 wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); 307 wpabuf_put_be16(msg, WPS_KWA_LEN); 308 wpabuf_put_data(msg, hash, WPS_KWA_LEN); 309 return 0; 310 } 311 312 313 int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, 314 struct wpabuf *plain) 315 { 316 size_t pad_len; 317 const size_t block_size = 16; 318 u8 *iv, *data; 319 320 wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); 321 322 /* PKCS#5 v2.0 pad */ 323 pad_len = block_size - wpabuf_len(plain) % block_size; 324 os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); 325 326 wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); 327 wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); 328 329 iv = wpabuf_put(msg, block_size); 330 if (random_get_bytes(iv, block_size) < 0) 331 return -1; 332 333 data = wpabuf_put(msg, 0); 334 wpabuf_put_buf(msg, plain); 335 if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) 336 return -1; 337 338 return 0; 339 } 340 341 342 #ifdef CONFIG_WPS_OOB 343 int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps) 344 { 345 size_t hash_len; 346 const u8 *addr[1]; 347 u8 pubkey_hash[WPS_HASH_LEN]; 348 u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN]; 349 350 wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password"); 351 352 addr[0] = wpabuf_head(wps->dh_pubkey); 353 hash_len = wpabuf_len(wps->dh_pubkey); 354 sha256_vector(1, addr, &hash_len, pubkey_hash); 355 356 if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) { 357 wpa_printf(MSG_ERROR, "WPS: device password id " 358 "generation error"); 359 return -1; 360 } 361 wps->oob_dev_pw_id |= 0x0010; 362 363 if (random_get_bytes(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) < 364 0) { 365 wpa_printf(MSG_ERROR, "WPS: OOB device password " 366 "generation error"); 367 return -1; 368 } 369 370 wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); 371 wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); 372 wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 373 wpabuf_put_be16(msg, wps->oob_dev_pw_id); 374 wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); 375 376 wpa_snprintf_hex_uppercase( 377 wpabuf_put(wps->oob_conf.dev_password, 378 wpabuf_size(wps->oob_conf.dev_password)), 379 wpabuf_size(wps->oob_conf.dev_password), 380 dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); 381 382 return 0; 383 } 384 #endif /* CONFIG_WPS_OOB */ 385 386 387 /* Encapsulate WPS IE data with one (or more, if needed) IE headers */ 388 struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) 389 { 390 struct wpabuf *ie; 391 const u8 *pos, *end; 392 393 ie = wpabuf_alloc(wpabuf_len(data) + 100); 394 if (ie == NULL) { 395 wpabuf_free(data); 396 return NULL; 397 } 398 399 pos = wpabuf_head(data); 400 end = pos + wpabuf_len(data); 401 402 while (end > pos) { 403 size_t frag_len = end - pos; 404 if (frag_len > 251) 405 frag_len = 251; 406 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 407 wpabuf_put_u8(ie, 4 + frag_len); 408 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 409 wpabuf_put_data(ie, pos, frag_len); 410 pos += frag_len; 411 } 412 413 wpabuf_free(data); 414 415 return ie; 416 } 417