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