18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Protected Setup - attribute building 3de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/dh_group5.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pubkey; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Public Key"); 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->dh_privkey); 271e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt wps->dh_privkey = NULL; 281e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey && 291e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt wps->wps->dh_ctx) { 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); 311e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (wps->wps->dh_pubkey == NULL) { 321e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt wpa_printf(MSG_DEBUG, 331e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt "WPS: wps->wps->dh_pubkey == NULL"); 341e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return -1; 351e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt } 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_ctx = wps->wps->dh_ctx; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->wps->dh_ctx = NULL; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pubkey = wpabuf_dup(wps->wps->dh_pubkey); 4004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC 41cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } else if ((wps->dev_pw_id >= 0x10 || 42cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) && 43cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (wps->wps->ap || 44cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (wps->wps->ap_nfc_dh_pubkey && 45cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->wps->ap_nfc_dev_pw_id == 46cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt DEV_PW_NFC_CONNECTION_HANDOVER && 47cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) && 48cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id || 49cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->wps->ap_nfc_dh_pubkey)) { 5004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); 511e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (wps->wps->ap_nfc_dh_privkey == NULL) { 521e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt wpa_printf(MSG_DEBUG, 531e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt "WPS: wps->wps->ap_nfc_dh_privkey == NULL"); 541e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return -1; 551e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt } 561e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt if (wps->wps->ap_nfc_dh_pubkey == NULL) { 571e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt wpa_printf(MSG_DEBUG, 581e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt "WPS: wps->wps->ap_nfc_dh_pubkey == NULL"); 591e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt return -1; 601e78e76961664775f58b139f8c6388cfa0485f3dDmitry Shmidt } 6104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); 6204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); 6304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); 6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh5_free(wps->dh_ctx); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pubkey = wpabuf_zeropad(pubkey, 192); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Diffie-Hellman handshake"); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(pubkey); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, wpabuf_len(pubkey)); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(msg, pubkey); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->registrar) { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->dh_pubkey_r); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_pubkey_r = pubkey; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->dh_pubkey_e); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_pubkey_e = pubkey; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Request Type"); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, type); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, type); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_config_methods(struct wpabuf *msg, u16 methods) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, methods); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (wpabuf_tailroom(msg) < 4 + WPS_UUID_LEN) 12968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_UUID_E); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_UUID_LEN); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, uuid, WPS_UUID_LEN); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_dev_password_id(struct wpabuf *msg, u16 id) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, id); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_config_error(struct wpabuf *msg, u16 err) 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, err); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->last_msg == NULL) { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Last message not available for " 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "building authenticator"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (M_curr* is M_curr without the Authenticator attribute) 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wpabuf_head(wps->last_msg); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = wpabuf_len(wps->last_msg); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = wpabuf_head(msg); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = wpabuf_len(msg); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_version(struct wpabuf *msg) 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: This attribute is deprecated and set to hardcoded 0x10 for 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * backwards compatibility reasons. The real version negotiation is 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * done with Version2. 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (wpabuf_tailroom(msg) < 5) 19668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_VERSION); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 0x10); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *auth_macs, size_t auth_macs_count) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *len; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 210fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_WPS_TESTING 211fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (WPS_VERSION == 0x10) 212fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 213fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_WPS_TESTING */ 214fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 21568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (wpabuf_tailroom(msg) < 21668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 7 + 3 + (req_to_enroll ? 3 : 0) + 21768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt (auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0)) 21868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_VENDOR_EXT); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_put(msg, 2); /* to be filled */ 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, WFA_ELEM_VERSION2); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 1); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, WPS_VERSION); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req_to_enroll) { 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 1); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 1); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_macs && auth_macs_count) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) auth_macs_count); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < auth_macs_count; i++) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(&auth_macs[i * ETH_ALEN])); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_TESTING 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPS_VERSION > 0x20) { 25168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (wpabuf_tailroom(msg) < 5) 25268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attribute"); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 42); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_TESTING */ 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_MSG_TYPE); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, msg_type); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_NONCE_LEN); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_NONCE_LEN); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 auth_types = WPS_AUTH_TYPES; 2976cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt /* WPA/WPA2-Enterprise enrollment not supported through WPS */ 2986cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt auth_types &= ~WPS_AUTH_WPA; 2996cb1f6521a84955752c2b99100cf1df87637f86cDmitry Shmidt auth_types &= ~WPS_AUTH_WPA2; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_types &= ~WPS_AUTH_SHARED; 301de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#ifdef CONFIG_WPS_TESTING 302de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (wps_force_auth_types_in_use) { 303de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt wpa_printf(MSG_DEBUG, 304de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt "WPS: Testing - replace auth type 0x%x with 0x%x", 305de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt auth_types, wps_force_auth_types); 306de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt auth_types = wps_force_auth_types; 307de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt } 308de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#endif /* CONFIG_WPS_TESTING */ 309de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags (0x%x)", 310de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt auth_types); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, auth_types); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 encr_types = WPS_ENCR_TYPES; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_types &= ~WPS_ENCR_WEP; 322de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#ifdef CONFIG_WPS_TESTING 323de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (wps_force_encr_types_in_use) { 324de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt wpa_printf(MSG_DEBUG, 325de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt "WPS: Testing - replace encr type 0x%x with 0x%x", 326de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt encr_types, wps_force_encr_types); 327de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt encr_types = wps_force_encr_types; 328de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt } 329de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt#endif /* CONFIG_WPS_TESTING */ 330de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags (0x%x)", 331de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt encr_types); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, encr_types); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 1); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, WPS_CONN_ESS); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Association State"); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_ASSOC_STATE); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 2); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(msg), hash); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, WPS_KWA_LEN); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, hash, WPS_KWA_LEN); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain) 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pad_len; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t block_size = 16; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *iv, *data; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PKCS#5 v2.0 pad */ 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = block_size - wpabuf_len(plain) % block_size; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iv = wpabuf_put(msg, block_size); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(iv, block_size) < 0) 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = wpabuf_put(msg, 0); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(msg, plain); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_OOB 40404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, 40504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *pubkey, const u8 *dev_pw, 40604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t dev_pw_len) 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[1]; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pubkey_hash[WPS_HASH_LEN]; 41104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 4125460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password (dev_pw_id=%u)", 4135460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt dev_pw_id); 41404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt addr[0] = wpabuf_head(pubkey); 41504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hash_len = wpabuf_len(pubkey); 41604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sha256_vector(1, addr, &hash_len, pubkey_hash); 417cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_WPS_TESTING 418cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_corrupt_pkhash) { 419cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash", 420cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 421cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash"); 422cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++; 423cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 424cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_WPS_TESTING */ 42504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); 42704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len); 4285460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash", 4295460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_be16(msg, dev_pw_id); 432cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (dev_pw) { 433cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password", 434cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw, dev_pw_len); 435cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_data(msg, dev_pw, dev_pw_len); 436cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 43704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 43904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_OOB */ 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Encapsulate WPS IE data with one (or more, if needed) IE headers */ 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_ie_encapsulate(struct wpabuf *data) 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ie; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = wpabuf_alloc(wpabuf_len(data) + 100); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie == NULL) { 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_head(data); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + wpabuf_len(data); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (end > pos) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t frag_len = end - pos; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (frag_len > 251) 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt frag_len = 251; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(ie, 4 + frag_len); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(ie, pos, frag_len); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += frag_len; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ie; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4734b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4744b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4754b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidtint wps_build_mac_addr(struct wpabuf *msg, const u8 *addr) 4764b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt{ 4774b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", 4784b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt MAC2STR(addr)); 4794b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpabuf_put_be16(msg, ATTR_MAC_ADDR); 4804b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpabuf_put_be16(msg, ETH_ALEN); 4814b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpabuf_put_data(msg, addr, ETH_ALEN); 4824b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt return 0; 4834b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt} 484cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 485cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 486cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands) 487cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 488cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", rf_bands); 489cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, ATTR_RF_BANDS); 490cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, 1); 491cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_u8(msg, rf_bands); 492cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 493cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 494cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 495cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 496cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel) 497cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 498cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * AP Channel (%u)", ap_channel); 499cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, ATTR_AP_CHANNEL); 500cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, 2); 501cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, ap_channel); 502cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 503cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 504